I started answering this but it turned out to be quite long and incoherent (it is 2am here…) It is a good question and I will actually try to see if I can write something up as a response at a later time
Sure they could have been, just wrap them in
 as usual.
/me rarely uses keyword lists without them being inside a
, naked keywords look too much like arguments and are confusing until I can mentally parse it
Plus something like this would still work fine if piped into the end:
def blah(i, kw \\ , v), do: ...stuff... get_something() |> blah(42) |> blah(64, a: 1, b: 2)
Plus it would be a fairly simple matter to put naked keyword lists in any position, like:
blah(1, a: 2, b: 3, 4, c: 5, d:6, 7) -> Inferred as: blah(1, [a: 2, b: 3], 4, [c: 5, d:6], 7)
Of which also fixes the piping to end keyword thing.
/me really really hates ruby syntax
But then we’re losing the syntactic sugar and things become more complicated and unintuitive.
A common example:
DB.save record, use_transaction: true, logging: "HIGH"
DB.save([use_transaction: true, logging: "HIGH"], record)
or, if it was actually possible to omit brackets with the KW list being in the middle/front:
DB.save use_transaction: true, logging: "HIGH", record
record going at the end (whereas it reads better at the front, as
DB.save record, or
DB.delete account etc )
You can hate it all you like but you can’t ignore the fact that a huge number of people not just like it, but love it, and a significant number of people coming to Elixir came via Ruby and in no insignificant part due to the syntax’s likeliness to it
Or just pipe it, which is probably where you would get it anyway (following piping into the end):
do_stuff(42) |> Blah.changeset(params) |> DB.save(use_transaction: true, logging: "HIGH")
Or better yet, if it supported erlang property lists instead of just basic keyword lists:
do_stuff(42) |> Blah.changeset(params) |> DB.save(use_transaction:, logging: "HIGH") # Leaving out the value implies `true` in property lists, this would even be compatible with Keyword Lists if it became true at compile-time
Or better yet, if the save was partially applied with such default options (say via a, hmm, partially_apply or so at the top? Let’s name it
db_trans_save) since it is likely to be used with the same options in multiple places in the file:
do_stuff(42) |> Blah.changeset(params) |> db_trans_save()
And of course these parenthesis are entirely superfluous if the
|> binds properly:
do_stuff 42 |> Blah.changeset params |> db_trans_save
Hmm, oh wait, we just made OCaml syntax. ^.^;
A lot of people like Perl, Java, and PHP too, still does not mean they are good syntaxes.
/me did not come from the ruby world
I think it’s more along the lines of wanting to take advantage of Elixir goodies, you’ll have to dip your toes into the Elixir eco-system - and I’m not talking about becoming an Elixir convert. Though I guess there is room for improvement when it comes to “compatibility”.
But I also believe that anyone who adopts Elixir with a one language attitude is fooling themselves - there comes a point where not being able to at least read Erlang becomes a handicap. For one, a lot of the existing OTP “wisdom” is tied to Erlang and it’s eco-system.
Also Erlang/BEAM seems very aware of the need to interact with other languages/processes (NIFs, ports, C/Java/Python nodes) to “get the job done”. To me this seems to favour a polyglot/language agnostic solution approach (i.e. maybe it isn’t that big of a deal to step out of the Erlang-zone to take advantage of what Elixir has to offer).
I don’t know what’s up with the general Erlang-syntax-phobia expressed by many imperative language developers‡, I prefer it’s brevity, never having been fond of the Ruby syntax in the first place. But I have to be honest - ever since “Programming Erlang” (2007) I wanted to get acquainted with Erlang but it’s relevance from my own perspective seemed a bit “way out in left field” to justify the investment of effort and time. That changed with “Programming Elixir” (2014) which seemed much less esoteric. Should Erlang have enjoyed a wider popularity much earlier in it’s lifecycle? I think so. Could, from the Erlang perspective, the Elixir hype seem puzzling and possibly even annoying? I can empathize with that. I’m still hoping that Erlang gets a bit more exposure because of Elixir but perhaps that is being naive.
Now when it comes wishing for “static type system support” I suspect that is going to take yet another BEAM language, one that is statically typed from the ground up (I only know of Alpaca) to act as a driver - though I’m not even sure how the BEAM could be a barrier to something that seems to be largely a compile time concern.
In the end it seems important that the BEAM gets more widespread visible exposure and use in whatever way possible.
‡ The ant turd tokens serve a purpose - having problems with those just means you haven’t built the right Erlang mindset yet.
- Though I like Clojure’s “whitespace is good enough” (“commas are considered whitespace”) but I don’t go around maligning languages that rely on commas
- However beyond using whitespace as a delimiter I’m not fond of “syntactically significant whitespace” (e.g. Python blocks)
i.e. at the end of the day these are just (sometimes petty) preferences. These types of “dislikes” really shouldn’t get in the way of using/adopting effective tools (though Perl syntax does tax my tolerance).
But KW lists aren’t alway used with a pipe. I can’t really comment on the others as I don’t know enough about the lower level stuff (and why they may or may not be good feasible alternatives).
Well that just boils down to opinion and I think the key point here anyway is that a significant number (arguably the largest majority - a third in our poll) of Elixir users aren’t from those other languages but from Ruby and that in itself has brought more than just users, but ideas, talent, libraries, culture etc
Obviously Erlang plays a significant part too - and it’s precisely this marrying of the two that has led to the success we now see. It’s like what was said when Elixir was born; it’s as though Erlang and Ruby had a baby… and it wasn’t a mistake!
Entirely! The BEAM makes such a fantastic glue engine. ^.^
Yeah I think that is it too. I quite prefer erlang syntax over, say, elixir (ah if erlang had elixir-style macros, entirely doable ^.^). I think most of the fear of erlang’s syntax is it is not C-like, at least that was the issue a 1.5 decades ago I’d say. But yeah, I do get that bit of puzzling/annoying bit.
Not a barrier at all, however it does mean the JIT cannot take advantage of static type information to generate better machine code. ^.^;
Lol, true true, they have their specific functions, like
Commas are just a form of scoping, like take this convoluted example between elixir (uses commas) and ocaml (uses spacing):
# Elixir f a, (b 4, 5), c+1, d f a, b(4, 5), c+1, d
(* OCaml *) f a (b 4 5) (c+1) d
You are swapping commas for parenthesis or vice-versa (although ocaml has other scoping constructs, parenthesis is what you’d most likely use in this case). Elixir optimizes for ‘heavy’ arguments, where the arguments are often more then just a binding and are often more complex expressions. OCaml optimizes for ‘light’ arguments, where the arguments are often just a binding and where more complex expressions need to be scoped. Elixir requires OCaml-Like scoping in cases where things become ambiguous where OCaml does not have the ambiguity at all as it enforces it. Just different styles in that way.
Likewise, makes refactoring a hell.
Ah perl, the language where you can call something identically in the same place and get back entirely different results, so powerful, but holy frick it is brain draining. ^.^;
But that example would generally be. ^.^
Technically your example in pure OCaml would be like:
DB.save ~use_transaction:true ~logging:"HIGH" record
And of course you can stop at any point to partially apply it, so could do this:
(* somewhere higher *) let db_trans_save = DB.save ~use_transaction:true ~logging:"HIGH" (* in functions *) db_trans_save record
Traditional OCaml would have the use transaction and logging be optional arguments, can be left off, with the final argument(s) being the main data load.
I’m not sure where the macro’s come from though, Ruby does not have macro’s (though you can monkeypatch to hell), if not Lisp of course (that is what they are closest to by far, heck even sigils can enable a kind of scoped read-macro’s), so I’m not sure what ruby brings to elixir other than the syntax itself, which is about the only part of elixir I really really dislike for a multitude of reasons. Ignoring syntax the big main thing I’d change of Elixir is piping to last instead of first, that’d recover compatibility with the multitude of Erlang libraries, allowing them to be used in-place without needing to remake or create thousands of wrappers as Elixir has done, which makes using Erlang in Elixir significantly less popular than it would have been otherwise.
I think you are overlooking the role Ruby has played in the success of Elixir.
Even if you think it was ‘just’ syntax, it brought along a large number of Rubyists (currently over a third according to our poll and probably significantly higher at the start) who in turn brought ideas, talent, libraries, culture, friendships, proponents, authors etc. Remember, whatever it was that attracted them to Elixir from Ruby (syntax or otherwise) was precisely what was needed to entice them, to help get us where we are today.
So if you remove that, you dramatically change the path Elixir may have taken. Would it be the functional language taking the programming world by storm that we know and love today were that not the case? Arguably not…
The ecosystem of Elixir can be used from Erlang. I integrated Elixir into an Erlang project in early 2013. Sure, it required some hackery, but it was definitely doable. I remember that back at the time there was also a rebar2 plugin which allowed the same thing.
You can’t really write Phoenix specific stuff in Erlang b/c it requires features not existing in Erlang. However it should be possible (and fairly easy) to immediately delegate from controllers to a module written in plain Erlang.
For libraries which do not use metaprogramming to inject things into the client modules (e.g. postgrex, comeonin, gen_stage), it should be possible to write the client code in plain Erlang.
A few other positives that come to mind…
- A modern language for their beloved BEAM
- Lots and lots and lots of interest via this new language
- Lots of new people learning (or learning parts of) Erlang to use with this new language
- Pull requests to Erlang/OTP/BEAM
- Tools/libraries that in some cases can be used with Erlang
- Seeing the BEAM being used in areas where it was not previously ‘known’, such as embedded devices (Nerves) the web (Phoenix)
- Cool (as in ‘nice’) new people in the ‘wider’ BEAM community
There’s probably lots more
Erlang actually had a LOT of webservers, even going back well over a decade. Nitrogen/n2o was an especially fascinating one that I’d like to remake on Phoenix someday, it was a purely server-driven kind of UI interface, kind of like Drab.Live on steroids.
What foes n2o bring beyond what Drab already offers?
Thus it is obvious it is not as great a thing for mostly static sites, but for highly dynamic pages it is amazing.
Well not so much a VDom but direct commands and swaps like they are local elements. I guess it is a lot like Drab now that I’m remembering it, cool.
The examples do look like something you might do with Drab. They do not show dynamically sized lists of editable elements, which is a shame. To me, this is the real test to a dynamic UI framework (and is something I can fo trivially with VueJS).
Given that Drab is so new, I think it might hit feature-parity with n2o soon (unless something better comes aling in the meantime).
I think I actually prefer Drab.Live’s tenplates, even though it means you must write HTML, but this is suggestive. You might prefer an elixir DSL, for example. I think that the best DSL for HTML is the Pug template language, which has an elixir implementation.
The nice thing about a full elixir html-dsl is being able to do tiny piecemeal updates to the remote end without worrying about, say, wiping out an input field. ^.^
Why can’t that DSL be an EEx template?
Because those are text. The best you can do with those is what Drab.Live is doing now, parsing it out and trying to guess what goes where.
I’m sorry, I still don’t get it… If the EEx template uniquely identifies the DOM after parsing it, what would the difference be? AFAIK, Drab.Live parses the EEx tenplate into a Floki data structure, which is more or less the same thing I would use to represent the DOM defined by an elixir DSL.
First of all a vdom would be significantly more lightweight than that! ^.^;
But that is not how Drab works, it does fairly simple string munging depending on what it detects around it.
If Drab.Live eventually does do something like parse an entire template at compile-time with something like floki as it does now, then reifies that into a VDOM function that spits out changes based on old and new data, then it could become very reliable indeed, but currently it does not do that (yet?), and it would be a lot of work. ^.^;