Closed yrashk closed 12 years ago
There are a few things that is worthy considering here. Elixir is a homoiconic language and allow people to come up with their own control flow structures. While we could control what when
means inside Elixir, we cannot ensure its semantics on the outside world (nor we would like to, this is the point of being homoiconic + having macros).
Take case in Clojure, how do you know what each argument is suppose to mean and the format they must be passed? You consult the docs.
That said, I am perfectly fine with when
in comprehensions being a superset of guards and I foresee this happening in many other situations. The way to look at this is as lc
and bc
are macros that manipulates the incoming syntax tree to its own semantics, they are not keywords.
Regarding message sending, we already use !
to mean negation since Elixir introduces nil
and Erlang's only negation operator (not
) is strictly boolean.
I will go nuclear on this. As much as I understand that it is hard to make decision to change syntax, but in this case it is not about Elixir being homoiconic, but inconsistent. Big time inconsistent.
Seriously, it is a very bad defence. "We're making this inconsistent because it is possible for us to do so!". Not only we redefine what guarding is and making it confusing to outsiders, we also make it extremely confusing to Erlang developers as well. We also use guard syntax for generators in comprehensions and break the simplicity of comprehensions right at the door.
I am declaring war on this. I'll come up with examples of how this might look.
It is the best time to adjust the syntax. It will be too late to do that soon.
First two ideas:
lc a from list, a > 1, do:
lc a :: list, a > 1, do:
As per IRC discussion the plan is:
in
with inlist
and inbits
when
In support of this change:
2> Tables = [tab1, tab2, "tab3", tab4].
[tab1,tab2,"tab3",tab4]
3> put(tab1, [f1,f2]).
undefined
4> put(tab2, [f3,f4]).
undefined
5> put(tab4, [f5,f6]).
undefined
6> [ Field || Tab <- Tables, Field <- get(Tab), is_atom(Tab) ].
** exception error: bad generator undefined
7> [ Field || Tab <- Tables, is_atom(Tab), Field <- get(Tab) ].
[f1,f2,f3,f4,f5,f6]
8>
The order is important. I just encountered this issue while developing ExQL.
I think usage of 'when' in list comprehensions is plain wrong. The problem here is that when is supposed to work with a very limited set of "guard expressions", while in Erlang, list comprehensions' conditions are any boolean expressions.
In Erlang, what you have is a comma-delimited list of (|). So I think this should be solved similarly.
Now, come to think of it, use of
in
in LCs is wrong too. Other use of 'in' implies a boolean test of A in B, and this is not that, this is a generator. So, it would be natural to use some "generator" operator to signify generators.The tricky part comes from the fact that Elixir uses
<-
instead of '!' for message sending which effectively renders us unable to use it for generators. I see two solutions too this: 1) pick another operator that is as expressive 2) replace <- with ! for message sending.Thoughts?