News for hackers. Stuff that matters.
Re:Elixir for Cynical Curmudgeons by chubot on Thursday August 03, 2023 @11:52AM (#36987549)
I'm also looking at Elixir and Phoenix (coming from Python/C++), and it looks cool. Doing realtime features with Python requires something like Tornado / asyncio, which isn't ideal IMO.

I'm all for the immutable / message-passing architecture in the large, but I wish that you could just write Python-style code within processes. The VM copies all data structures at process boundaries anyway.

I think that language would be very popular!

I wrote Lisp 20 years ago, before Python, but now it feels a little annoying to "invert" all my code, for what seems like no benefit

e.g. from https://learnxinyminutes.com/docs/elixir/

    defmodule Recursion do
      def sum_list([head | tail], acc) do
        sum_list(tail, acc + head)
      end

      def sum_list([], acc) do
       acc
      end
    end
I would rather just write

   def sum_list(L):
     result = 0
     for item in L:
       result += item
     return result
But then also have the Erlang VM to schedule processes and pass immutable messages.

There is obviously a builtin in Python that does this, and I'm sure there is a better way to do this in Elixir. But I think the general principle does hold.

Re:Elixir for Cynical Curmudgeons by pythonaut_16 on Thursday August 03, 2023 @12:01PM (#36987693)
Have you seen Elixir list comprehensions?

  iex> for n <- 1..4, do: n*n
  [1, 4, 9, 16]
Or for your example:

  iex> l = 1..3 # equivalent to [1,2,3]
  iex> Enum.reduce(l, fn item, acc -> acc + item end)
  # or
  iex> Enum.reduce(l, &(&1+&2)
  # or the built in
  iex> Enum.sum(l)
  # all return:
  6
https://elixir-lang.org/getting-started/comprehensions.html https://hexdocs.pm/elixir/1.12/Enum.html#reduce/2 https://hexdocs.pm/elixir/1.12/Enum.html#sum/1

None of which take away from your point though: it's definitely a different mental model than you use for Python/Go/Javascript.

Re:Elixir for Cynical Curmudgeons by chubot on Thursday August 03, 2023 @10:00PM (#36994540)
Yes though Python has list comprehensions too :)

I should have picked a different example -- the idea I was trying to get across was that mutability within a loop is useful.

Here’s a similar question I asked with Python vs. OCaml and Lisp. Short-circuiting loops seems to cause the code to become fairly ugly in functional languages

https://old.reddit.com/r/ProgrammingLanguages/comments/puao1...

Re:Elixir for Cynical Curmudgeons by jclem on Thursday August 03, 2023 @12:05PM (#36987755)
You can reduce with list comprehensions in Elixir, but it's uncommon to see:

    sum_list = fn list ->
      for item <- list,
          reduce: 0,
          do: (sum -> sum + item)
    end

    sum_list.([1,2,3])
Other comments are correct that `Enum.reduce/2` is probably better:

    Enum.reduce(list, &(&1 + &2))
Obviously you don't have the flexibility / mutability you refer to in other comments with either of these, but you can always put more in your accumulator:

    get_sum_and_update_count = fn list, map ->
      for item <- list,
          reduce: {0, map},
          do: ({sum, map} -> {sum + item, Map.update(map, item, 1, &(&1 + 1))})
    end
(A contrived function that returns a list sum and an updated map with the count of the values found in the list)
Re:Elixir for Cynical Curmudgeons by bcrosby95 on Thursday August 03, 2023 @11:54AM (#36987584)
Built ins aside, I find most uses of recursion to be better served by Enum.reduce.
Re:Elixir for Cynical Curmudgeons by chubot on Thursday August 03, 2023 @11:57AM (#36987635)
Yeah I knew someone was going to say that (see last sentence), but a for loop is more powerful and general than reduce().

Mutability within the loop is useful, and it can be controlled by processes and message passing.

Re:Elixir for Cynical Curmudgeons by sodapopcan on Thursday August 03, 2023 @12:41PM (#36988232)
I'm not sure "powerful" is the right word here, it's more a matter of "what certain people are used to". If you want a counter or whatever, you can use a tuple to give yourself multiple accumulators. You could argue it's uglier, but I wouldn't necessarily agree. It's something that is easy to get used to if you remove the "but I'd rather just do it this way" mindset.
Re:Elixir for Cynical Curmudgeons by bcrosby95 on Thursday August 03, 2023 @12:00PM (#36987681)
I assumed you meant something like Enum.sum that completely trivializes the code. In comparison, generic, higher level functions are pretty fundamental to FP.
Re:Elixir for Cynical Curmudgeons by throwawaymaths on Thursday August 03, 2023 @02:22PM (#36989665)
the problem with a for loop is that it is inexplicit about what from the outer scope can be mutated. Which isn't a problem, for small functions but I have definitely seen monster for loops in professionally written django code with ~500 lines of code in the function.

Besides being in that magical sweet spot (executes imperatively but reads declaratively), a reduce forces you to declare ahead of time what things can be carried over and mutated between each iteration.

> it can be controlled by processes and message passing.

DO NOT DO THIS YOU WILL REGRET THIS SIMCITY MEME

Re:Elixir for Cynical Curmudgeons by mfitton on Thursday August 03, 2023 @04:26PM (#36991325)
You might want to look into Ray. It's a Python library lets you deploy actors (classes) and tasks (functions) and abstracts away the management of resources, message passing, lets you define automatic repairs, etc. that is entailed with deploying an arbitrary amount of intercommunicating processes in Python.

Admittedly, I haven't worked with Erlang or Elixir, so their solution to this might be much more usable. Ray is aimed primarily at ML use-cases, though it is quite general.

Re:Elixir for Cynical Curmudgeons by ttymck on Friday August 04, 2023 @12:57AM (#36995646)
Is Enum.reduce not sufficient? Even better, Enum.sum?

https://hexdocs.pm/elixir/1.12/Enum.html#reduce/3