Live data from Hacker News

Metaprogramming in Elixir

serokell.io

21–30 of 39 posts

Re: Metaprogramming in Elixir

#21
post #16

I think that the metaprogramming situation is a little problematic in Elixir. Elixir makes heavy use of macros in basic libraries like the Phoenix or Ecto frameworks that are used by more or less everybody. I understand that macros are useful to build a DSL for a specific project but using macros in basic libraries like this leads to "way too much magic": Trying to understand (or somehow extend) Ecto is not really po…

I agree. I was trying to learn Phoenix but had a hard time with the DSL because it was so non-functional in appearance.

Are you talking about routes or Phoenix.HTML? Those are the only two places I can think of having a DSL. Phoenix.HTML isn't strictly required and the routes look like data to me.

Re: Metaprogramming in Elixir

#22
I very rarely write macros but Elixir is much, much nicer to work with for having them.

Probably my favorite overall library in Elixir is Ecto. It's the go-to relational DB library and makes great use of macros for its query syntax DSL. The Phoenix router, controllers, etc also benefit quite a bit.

The thing that makes Elixir's macro implementation a really big win for me as a user is how explicit it is.

There is never a case of hidden magic. Just as you can see what functions are brought into a module by scrolling up and looking for the keywords "alias" and "import", you can find macros by looking for "use" and "using". This is very different from JavaScript, where another module could alter the prototype chain or overwrite attributes on any non-const object it has access to.

Re: Metaprogramming in Elixir

#23

I think that the metaprogramming situation is a little problematic in Elixir. Elixir makes heavy use of macros in basic libraries like the Phoenix or Ecto frameworks that are used by more or less everybody. I understand that macros are useful to build a DSL for a specific project but using macros in basic libraries like this leads to "way too much magic": Trying to understand (or somehow extend) Ecto is not really po…

Not sure I agree on Phoenix. There are macros, but only around plugs and routing, not much different to what you’d find in Django and definitely less magic than Rails.

Plugs are straightforward function pipelines and a declarative DSL really helps structure your routes.

The controllers and channels, which are responsible for coordinating with your domain layer, don’t really add anything in the macro department. Plus there is no inheritance, which in my opinion is the biggest source of confusion on most OO frameworks, often requiring you to chase a behavior up and down the class chain.

Re: Metaprogramming in Elixir

#24

I think that the metaprogramming situation is a little problematic in Elixir. Elixir makes heavy use of macros in basic libraries like the Phoenix or Ecto frameworks that are used by more or less everybody. I understand that macros are useful to build a DSL for a specific project but using macros in basic libraries like this leads to "way too much magic": Trying to understand (or somehow extend) Ecto is not really po…

I see this criticism a lot but I don't think it has anything to do with macros specifically and more so to do with lack of familiarity with Elixir. I've felt the same way about Django being magic because I had trouble following the class hierarchy. It makes a lot more sense now because I'm more familiar with Python and Django. But even today I'll be looking deeper at something and ask WTF it's doing. In that respect, Elixir codebases are easier to me. The module depth seems "shallower" and I don't have to disambiguate between what behavior is caused by class inheritance or an imported function.

When I first tried to use Elixir several years ago Ecto.Schema [0] seemed complex and magical, but then I came to realize it's just converting module attributes to runtime code. There is not really that much complex macro logic going on.

>This also leads to cryptic errors where you get an error in non existant lines of code.

When was the last time you used Elixir? This isn't a problem I can recall having in the last 4 years or so of using Elixir.

>following the control flow in Phoenix is like a maze because of all the macro substitutions.

Can you clarify what you mean by this? A specific case as to where this happened for you would help. Phoenix's use of macros is actually pretty light [1] except for some very low level stuff. You can even see how frequently a developer will use macros in Phoenix by searching `__using__` in the codebase [2]. It's not used as much as people think. The majority is for views and controllers and only to provide a very thin layer of support on top of your regular use of code. As an example, the "macro magic" in Phoenix.Controller is just handling some basics for giving a layout and view to Plug and handling fallback actions for exceptions. You could do the plug calls manually and I think it would be safe to not use any macros in your controller code.

Another familiarity issue with the language (and any language really) is understanding what is meaningful in a stack trace and what isn't. And the likely cause of the error in the first place. Is it syntax? Is it mistyping a variable? Is a function just used improperly? (wtf is init_p_do_apply and why does it show up in every stacktrace?) You're juggling all these different issues - learning a new paradigm, a new syntax, not knowing how to extend things. It's obviously going to be a little overwhelming and, if not strictly required, we might just pick a different language that we're more familiar with.

[0]: https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/sch...

[1]: https://github.com/thechangelog/changelog.com/blob/master/li... (not mine, I just go here to show the most frequent use of macros in Phoenix)

[2]: https://github.com/phoenixframework/phoenix/search?q=__using...

Re: Metaprogramming in Elixir

#25

I think that the metaprogramming situation is a little problematic in Elixir. Elixir makes heavy use of macros in basic libraries like the Phoenix or Ecto frameworks that are used by more or less everybody. I understand that macros are useful to build a DSL for a specific project but using macros in basic libraries like this leads to "way too much magic": Trying to understand (or somehow extend) Ecto is not really po…

Macros can be de-mystified with proper editor support. In Emacs and Lisp you can (recursively) use "macroexpand" to see what code it produces in-place. I am not an Elixir user (though thinking about hopping on), apparently there is alchemist.el[1] that lets you do that (with caveat, and the project seems dead tbh).

[1] https://github.com/tonini/alchemist.el

Re: Metaprogramming in Elixir

#26

I think that the metaprogramming situation is a little problematic in Elixir. Elixir makes heavy use of macros in basic libraries like the Phoenix or Ecto frameworks that are used by more or less everybody. I understand that macros are useful to build a DSL for a specific project but using macros in basic libraries like this leads to "way too much magic": Trying to understand (or somehow extend) Ecto is not really po…

Completely disagree with ecto[0] and plug. (I have some issues with ecto, but it has nothing to do with macros). The use of macros in those two libraries is parsimonious and exactly what you want in a DSL. For that matter ExUnit, too, has exactly the 'right' amount of macro usage. Phoenix, on the other hand, drives me up the wall.

I would not call Phoenix a "basic library". It's definitely a heavy framework. You can of course use "just Plug" (though very few people do).

Finally, I think the bigger problem is when you get devs that "take inspiration" from some of the way that Phoenix uses macros. It's a serious problem when a dev has built a macro that cleverly autogenerates a function call (so you can't search the codebase for that function to chase the call path) is not fun. This is the strategy that the Phoenix Routes (is that the right name? not to be confused with Router) uses. I hate it so much.

[0] as an ecto consumer. if you ever try to develop an adapter for ecto, you'll run into these problems. I think for example this is why it took forever for someone to build an ecto3 SQLite adapter.

Re: Metaprogramming in Elixir

#27

I really love Elixir but our company had to drop it and rewrite a few projects in Go and Ruby, was too hard hiring and the existing team preferred not to continue with it. I think the learning curve is also quite harder than it initially seems, might be why some people give up on Elixir. But nothing but respect for Elixir.

I’ve seen this a lot. The biggest reason for failure is people assume they already know everything about the VM and language. Erlang + BEAM are the most integrated pair of VM and language I know of. It’s the only VM that will preempt running processes. It’s also truly functional. A lot of really brilliant folks have written truly shit Elixir code because they underestimated the challenge. Oh you’re passing that blob…

Yes. I view Elixir kinda like 2 different languages in 1: the functional language and the process language. The process language is the most unique one though so you will probably spend more time learning that than the functional one.

Re: Metaprogramming in Elixir

#28
post #6

Earlier quoted context omitted.

I don’t know why you are getting downvoted. I think this is a valid criticism that should be discussed and not ignored. I find elixir to be quite elegant to work with but that’s just like my opinion. I guess my question is what about it gives it the steep learning curve?

It was discussed four days ago on HN https://news.ycombinator.com/item?id=27192873

Thank you for sharing this.

Re: Metaprogramming in Elixir

#29

I don't like the operators' logic in elixir. There should be one for assigning variables, one for pattern matching and there is no rebinding of variables. Could be like that: // assigning x = 1 // pattern matching x ^ 1 // pattern matching and assigning x =^ 1 And they should remove the rebinding that is useless. But I find it very difficult for that to happen at that time. Automatically translated.

[deleted]

Re: Metaprogramming in Elixir

#30
post #25

I think that the metaprogramming situation is a little problematic in Elixir. Elixir makes heavy use of macros in basic libraries like the Phoenix or Ecto frameworks that are used by more or less everybody. I understand that macros are useful to build a DSL for a specific project but using macros in basic libraries like this leads to "way too much magic": Trying to understand (or somehow extend) Ecto is not really po…

Macros can be de-mystified with proper editor support. In Emacs and Lisp you can (recursively) use "macroexpand" to see what code it produces in-place. I am not an Elixir user (though thinking about hopping on), apparently there is alchemist.el[1] that lets you do that (with caveat, and the project seems dead tbh). [1] https://github.com/tonini/alchemist.el

Macro expansion has recently been added to elixir-ls[1] and is supported via custom command in vscode extension.

[1] https://github.com/elixir-lsp/elixir-ls

Post reply on HN