Metaprogramming in Elixir

This page summarizes the projects mentioned and recommended in the original post on news.ycombinator.com

Our great sponsors
  • WorkOS - The modern identity platform for B2B SaaS
  • InfluxDB - Power Real-Time Data Analytics at Scale
  • SaaSHub - Software Alternatives and Reviews
  • ecto

    A toolkit for data mapping and language integrated query.

  • 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...

  • changelog.com

    Changelog is news and podcast for developers. This is our open source platform.

  • 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...

  • WorkOS

    The modern identity platform for B2B SaaS. The APIs are flexible and easy-to-use, supporting authentication, user identity, and complex enterprise features like SSO and SCIM provisioning.

    WorkOS logo
  • Phoenix

    Peace of mind from prototype to production

  • 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...

  • alchemist.el

    Elixir Tooling Integration Into Emacs

  • 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

  • elixir-ls

    A frontend-independent IDE "smartness" server for Elixir. Implements the "Language Server Protocol" standard and provides debugger support via the "Debug Adapter Protocol"

  • 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

  • InfluxDB

    Power Real-Time Data Analytics at Scale. Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.

    InfluxDB logo
NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts