So Joe Armstrong wrote this post a while ago making points/suggestions on what should be changed in Elixir: http://joearms.github.io/2013/05/31/a-week-with-elixir.html
I wonder was any of it taken into account? What was changed if anything?
Might be a simple macro, but Iâd love if we could use !
for sending!
I suggest that one limit the use of send/2
and instead define a proper GenServer (or other OTP behaviour), and define a public interface that is used to call the behaviour, ie.
defmodule Foo do
use GenServer
# public api ...
def increment_number(pid, value) do
GenServer.call(pid, {:increment_number, value})
end
# callback implementations ...
end
GenServer.call/2
should never get called from outside the module. The fact that the module uses a GenServer should be hidden away; an implementation detail. The âpublicâ interface should stay the same, even if we change the underlaying implementation to a GenStateMachine (see :gen_state_machine
on hex for awesomeness).
I see sending messages to process with send/2
the same way. Sometimes it is neat to send a delayed message using send_after
to the process itself, but other than thatâŠlife is better with properly defined OTP behaviours.
(Message meant to be helpful, not condescending)
I believe the biggest changes we made from the article is to support tagging the Elixir versions you support in your mix.exs
file and removing the <-
operator in favor of send/2
. Both <-
and !
for sending messages are too foreign and send/2
is more inline with spawn/1
and receive/1
(we wanted the process trinity to be all names, no operators).
I really like the idea of an extended pipe syntax (in the blog post comments):
|N>
should inject into the Nâth argument of the next function
|>
is shorthand for |0>
|-N>
injects âbackwardsâ
|->
is shorthand for last arg
This would be useful when there isnât an obvious single parameter to use as the subject for a function. Eg. def kiss(me, you)
with semantics that the kiss is cooperative and not one kissing the other (and the arguments are not interchangeable). Being able to pipe in the first or the second argument might be useful at different times.
Also, the extra ,
before the do:
annoys me too. But Iâm guessing itâs there for some good reason that I have yet to understand
Edit: After finding these discussions on the mailing list Iâm less convinced that pipe extensions are a good idea
It is because using do: <expr>
turns into [{:do, <expr>}]
as it is a normal argument. However do <expr> end
is âspecial syntaxâ (only really shared by fn
and else
that immediately come to mind), but as that is a special syntax expression block it is not a true âargumentâ, until it gets resolved back down into the same as do: <expr>
.
I explained it badly, but hopefully that shows the gist of it. ^.^
/me goes to get coffeeâŠ
Ok, but why do I have to take care of it with commas in weird places? Why leave little annoying energy sucking things in there for user to take care of?
Another thing: why cant I use same syntax for defining functions in shell and in modules? In erlang it is one of those things that sucks. And I hear its easy to fix, so why have this dichotomy? cc @josevalim
Ok, but why do I have to take care of it with commas in weird places? Why leave little annoying energy sucking things in there for user to take care of?
It is part of the language grammar. Once you understand why it is there, it should make more sense. Would you really expect languages to make small energy vampires on purpose?
And I hear its easy to fix, so why have this dichotomy?
Ask whoever told you it is easy to fix to send a pull request then.
If you are interested on those answers, I would recommend looking at the Elixir mailing lists. We have likely discussed those topics in detail in the past.
I suspect somebody not giving it enough thought, not malice. How does that comma benefit the user of the language? Help me understand please.
That would be Joe Armstrong, in the post I linked to. He also made an attempt with erl2 to make it right. Donât know what happened to it though.
You did not understand. It is not that the comma is beneficial for the user, but it is easier to remember putting that comma in after the user understood how the compiler sees the code.
In general do ... end
, is just syntactic sugar for do: ...
, which again is sugar for [{:do, ...}]
. Having this in mind I throw the comma in when necessary. I did not even realize it as an inconsistency in the language. I just use it or I use it not. But now as you began to talk about it, I still donât mind the comma but I am happy that I do not have to write [{:do, ...}]
You always use the comma to separate arguments, elements on a list, and everything else:
if some_expr?, do: call_this(), else: call_that()
The only time you do not have a comma is when you are using the do/end
construct, which was designed as syntax sugar of the construct above:
if some_expr? do
call_this()
else
call_that()
end
Notice how we lost the comma before each keyword (do
and end
) and the colon after. Even though, those constructs are equivalent. The first syntax, with the comma, is the canonical format, while the second one is a special construct where you lose all the punctuation to make it simpler to work with code blocks.
I hope this shines a light on why using the comma is the consistent approach. There should be no such thing as comma in weird places. You could ask, however, why the do/end has no commas before. That would be the correct question and it has been answered above: it is done so by design to make it simpler when working with large code blocks.
Joe has fixed it on another programming language. The solutions applied there do not necessarily map to Elixir. I would really recommend taking a look at the archives for a detailed discussion.
It is also worth mentioning âeasyâ for someone does not imply it is easy for everyone else. Specially when we are talking about Joe who has a PhD, has designed a successful language, a robust virtual machine and probably deployed software more interesting than we will in our lifetimes. Saying something is easy does not make it easy.
So Elixir is homo-iconic but pretends itâs not. Thatâs what threw me.
def/2
(link) is just a marco in the Kernel module defined as such:
defmacro def(call, expr \\ nil) do
define(:def, call, expr, __CALLER__)
end
it takes 2 arguments a call which is the name and its argumets (correct me if Iâm wrong) and the expression which as @NobbZ and @OvermindDL1 said above is a list containing a tuple of the :do
atom and an expression [{:do, <expr>}]
.
Now anyone who completely understand macros (not me), can tell with 100% confidence how the following code works
def hello(world), do: IO.puts "Hello #{world}"
If instead we removed the comma then the def macro would just not make sense, it would be irregular, an aberration of a macro.
And then in 7 years time people would be making posts on this forum asking why the def macro is different that the rest.
Plus the extra code to support that feature would make elixir more complicated, I see no value in that.
On the other hand the do end
syntax is something we agreed on since the beginning, likewise for the atom: "key"
syntax.
While being a bit âmagicalâ its clear what they are doing, so them being special is less confusing. I believe and most will agree the less magical stuff there is in a language the better one can understand it and use its features to the fullest.
It is also worth mentioning âeasyâ for someone does not imply it is easy for everyone else. Specially when we are talking about Joe who has a PhD, has designed a successful language, a robust virtual machine and probably deployed software more interesting than we will in our lifetimes. Saying something is easy does not make it easy.
Apology accepted
Sharas - please keep the tone friendly (and helpful) as outlined in our Mission Statement. Thanks!
Not cool dude
Hmm⊠iâm just curious, is homoiconicity a bad thing? I always thought itâs a good thing.
- Donât be rude. Thatâs just bad for the entire community. Be nice or go home.
- Fix it and send a PR and try to get it merged. When researching how things work youâll probably realize why itâs there. Perhaps you can fix it. If not, youâll learn a whole lot.
So you found an excuse to spit out part of that pint-up by âbe niceâ a.k.a. âbe phonyâ agression. Glad to help.
Donât take your selves too seriously, thats even better for the community.
But who are we kidding, âprotector of communityâ is yet another justification you created for your agression)
Iâm sorry you feel that way Sharas, however I completely disagree. There is absolutely no reason why you cannot be civil in a discussion even when you are at polar opposites of an argument. Thereâs simply no need for any sarcasm or rudeness in discussions when people are taking part in good faith and Iâm afraid the thread took a turn for the worst when you posted as such.
With that said I think José has answered the question and so think the thread is now best closed. Thank you everyone for taking part.