5 ms·
I've written some Erlang and found the syntax awkward. One example of this is that variables can only be bound once. This means you end up writing: Val = Som
by loftsy 4y ago
I've written some Erlang and found the syntax awkward. One example of this is that variables can only be bound once. This means you end up writing:
Val = SomeFunc()
Val1 = Func2(Val)
Val2 = Func3(Val1)
Yes I know you can use the functional style to minimise having to do this but you still end up seeing this pattern in real code.
Kubernetes has done a good job of replacing OTP.
That said I think Erlang is still an interesting language to learn just because of how different it is.
- codesnik 4y agoI personally don't find this binding once behaviour problematic in any way, but Elixir specifically addresses this (it creates another variable with the same name, though)
- holsee 4y agoI wish they didn't tbh, it makes me sad. Not allowing rebinding does provide a little bit of encouragement towards factoring things better, but I have seen manys a `X1` `X2` in my time :(
- weatherlight 4y agoits a bit of a smell, but good elixir code doesn't have to worry about rebinding for bindings in the same scope. Jose Valim goes on as to why he made that design decision from the following: https://groups.google.com/g/elixir-lang-talk/c/w83lKZs4YS8/m/rFeb3Env-6YJ https://groups.google.com/g/elixir-lang-talk/c/w83lKZs4YS8/m... I will post the same answer from before: I like the explicitness of pattern matching. In Elixir, as soon as I see ^foo, I know I am matching. If there is no ^, I know the previous value regardless if it there is one or not, will be discarded. If pattern matching is not explicit, I always need to know if a variable was previously defined or not to know what is going to happen. To me this behaviour is non negotiable. In my experience, it is more likely to run into accidental matches than into accidental rebindings. Another possible limitation to the suggestion above can be related to macros. Let's suppose you have a macro that stores a value in a hygienic variable: defmacro do_something(a, b) do quote do var!(hello, Hygienic) = calculate_something(unquote(a), unquote(b)) end end Someone may call this macro multiple times but we always care about the last value of hello. If we make a distinction in between being assigned once and then multiple times, the macro simply won't work. Or the macro developer would need to work around this behaviour by inspecting the environment or we would need to provide some sort of functionality that does it for you. Maybe this behaviour could be built-in in var! or maybe we'd need to introduce something like: defmacro do_something(a, b) do quote do set!(hello, Hygienic) = calculate_something(unquote(a), unquote(b)) end end We can see how this is getting complex: 1. Use = to define variables 2. Use ^ for pattern matching 3. Use := for rebinding 4. Use set! in macros when you don't care if a variable was previously defined or not It is also interesting to point out that the := operator won't work for rebinding inside clauses. For example, how would you make the rebinding below explicit? x = true case false do x -> :ok end Of course, there are interesting consequences for making a distinction in between defining and rebinding a variable by introducing something like the := operator. We could have better control of the scope to provide better warnings or even make it easier to implement imperative for loops: x = 0 for i <- 1..5 do x := x + i end x #=> 15 But the fact Elixir have different ways for variables to be introduced in the scope, adding more rules can make the overall system very complex.
- kaptainscarlet 4y agoWhy do you need the extra variables when you can pass function expressions into other function calls?
- loftsy 4y agoIt just turns out you can't always do that in a real codebase. For example see here: https://github.com/apache/couchdb/blob/23efd8e5b1aa96ef01640fec03a5fedc945ba8b9/src/couch_mrview/src/couch_mrview_http.erl#L228
- holsee 4y agoSounds like a good old foldl may or may not have brightened up your day (with the "functional style" you mentioned) e.g. Pipeline = fun(Functions, Initial) -> lists:foldl( fun(Function, Acc) -> Function(Acc) end, Initial, Functions ), Initial = SomeFunc(), Pipeline = [Func0, Func1, Func2, Func3], Result = Pipeline(Pipeline, Initial). At a certain point I grew to not mind the punctuations `; , .` I often miss language itself given how verbose things are in elixir by comparison. The language ecosystem is pretty good with LFE for the Lispers https://lfe.io/ https://lfe.io/ and https://gleam.run/ https://gleam.run/ for the OCaml inclinded.
- weatherlight 4y agoseems more complicated than the following elixir code. Val |> SomeFunc() |> Func2() |> Func3()
- holsee 4y agoI agree, or a nice `with` clause. When strict simplicity is not the ultimately goal dare I say leaning into the monads is the way...
- davidjfelix 4y ago> Kubernetes has done a good job of replacing OTP. I feel like this statement alone demonstrates a wild misunderstanding of what OTP does and is. Kubernetes is at best a replacement for VM-level scheduling, but without a slew of additional functionality and application-level interaction with the kubernetes runtime, individual servers are basically running blind in a container, totally unable to do anything that OTP provides to gen_servers for free.