Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Elixir v1.6 released: code formatter, dynamic supervisors, and more (elixir-lang.org)
341 points by josevalim on Jan 17, 2018 | hide | past | favorite | 39 comments


I'm really excited about the code formatter. I'm glad more and more projects are following Go's lead on this.

How was the default style decided? And very importantly, what's the forum for users to bikeshed endlessly about how it should be different?

More seriously, as someone who's literally updating a bit of code to use a :simple_one_for_one supervisor right now - is the new DynamicSupervisor more about naming, so people understand it better, than semantics? I was under the impression that :simple_one_for_one, :rest_for_one, etc, were all standard erlang OTP supervisor strategies and that Elixir mostly deferred to them. Is it still using the same erlang semantics under the hood?

Oh, and edited to add: does that mean using `:simple_one_for_one` with a `Supervisor` is now deprecated? If so, what's involved in transitioning to the new approach?


>is the new DynamicSupervisor more about naming, so people understand it better, than semantics?

It is mostly about naming, the semantics are the same. The DynamicSupervisor has a new feature called max_children that Erlang doesn't but that's it.

> Oh, and edited to add: does that mean using `:simple_one_for_one` with a `Supervisor` is now deprecated? If so, what's involved in transitioning to the new approach?

It will be eventually, probably on v1.8. Good question about transitioning. We should have some docs on that. I will work on it.


Just adding for others who might not have been aware otherwise:

> A `.formatter.exs` file can also be defined for customizing input files and the formatter itself

https://github.com/elixir-lang/elixir/blob/master/lib/mix/li...


While it's clear that a std formatter is a big win (I absolutely love elm-format), I'm somewhat afraid of this sort of change. Stuff like line length isn't only a personal preference, changing the width e.g. from 80 to 100 would seriously "break" my IDE window layout. At the same point, making it configurable would decrease the benefit of OneTrueStandard. Definitely a tough decision either way.


I think having something is way better than nothing.

I too like 80 max chars since it lets me fit 3 side by side code windows. From what I gathered this is configurable at a project level.

To me it seems like a huge step up from having to use a tricked out rubocop/flake8 config to detect issues while you have to manually fix them.

Just knowing I never have to deal with formatting again because Jose and gang put a crazy amount of effort into ensuring it does the right thing is really nice.


80 character max also fits nicely with the 4-6 inch column width for optimal readability.


I love the formatter but sometimes I arrange macros with uneven spacing to align categories of things in columns. It would be nice to have sections where you could disable the formatter.


You can have a .formatter.exs file where you'd specify input files for the formatter. You can't exclude files but you can achieve the same this way.


Agreed! I've always found formatting debates to be quite silly. Good to see that the community just enforces one format. How did it work out for the Go people? Some probably grumbled at first and then got used to it.


Go had the advantage taht the formatter came along very early in its usage. That meant that there wasn't an existing installed base of people with entrenched formatting ideas, so comments have mostly been positive about consistent code everywhere rather than complaints.


It might be a small thing, but I am most excited about @defguard. I find that splitting a function to match on different inputs and using guards creates elegant, clear, and maintainable code, but if a guard statement is too large, that effect is diminished and I fall back to `if` or `case`. @defguard allows me to stick to the more elegant (in my opinion) solution.


For those interested in some of the thought-process of defguard check out Chris Peele's gist of his development process:

https://gist.github.com/christhekeele/76c3e37cb9082274f52f79...

While not the final spec per his PR, a really good look at the internals nonetheless.


You can follow my development even further—the lingering question in that gist is how to expand the guard code to see if it is valid in a guard.

I tried my hand at a pure-Elixir guard expansion in an earlier PR, documenting my thoughts as I went: https://github.com/elixir-lang/elixir/pull/5854

After José gave me some direction in response to that, I produced the ultimate PR: https://github.com/elixir-lang/elixir/pull/5857

It simply relies on calling the :elixir_expand.expand function that the compiler uses, with a guard context—so the defguard implementation is always up-to-date with what the compiler allows in guards. Waaay more elegant than munging AST myself.

Funnily enough, the tests I wrote for defguard actually uncovered some missing assertions in that function. Some invalid expressions would make it past that step and return a different error much deeper in. It's kinda cool I indirectly contributed to the compiler.

I took on the feature mostly because over 4 years ago I'd made a gist to do exactly that, minus the validation, and when I found the issue on github for it, it gave me a lot of pleasant closure to get it merged in! https://gist.github.com/christhekeele/8284977/revisions#diff...


+1 very welcome addition for exactly the reasons you have outlined.


Some extra stuff I've been working on to supplement the the formatter in your workflow a bit:

Pre commit hook: https://github.com/jasongoodwin/elixir-mix-format-pre-commit...

Emacs format current file: https://github.com/jasongoodwin/emacs-elixir-formatter

Generally the formatter is good, but we've noticed a couple cases where it would be nice to override

EG:

it would be nice to have the join and on statements on the same line so you can see as the reader what relates to what

  u in Db.User,
  distinct: u.id,
  join: c in Db.Comment,
  on: u.id == c.user_id,
  join: p in Db.Profile,
  on: u.profile_id == u.id,
  join: x in Db.SomethingElse,
  on: x.profile_id == u.id,
  join: y in Db.AnotherThing,
  on: y.profile_id == u.id,
...

I can see why it's like that, but it would be nice to be able to override it.

Also the formatter requires () so you end up with ecto code differing from the styles recommend in the docs

  schema "thingy" do
    field(:name, :string)
    field(:abbreviation, :string)
  end
instead of

  schema "thingy" do
    field    :name,         :string
    field    :abbreviation, :string
  end
Anyway, still useful and good for the team.


> it would be nice to override

One of the big advantages I have experienced from the Golang formatter is that you cannot configure it, period. This took me a little bit off getting over myself, but eventually the fact that every single Golang codebase adheres to these rules is so nice. Plus you don't have to think about it, ever.

In this case I think it would be best if Ecto just recommends the new default style in their docs.


That's fair - thanks for the comment. It makes sense - then there are no opinions or variation so "this is the way" and all code looks like that.


> Emacs format current file: https://github.com/jasongoodwin/emacs-elixir-formatter

Would it be possible to have that be trivially configurable to hook into save-buffer? That would seem to be the cleanest way to use it.


I was thinking that too and had actually created a ticket for it https://github.com/jasongoodwin/emacs-elixir-formatter/issue... . I'm relatively new to elisp and this was a good way to jump in a little deeper - I'll try to tackle this soon. Publish it somewhere etc. I save on navigate away so that would be ideal for me too. I'll try to make that change shortly. Or feel free to make a pr.


Ecto can export a .formatter.exs file that says you don't need parens for those calls.


But that would apply ecto's style across whole codebase and for some function names this wouldn't be handy (see https://groups.google.com/d/msg/elixir-lang-core/xTduV3KZvfY... )


For people wondering about what Elixir and the BEAM are offering, for a quick overview of the best features of this stack see [this talk]( https://www.youtube.com/watch?v=pO4_Wlq8JeI ).

If anyone starts learning Elixir now: I can recommend using VSCode with ElixirLS extension. Also: pragprog books, Sasa Juric's book. If you like video tutorials I've heard good things about PragDave's course.


I guess you mean Elixir in action - its manning and not pragprog.


Yes, and I do recommend all of pragprog elixir books and manning's elixir on action.


defguard/defguardp is a really welcome addition that should improve lots of normal code. Planning on using it in a refactor today. Great to see improvements like this.


Just in time for a start of a new proj. Huge thanx to everyone who contributed the maturity of tooling and attention to developer productivity is amazing and puts many established languages to shame.


Been looking forward to this since your keynote at ElixirConf. Love the direction the language is evolving towards, and the emphasis on improving ease of use and better tooling.


This is fantastic! Easily most excited for the code formatter - it should make it easier for new users of the language to pick it up based on seeing others code.


thanks for everything you do jose, looking forward to getting our hands on it.


I wonder why go doesn't have it's elixir, yet.


I'm not entirely sure what that would exactly mean, but I can think of two answers, one philosophical and one technical:

(1) Philosophically, Erlang borrows a lot from Prolog while Elixir borrows a lot from Ruby. For some programmers (dilettantes like myself included), that relative familiarity is a fairly big win. Go doesn't have the same "weird syntax" drawback; it's pretty easy for anyone familiar with C-like languages to pick up the basics virtually on sight.

(2) Technically, Elixir is another language for the Erlang VM, like Scala and Clojure are other languages for the Java VM. But Go doesn't have a VM; its compiler produces native code. So there's no way to produce something that's strictly comparable. You could write a preprocessor that translates an entirely new syntax into Go, but that wouldn't be Go's Elixir, it would be Go's CoffeeScript.


> Go's CoffeeScript

As someone terrified of lower level languages (I'm a somewhat JR dev, used to working with fun things like Python, Ruby, Elixir and JS) this would kind of be really nice. Mostly maps.


There are some languages that transpile to Go:

Have: http://havelang.org/ with generics

Godzilla: https://github.com/jingweno/godzilla ES2015 to Go

I didn't try any of them, nor Go itself.


good news, elixir is a such a joy to use.


Sorry for asking here, but if I wanted to learn Elixir, do I need to know Erlang?


No. You can start learning elixir and you'll learn about how the BEAM works on the way. You'll also eventually learn about Erlang/OTP libraries and probably that's when you'll start reading basic erlang code but that should come (mostly) naturally. I included some tips in another comment here.


Ah thanks.


A very good place for elixir questions is https://elixirforum.com/ community is super friendly and you will often get questions answered by core team members or even Robert Virding (one of the Erlang creators).


Is this code formatter roughly equivalent to format document in c#/VS?




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: