3 ms·
I picked up Elixir and LFE (Lisp Flavoured Erlang) at the same time. I prefer Lisps, and so I stuck with LFE, so my knowledge of the current state and capabilit
by eggy 9y ago
I picked up Elixir and LFE (Lisp Flavoured Erlang) at the same time. I prefer Lisps, and so I stuck with LFE, so my knowledge of the current state and capabilities of Elixir is lacking.
Robert Virding who co-created Erlang, created LFE. He responded to Jose Valim in 2013 in a LFE vs Elixir thread [1].
I was accused of spreading misinformation when I made the same point recently on HN in another Elixir thread [2].
So my question is: Does Robert Virding's point still hold about Elixir's macros only able to use its predefined syntax, and not create new syntax like a Lisp can. I like Elixir, I just prefer Lisp's syntax. However, if Elixir is making these type of improvements I may want to revisit it, and to ensure I am not repeating old, incorrect information.
Robert Virding uses this example (look at the thread for context):
>> (defmacro kl
>> ((list* k v rest) `(cons (tuple ',k ,v) (kl ,@rest)))
>> (() ()))
>> which I can use
>> (kl a (+ 2 7) b 6) ==> (#(a 9) #(b 6))
Can Elixir do this or not?
Thanks!
[1] https://groups.google.com/forum/#!topic/lisp-flavoured-erlang/ensAkzcEDQQ
[2] https://news.ycombinator.com/item?id=14390916
- CoderPuppy 9y agoYes, sorta. The point I think he was trying to make was that Lisp's syntax is less restrictive, but that seemed to get confused by: - mentioning the some people say it has no syntax (which it definitely does have) - saying macros can create new syntax (which they can't in Lisp) Elixir macros are approximately the same as Lisp macros (apart from not being able to take a variable number of arguments). This is a straight port of that macro into Elixir: defp kl_i([k, v | t]) do quote do [ {unquote(Macro.escape(k)), unquote v} | unquote kl_i t ] end end defp kl_i([]), do: quote do: [] defmacro kl(l), do: kl_i l # usage IO.inspect kl [a, 2 + 7, b, 6] # => [{{:a, [line: 16], nil}, 9}, {{:b, [line: 16], nil}, 6}] Note: Elixir's syntax does get in the way a bit here, the `a` and `b` are converted into nullary calls, you could use a different escaping function to fix this defp escape_key({v1, v2}), do: {escape_key(v1), escape_key(v2)} defp escape_key({:{}, pos, els}) when is_list(pos), do: {:{}, pos, Enum.map(els, &escape_key/1)} defp escape_key(els) when is_list(els), do: Enum.map(els, &escape_key/1) defp escape_key({sym, pos, nil}) when is_list(pos), do: Macro.escape sym
- eggy 9y agoI sort of get it. But this part he writes in the discussion seems to hold, no? "What I mean here is that elixir has a predefined syntax. It has a number of predefined syntactic constructs, operators and function calls. And while I can with macros change the meaning of the constructs I cannot add new constructs or operators as the handling of macros is done after parsing. So if I want to add something completely new it ends up syntactically being a function call. Now elixir has many ways of disguising function calls at the end of the day they are syntactically still function calls. For example parentheses around arguments are optional, there is special syntax for property lists where the keys are all atoms, special syntax for using these property lists as function arguments, special handling of do ... end when it is a function argument, etc. Elixir's uniform abstract syntax makes it easier to work with these but I am still limited by only having the existing syntax."