Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> My hypothesis is that you discovered that this syntax allowed an elegant, unifying structure to the internal implementation

Your hypothesis is almost right. The important bit is that it is not about an internal structure, it is about a public structure that is accessible to macros. It is about the language AST.

Before there was syntax, I had defined I would like to have Lisp-style macros in Elixir. For that we need to have a regular syntax because when you are composing AST nodes you don't see keywords.

As an example, imagine you have code generation where you may generate a function called `add` and we treat `def` as a keyword. You would do something like:

    quote do
      def add(x, y)
        x + y
      end
    end
Now let's say the function may be public or private. You would try to write it like this:

    kind = :def # or :defp 

    quote do
      unquote(kind)(add(x, y))
        x + y
      end
    end
And now the parser would be unable to parse the code above because there is no longer a `def` or `defp` keywords where the parser would know it could skip the `do` bit. Therefore having an uniform syntax means you can generate and transform code without worrying about special cases, without evaluating strings and without resorting to special functions/methods for dynamic code definition. You can just compose code!

I also believe this matters a lot to the end-user, positively, for two reasons.

1. Consistency. The language is consistent and you can extend it in a consistent fashion. For example, Elixir code is written inside modules. `defmodule` is not a keyword, it is an identifier as any other in the language:

    defmodule MyModule do
    end
We also have defprotocol, which is implemented as a macro, and looks exactly the same:

    defprotocol MyProtocol do
    end
If we made defmodule a keyword, we would put ourselves into a corner as we would either have to make defprotocol a keyword too (for consistency) or have defmodule and defprotocol looking slightly different (causing confusion).

2. The second reason is that enabling such AST macros allows us to extend the language in different and interesting ways you can't do cleanly with other languages. One example I like to give in talks is the assert macro in our ExUnit test framework:

    assert foo == bar
Different to many unit test frameworks, we don't need `assert_equal`, `assert_more_than` and friends. As a macro, `assert` navigates the AST, which is quite uniform, and extract information from the code.

Another example I gave at my talk at ElixirConf is that we could even extend language constructs like our for comprehensions. Someone can implement a `parallel` macro that transforms a regular for comprehension into one that runs in multiple Elixir processes (leveraging multicore):

    parallel for user <- users do
      fetch_user_data(user)
    end
This only works if parallel can look at the code and transform it in multiple ways.

TLDR: The unifying syntax is an important part of Elixir macro system which brings consistency and provides an extensible foundation to the language that can be leveraged by its users.



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

Search: