Live data from Hacker News

Why Elixir (2014)

theerlangelist.com

51–59 of 59 posts

Re: Why Elixir (2014)

#51
post #20

Earlier quoted context omitted.

Elixir is very easy to learn. I suppose at the end of day you would be spending more time designing your architecture rather then language.

I disagree that Elixir is easy to learn, the syntax ok, it's weird compared to most OO languages, but actually using OTP is a real paradigm shift that requires a totally different way of thinking about issues. I did not find that easy at all. The other issue is that Elixir and Phoenix have become joined at the hip in the same was as Ruby and Rails, and Phoenix didn't click with me at all, coming from the JVM world I…

Your web server, database connections, http clients would be the ones leveraging OTP here. In my talks, I usually cover the design of the connection pool and how it guarantees bugs in the pool bring all connections down with it, without leaking resources.

Ideally, developers should be able to use Phoenix for simple applications without caring about the low-level OTP details. That's how we tried to structure the Phoenix book: the classic MVC and then the OTP stuff. But it seems we still have more work to do in this area. :)

Re: Why Elixir (2014)

#52
post #37
post #8

I really am in awe of Elixir. I think it's an amazing language, and it introduced me to Erlang and OTP. I've come from using scala actors, and I can do more in way less time, less memory, and similar performance if I use Elixir. That said, there are some things that suck so hard about it. The log messages suck. If I want to use them in production and actually ship them to ELK or similar, the format really sucks. Gett…

How do you handle operating system signals? like when your autoscale group decides to scala down and you get a SIGTERM with some time to handle it, what do you do? This might help: from the release notes to Erlang R20 (i.e. latest): A new event manager to handle a subset of OS signals in Erlang It's documented in the docs for kernel here: http://erlang.org/documentation/doc-9.0-rc2/lib/kernel-5.3/d... You can write y…

This is brilliant, I can't believe I missed it! Thank you

Re: Why Elixir (2014)

#53
post #8

I really am in awe of Elixir. I think it's an amazing language, and it introduced me to Erlang and OTP. I've come from using scala actors, and I can do more in way less time, less memory, and similar performance if I use Elixir. That said, there are some things that suck so hard about it. The log messages suck. If I want to use them in production and actually ship them to ELK or similar, the format really sucks. Gett…

This is very good feedback and show flaws in areas that could be improved. Thank you! I will add some comments below but they are not meant to dispute your claims but to find places where we can improve. > The log messages suck. If I want to use them in production and actually ship them to ELK or similar, the format really sucks. Do you mean the Logger messages? Their format is customizable. Can we make this clearer?…

José, thanks for taking the time to respond to my somewhat rambling comment. To be honest, if I had a clear idea on how to solve some of these things I would have done it - but i'm still a novice at the otp ecosystem in general.

Maybe it's easier for me to walk through what I do, so I can show you where I run into problems. One of my favourite ways to learn a new language is in a REPL. I've used a lot of them in the past, and iex is pretty good. Pry (in ruby) is probably the gold standard.

  Interactive Elixir (1.5.0) - press Ctrl+C to exit (type h() ENTER for help)
  iex(1)> 1 / 0
  ** (ArithmeticError) bad argument in arithmetic expression
      :erlang./(1, 0)
This is pretty good. Now we can move on to pry

  [1] pry(main)> 1 / 0
  ZeroDivisionError: divided by 0
  from (pry):1:in `/'
The beauty here is it's saying the same thing, but the information is slightly more precise and it tells me clearly that the function being executed came from (pry) which makes a load of sense to someone using pry. I know this is a basic example, but in elixir, as you start spawning more and more processes, deciphering the log messages gets harder.

back to iex

  Task.async(fn -> 1 / 0 end)
  ** (EXIT from #PID) evaluator process exited with reason: an exception was raised:
      ** (ArithmeticError) bad argument in arithmetic expression
          :erlang./(1, 0)
          (elixir) lib/task/supervised.ex:85: Task.Supervised.do_apply/2
          (elixir) lib/task/supervised.ex:36: Task.Supervised.reply/5
          (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
  
  
  07:34:45.847 [error] Task #PID started from #PID terminating
  ** (ArithmeticError) bad argument in arithmetic expression
      :erlang./(1, 0)
      (elixir) lib/task/supervised.ex:85: Task.Supervised.do_apply/2
      (elixir) lib/task/supervised.ex:36: Task.Supervised.reply/5
      (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
  Function: #Function
      Args: []
This is scary. Why's it repeated? why does one have a timestamp? how does "lib/task/supervised.ex:85: Task.Supervised.do_apply/2" get here ? I called Task.async which doesn't show in the messages?

I want to reiterate at this point that it's not that bad, I think the repl is pretty good but the error messages just leave a bit to be desired. Maybe there is an article on deciphering them? But if you need that, I'll say it's a barrier.

In terms of the formatter, I need to go through my old code to remember where all those particular hurdles were, but someone has suggested a prebuilt json formatting logger which sounds good to me.

A sweet spot for Elixir (for me) is queue processing, in an autoscale group on AWS. So I have a real application in mind, and I originally knocked it up with hardly any knowledge and using genstage for back-pressure etc. in a couple of nights. This is saying a great thing about the language. But then shipping logs, deployment, debugging (if i deploy with distillery it locks up, and it has slow memory leak that makes no sense to me), dockerising, handling autoscale events have all stopped it from going to production ready.

> Where would you expect to find this information? Did you see `mix run` at all? Maybe in the escripts page we should point to `mix run` as it seems an `escript` is really not required in your case?

A guide on https://elixir-lang.org/getting-started/introduction.html would be great, to just give the different options and when you'd use them. Maybe something like "The anatomy of an elixir application" (or program because application is overloaded).

For me it is the cyclic journey through the different ways to do things. So it took a while to work out that I can't just pass in command line parameters to mix run, so the application gets them. Unless i'm wrong?

In escripts I can. And they will start the application automatically. Why would I use them? And what's the difference between them and running mix run lib/script.exs?

So then I started thinking - maybe the ideal way is to have an application running in the --no-halt way like you've described and have an escript connect to it to pass in configuration changes. But i'm just hacking different ways rather than learning from an example or best practice. I'd love config to be changeable on the fly for a daemon / application.

> Which kind of information do you need? (re: run time vs compile time)

in my limited experience, config.exs pulls in config params at compile time. I thought it would happen at run time because it's a script (exs). I know phoenix has a way of dealing with this, but i haven't gone fully down that rabbit hole yet, because I'm not even sure if config.exs is right for my requirements. If I want it to be hot loaded, I'm thinking I need a genserver with the config as its state, and some way to communicate changes to it - either from the file system or an escript.

> Those particular error message were fixed in Elixir v1.5

Thank you, it sounds like a great release

I'll open that issue, and check out your new book too because I really think there are huge gaps between

1) I can write genservers and get that

2) I know the tradeoffs and best structure for my supervision tree (especially with things like OS signals thrown in the mix)

3) I can deploy this into production

4)

5)

6) I can leverage distributed features

Re: Why Elixir (2014)

#54
post #8

I really am in awe of Elixir. I think it's an amazing language, and it introduced me to Erlang and OTP. I've come from using scala actors, and I can do more in way less time, less memory, and similar performance if I use Elixir. That said, there are some things that suck so hard about it. The log messages suck. If I want to use them in production and actually ship them to ELK or similar, the format really sucks. Gett…

We use https://github.com/rentpath/ex_json_logger to make logs nicer for consumption by ELK and the like.

pro tip, thanks

Re: Why Elixir (2014)

#55
post #35
post #8

I really am in awe of Elixir. I think it's an amazing language, and it introduced me to Erlang and OTP. I've come from using scala actors, and I can do more in way less time, less memory, and similar performance if I use Elixir. That said, there are some things that suck so hard about it. The log messages suck. If I want to use them in production and actually ship them to ELK or similar, the format really sucks. Gett…

> The error messages. Holy hell. What actually caused a pattern match to not work? what is it expecting? Elixir 1.5 has introduced improved messages for pattern matching errors in function clauses: https://github.com/elixir-lang/elixir/blob/v1.5/CHANGELOG.md...

This is really great. Maybe it's been working for me recently and I didn't realise.

Re: Why Elixir (2014)

#56
post #52
post #37

Earlier quoted context omitted.

How do you handle operating system signals? like when your autoscale group decides to scala down and you get a SIGTERM with some time to handle it, what do you do? This might help: from the release notes to Erlang R20 (i.e. latest): A new event manager to handle a subset of OS signals in Erlang It's documented in the docs for kernel here: http://erlang.org/documentation/doc-9.0-rc2/lib/kernel-5.3/d... You can write y…

This is brilliant, I can't believe I missed it! Thank you

If you hadn't mentioned it, I wouldn't have gone researching it and then finding legocia's 2017 comment to a 2010 StackOverflow thread where he says that perhaps a pull request involving an "event manager for signals" might make it into R20.

So, you're welcome...and thank you for getting me to look :-)

Re: Why Elixir (2014)

#57
post #53

Earlier quoted context omitted.

This is very good feedback and show flaws in areas that could be improved. Thank you! I will add some comments below but they are not meant to dispute your claims but to find places where we can improve. > The log messages suck. If I want to use them in production and actually ship them to ELK or similar, the format really sucks. Do you mean the Logger messages? Their format is customizable. Can we make this clearer?…

José, thanks for taking the time to respond to my somewhat rambling comment. To be honest, if I had a clear idea on how to solve some of these things I would have done it - but i'm still a novice at the otp ecosystem in general. Maybe it's easier for me to walk through what I do, so I can show you where I run into problems. One of my favourite ways to learn a new language is in a REPL. I've used a lot of them in the…

Stacktrace entries for emulator calls are coming on Erlang 21: https://github.com/erlang/otp/pull/1478

This means that something such as 1/0 should include the line where the error happened in IEx and in general.

Regarding the error messages, the reason why you have two reports is because there are two processes failing! The task fails, leading to the logger report, and then it causes the evaluator process to fail, causing it to be report an error as well.

Regarding configuration, it is not at compile time, but the config.exs itself is read when the escript is built. You can change it at any time though by calling Application.put_env, so there is no need for a GenServer. I know exactly where to improve the docs for this one.

Thanks for the feedback! I think I have an idea on how to improve many of those. I will do some of that and get back to you later.

Re: Why Elixir (2014)

#58
post #27

Earlier quoted context omitted.

I know it's probably not the answer you're looking for, but you can learn a lot by just reading the code of popular Elixir libraries, such as Ecto, Phoenix, etc. Error messages have gotten better in Elixir 1.5 The whole ecosystem is actually getting better with each release. For shipping to production I use 'distillery'. You create a 'release' and you can even instruct it to read some arguments from the env vars. But…

> You create a 'release' and you can even instruct it to read some arguments from the env vars. That's my main complain about Elixir. Releasing and configuring at runtime is a huge pain. I honestly don't see any value in this whole "compile time configuration". If it's at compile time, I can put it in the code. What I call configuration is things I can change at runtime. The fact that something that is a given in any…

Yep, I think there should be some included Config behaviour module which handles the serialising / deserialising of a config file, and genservers can register themselves against it, and when the config changes the registered genservers get terminated and restarted gracefully.

I don't think it's very much work - but everytime i try to build something like this I go down this path of trying to work out exactly what the architecture should be like.

Maybe it's a config application you include in extra_applications. How would you tell it the format of the file? How could you do validations?

And then maybe do an escript or similar for configuring it on the fly - something like "elixir_set "

Re: Why Elixir (2014)

#59
How's LFE in comparison? I don't hear as much about it, but I suspect (don't know why), that its closer to Erlang, any comparison with Elixir?
Post reply on HN