As mentioned earlier, releases was the last planned feature for Elixir. We don’t have any major user-facing feature in the works nor planned. I know for certain some will consider this fact the most excing part of this announcement!
This is a very important part of the Elixir developer experience. Even though the language is relatively young and we get a new minor version every six months, Elixir doesn’t feel like a moving target. This comes from having extensibility designed in from the start, as well as being built on a very mature platform (Erlang) where most of the new language blues have been worked out.
I’m still impressed by the confidence it takes to say, “Nope, no plans to add anything else right now.”
This is the biggest mistake they’ve made, honestly.
The core team continually shoots down little features and additions to the standard library, with the tired refrain “Don’t worry, the community will offer libraries for it!”.
This means we are still missing things like:
conversion of basic Elixir and Erlang types back and forth (ref <-> string, record <-> map, etc. etc.)
strftime
timezone/tzdata out of the box
various data structure helpers
various math routines
CSV parsing
JSON parsing
(You can bet that the pet features for developing, say, a compiler or macros were of course included and exposed early.)
“Batteries included”, even with occasionally corroding batteries, is better for devs everywhere. Other than the fact that we’ve all seen what happens when you have a small standard library and let the community “grow” it (cough npm cough), the fact remains that the only reason Elixir is possible is because of the baroque standard library afforded by Erlang/OTP. They bootstrapped the language using everything the other folks had, and then have the audacity to claim that they want a “small” language.
This would be maybe acceptable if they, say, wrapped the Erlang stuff with better docs and minor Elixir affordances–instead, the standard answer is to just link against Erlang/OTP directly and provide no support and pat themselves on the backs for a job well done.
It’s a position that I think is increasingly suggesting that a fork of Elixir is required.
I’ve never found this to be an impediment. When I needed time functions, I brought in Timex; for JSON, Poison; etc. I’ll admit that I did write a library containing a data structure helper. I don’t have strong opinions whether these features should be part of or separate from the core libraries, but I never found them missing when I needed to use them.
But that’s opinion. On a more factual level, I don’t know what you’re on about when you say that Elixir didn’t wrap and improve many OTP modules. GenServer, Supervisor, Application, Process, Node, the list goes on. Things like DynamicSupervisor and Registry are Elixir-specific but feel like natural extensions to OTP. There’s always the option to call into Erlang if something is not in Elixir, but that isn’t the default.
Good point, I should’ve given more credit to GenServer’s wrapper, and some various other ones. Buuuut…
There’s always the option to call into Erlang if something is not in Elixir, but that isn’t the default.
That’s the thing, though! Where are the wrappers for the math module (basic trig stuff? For the ETS? DETS? Mnesia? SSL? gen_tcp? Random number generation? Crypto? gen_fsm or gen_statem? timer?
The blessed answer is: do it in Erlang. For any non-trivial usage you pretty much have to have know the chunks of the Erlang stdlib in addition to Elixir.
Fair, I should have chosen a word other than “default”. But I have a non-trivial service written in Elixir (15K LOC, 20K lines of tests) and my calls into the Erlang std lib amount to :timer.sleep (which Elixir now provides with Process.sleep), :math.pow, :crypto.strong_rand_bytes, and :erlang.monotonic_time. I’m ok if the Elixir project gets around to wrapping these last.
What would the “dumb” wrapper over Erlang libraries provide that it would be worth it? Is there anything? Because if not, then I believe that creating such wrapper (especially in stdlib) is pointless.
As I said, the first one will change as soon as Erlang will implement EEP 48 (uniform documentation store). The second one is a little bit more problematic, but I do not see it as a big problem as Erlang functions often do not end in long pipelines.
Well, first, it would move Elixir to being independent of Erlang. Right now Elixir is basically just the super bonus DLC expansion for the BEAM–you still need Erlang to play. Wrapping those things makes it easier to make a cohesive language that doesn’t have Erlang weirdness just sticking out of it. This in turn makes it easier to add native extensions to make Elixir code more performant and even more of a value-add over Erlang.
Second, a lot of the functions (say, :math.exp) have weird failure modes that just aren’t documented. There’s no guard clauses or type information provided to keep them from throwing up. Elixir wrappers could improve error reporting and also documentation about things like valid domains for the functions.
Third, you assume “dumb” wrappers–I’m in support of slightly more invasive wrappers that do things like prefer UTF8 binaries to charlists or that are easier to pipeline or offer better options.
Well, first, it would move Elixir to being independent of Erlang
I agree, it would be great to have Elixir as a simple Erlang library, just like lfe or luerl.
Elixir wrappers could improve error reporting
It does:
iex> :math.exp(%{})
** (ArgumentError) argument error
(stdlib) :math.exp(%{})
iex> :math.exp(1111111111111111111111111111111111111111111111111111111111111111111111111111111111111)
** (ArithmeticError) bad argument in arithmetic expression
(stdlib) :math.exp(1111111111111111111111111111111111111111111111111111111111111111111111111111111111111)
vs:
> math:exp(111111111111111111111111111111111111111111111111111111111111111111111111111111111).
** exception error: an error occurred when evaluating an arithmetic expression
in function math:exp/1
called as math:exp(111111111111111111111111111111111111111111111111111111111111111111111111111111111)
> math:exp([]).
** exception error: bad argument
in function math:exp/1
called as math:exp([])
So it is transforming all calls to more “Elixirish” exceptions.
Yes, the Erlang documentation about types could improve a little, but it is still quite readable now:
A collection of mathematical functions that return floats. Arguments are numbers.
invasive wrappers that do things like […] offer better options
Just for your information, Erlang’s prop list [a, {b, 10}] is exactly the same as [{a, true}, {b, 10}] which makes [:a, b: 10] exactly the same as [a: true, b: 10]. So I do not see much of the problem there.
You’re missing the obvious: why is that number invalid as an argument? Elixir could give that information in the error, or even better restore proper IEEE754 support.
Or, you know, you could port that to the Erlang and return proper error message from there. It is not that hard. Why Elixir should fix Erlang issues while you can fix them in Erlang?
conversion of basic Elixir and Erlang types back and forth (ref <-> string, record <-> map, etc. etc.)
You have ref_to_list/1 in :erlang module or you can use inspect/1 from Elixir Kernel. But why anyone would like to call that function in situation other than inspecting the value? For record <-> map you have Record module. What other types you would like to convert? Especially as Erlang and Elixir uses exactly the same types.
timezone/tzdata out of the box
As this require HTTP requests and other stuff to keep it in sync with tzdb I think the current approach with allowing external libraries to register themselves as tzdb providers is the best one. This allows enough flexibility without requiring wrapping or incompatible date time types.
various data structure helpers
various math routines
Which one? What is missing from :math?
CSV parsing
JSON parsing
Please no, there is no need for such cruft in the stdlib and external libraries have hell lot of advantages over built-ins.
Erlang stuff with better docs
Erlang docs are pretty good, but require some time to get used to it. Maybe ti will improve in near future when Erlang implement EEP 48.
But why anyone would like to call that function in situation other than inspecting the value?
Let’s say you are using refs as a performant key for nodes in a scene graph, and you also want clients on other platforms to be able to interact with them.
This allows enough flexibility without requiring wrapping or incompatible date time types.
Everybody just uses Lau’s tzdata. This flexibility is just overengineering. In 2019, there is no reason to treat downloading tzdata as beyond the ken of a stdlib.
Please no, there is no need for such cruft in the stdlib and external libraries have hell lot of advantages over built-ins.
There’s nothing more annoying than using modules that have identical support for JSON but decide to use their own Super Extra Special representation that is mutually unintelligible. Further, both Ruby and Python have supported CSVs and JSON out of the box for a while now.
Most people using Erlang in the next 5 years will be doing Elixir. Of those, 90% or more are probably doing webshit. As it stands, Elixir is not good at that use case.
Let’s say you are using refs as a performant key for nodes in a scene graph, and you also want clients on other platforms to be able to interact with them.
Then use :erlang.term_to_binary/1 instead. It will be faster and IMHO easier.
In 2019, there is no reason to treat downloading tzdata as beyond the ken of a stdlib.
Unless you need to update tzdata without updating whole runtime.
decide to use their own Super Extra Special representation that is mutually unintelligible
That is why Jason for example is tested against JSON Test Suite to match RFC in 100%.
Further, both Ruby and Python have supported CSVs and JSON out of the box for a while now.
And most of the people are using external libraries anyway as default implementations are known to be slow and sometimes buggy. So why implement something that will not be used anyway?
Speaking of “cruft”, how about that asn1 support in core erlang?
This is needed for crypto and snmp applications as Erlang do not use OpenSSL ASN.1 implementation. In fact Erlang use OpenSSL only for ciphers, nothing else. Also AFAIK there is now trend to remove things from the “core” Erlang in favour of external libraries.
You are free to go. I like languages with minimal, yet useful, standard library. Throwing everything in just for sake of “convenience” isn’t the best way, especially when you accidentally make wrong decisions or inefficient implementations (ex. WEBrick or Python HTTP server).
This is a very important part of the Elixir developer experience. Even though the language is relatively young and we get a new minor version every six months, Elixir doesn’t feel like a moving target. This comes from having extensibility designed in from the start, as well as being built on a very mature platform (Erlang) where most of the new language blues have been worked out.
I’m still impressed by the confidence it takes to say, “Nope, no plans to add anything else right now.”
This is the biggest mistake they’ve made, honestly.
The core team continually shoots down little features and additions to the standard library, with the tired refrain “Don’t worry, the community will offer libraries for it!”.
This means we are still missing things like:
strftime
(You can bet that the pet features for developing, say, a compiler or macros were of course included and exposed early.)
“Batteries included”, even with occasionally corroding batteries, is better for devs everywhere. Other than the fact that we’ve all seen what happens when you have a small standard library and let the community “grow” it (cough npm cough), the fact remains that the only reason Elixir is possible is because of the baroque standard library afforded by Erlang/OTP. They bootstrapped the language using everything the other folks had, and then have the audacity to claim that they want a “small” language.
This would be maybe acceptable if they, say, wrapped the Erlang stuff with better docs and minor Elixir affordances–instead, the standard answer is to just link against Erlang/OTP directly and provide no support and pat themselves on the backs for a job well done.
It’s a position that I think is increasingly suggesting that a fork of Elixir is required.
I’ve never found this to be an impediment. When I needed time functions, I brought in Timex; for JSON, Poison; etc. I’ll admit that I did write a library containing a data structure helper. I don’t have strong opinions whether these features should be part of or separate from the core libraries, but I never found them missing when I needed to use them.
But that’s opinion. On a more factual level, I don’t know what you’re on about when you say that Elixir didn’t wrap and improve many OTP modules. GenServer, Supervisor, Application, Process, Node, the list goes on. Things like DynamicSupervisor and Registry are Elixir-specific but feel like natural extensions to OTP. There’s always the option to call into Erlang if something is not in Elixir, but that isn’t the default.
Good point, I should’ve given more credit to GenServer’s wrapper, and some various other ones. Buuuut…
That’s the thing, though! Where are the wrappers for the math module (basic trig stuff? For the ETS? DETS? Mnesia? SSL?
gen_tcp
? Random number generation? Crypto?gen_fsm
orgen_statem
?timer
?The blessed answer is: do it in Erlang. For any non-trivial usage you pretty much have to have know the chunks of the Erlang stdlib in addition to Elixir.
Fair, I should have chosen a word other than “default”. But I have a non-trivial service written in Elixir (15K LOC, 20K lines of tests) and my calls into the Erlang std lib amount to
:timer.sleep
(which Elixir now provides withProcess.sleep
),:math.pow
,:crypto.strong_rand_bytes
, and:erlang.monotonic_time
. I’m ok if the Elixir project gets around to wrapping these last.What would the “dumb” wrapper over Erlang libraries provide that it would be worth it? Is there anything? Because if not, then I believe that creating such wrapper (especially in stdlib) is pointless.
The biggest advantages I can think of:
|>
pipelinesBoth are “nice to have” as opposed to “essential”, but it adds up.
As I said, the first one will change as soon as Erlang will implement EEP 48 (uniform documentation store). The second one is a little bit more problematic, but I do not see it as a big problem as Erlang functions often do not end in long pipelines.
Well, first, it would move Elixir to being independent of Erlang. Right now Elixir is basically just the super bonus DLC expansion for the BEAM–you still need Erlang to play. Wrapping those things makes it easier to make a cohesive language that doesn’t have Erlang weirdness just sticking out of it. This in turn makes it easier to add native extensions to make Elixir code more performant and even more of a value-add over Erlang.
Second, a lot of the functions (say,
:math.exp
) have weird failure modes that just aren’t documented. There’s no guard clauses or type information provided to keep them from throwing up. Elixir wrappers could improve error reporting and also documentation about things like valid domains for the functions.Third, you assume “dumb” wrappers–I’m in support of slightly more invasive wrappers that do things like prefer UTF8 binaries to charlists or that are easier to pipeline or offer better options.
I agree, it would be great to have Elixir as a simple Erlang library, just like
lfe
orluerl
.It does:
vs:
So it is transforming all calls to more “Elixirish” exceptions.
Yes, the Erlang documentation about types could improve a little, but it is still quite readable now:
Just for your information, Erlang’s prop list
[a, {b, 10}]
is exactly the same as[{a, true}, {b, 10}]
which makes[:a, b: 10]
exactly the same as[a: true, b: 10]
. So I do not see much of the problem there.You’re missing the obvious: why is that number invalid as an argument? Elixir could give that information in the error, or even better restore proper IEEE754 support.
Or, you know, you could port that to the Erlang and return proper error message from there. It is not that hard. Why Elixir should fix Erlang issues while you can fix them in Erlang?
You have
ref_to_list/1
in:erlang
module or you can useinspect/1
from ElixirKernel
. But why anyone would like to call that function in situation other than inspecting the value? Forrecord <-> map
you haveRecord
module. What other types you would like to convert? Especially as Erlang and Elixir uses exactly the same types.As this require HTTP requests and other stuff to keep it in sync with tzdb I think the current approach with allowing external libraries to register themselves as tzdb providers is the best one. This allows enough flexibility without requiring wrapping or incompatible date time types.
Which one? What is missing from
:math
?Please no, there is no need for such cruft in the stdlib and external libraries have hell lot of advantages over built-ins.
Erlang docs are pretty good, but require some time to get used to it. Maybe ti will improve in near future when Erlang implement EEP 48.
Let’s say you are using
ref
s as a performant key for nodes in a scene graph, and you also want clients on other platforms to be able to interact with them.Everybody just uses Lau’s
tzdata
. This flexibility is just overengineering. In 2019, there is no reason to treat downloading tzdata as beyond the ken of a stdlib.There’s nothing more annoying than using modules that have identical support for JSON but decide to use their own Super Extra Special representation that is mutually unintelligible. Further, both Ruby and Python have supported CSVs and JSON out of the box for a while now.
Speaking of “cruft”, how about that asn1 support in core erlang?
~
Most people using Erlang in the next 5 years will be doing Elixir. Of those, 90% or more are probably doing webshit. As it stands, Elixir is not good at that use case.
Then use
:erlang.term_to_binary/1
instead. It will be faster and IMHO easier.Unless you need to update tzdata without updating whole runtime.
That is why
Jason
for example is tested against JSON Test Suite to match RFC in 100%.And most of the people are using external libraries anyway as default implementations are known to be slow and sometimes buggy. So why implement something that will not be used anyway?
This is needed for
crypto
andsnmp
applications as Erlang do not use OpenSSL ASN.1 implementation. In fact Erlang use OpenSSL only for ciphers, nothing else. Also AFAIK there is now trend to remove things from the “core” Erlang in favour of external libraries.You and I clearly want different things from our programming languages. This is why a fork is needed–folks like us aren’t going to reach a compromise.
You are free to go. I like languages with minimal, yet useful, standard library. Throwing everything in just for sake of “convenience” isn’t the best way, especially when you accidentally make wrong decisions or inefficient implementations (ex. WEBrick or Python HTTP server).