News for hackers. Stuff that matters.
Re:Lovely Week with Elixir by biggestlou on Wednesday May 20, 2020 @02:58PM (#23250440)
I learned Elixir a few weeks ago as a quarantine self-improvement project and pretty much loved it. There are some warts, as in any language. As someone who's primarily worked in Go and Java in the past and has also been learning Rust I don't super love the optional typing thing, and I end up missing higher-level data constructs like interfaces and traits.

But there are some great language features, like guards and pattern matching, that are hard to give up when you go back to other languages.

Plus it's great to have OTP goodies like GenServer at your fingertips if you run into performance bottlenecks (which you may not!). The OTP APIs are a bit weird coming from other languages but not too bad.

Other things I've liked:

1. Ecto is simply the best DB library I've encountered in any language. I'd almost recommend learning Elixir just to be able to use Ecto.

2. Plug provides great HTTP ergonomics highly reminiscent of Go's context-based middleware approach. Having direct access to the full request/response lifecycle is a win.

3. Phoenix is nice because it's essentially just Plug with some convenient helpers on top. Strikes a really nice balance between configuration and convention by letting you use only what you need. Haven't tried LiveView as I'd prefer to handcraft my own JS but probably worth a shot.

4. Absinthe is the best GraphQL framework I've encountered after many others in other languages left me completely cold.

Re:Lovely Week with Elixir by ch4s3 on Wednesday May 20, 2020 @03:20PM (#23250655)
> 1. Ecto is simply the best DB library I've encountered in any language. I'd almost recommend learning Elixir just to be able to use Ecto.

It's interesting, people always talk about Phoenix, which is nice, but Ecto is really special. I often recommend it to anyone who is feeling burned by Active Record implementations.

Re:Lovely Week with Elixir by i_s on Wednesday May 20, 2020 @10:24PM (#23254255)
I thought so too, at first, but now I'm really down on it. Ecto Changesets work fine for flat data, but when you have to deal with nested data, it becomes a nightmare, because you have to use these special functions to read and update the data. Doing that in a nested context just gets really clunky, especially coming from Clojure, where I would just do something trivial, like

    (assoc-in changeset [:children 1 :title] "New title")
Re:Lovely Week with Elixir by sooheon on Thursday May 21, 2020 @12:18AM (#23254750)
Clojure sets an unfairly high bar for data manipulation with core, transducers, libraries like supdate and specter.
Re:Lovely Week with Elixir by ch4s3 on Thursday May 21, 2020 @10:02AM (#23258442)
That is indeed a bit of a pain point. From what I understand, it's a bit intentional and the library authors want you to prefer flatter data structures. Now of course not all structures CAN be flat so you can hit a bit of an impedance mismatch. However, I think Ecto is amazing for more common (for me at least) cases.
Re:Lovely Week with Elixir by pmontra on Thursday May 21, 2020 @12:51AM (#23254904)
Having worked for years with both Ecto and Ruby's ActiveRecord I really prefer ActiveRecord. It's less flexible but so much easier to use. Ecto is somewhat closer to SQL and still suffers from the "I have to relearn how to do SQL in yet another language" syndrome and it's a particularly difficult case of it. A lot of boilerplate to represent database tables and a lot of not obvious code to do easy queries. Definitely the part of Elixir I like less, by a large margin. Ecto and the deployment system are what stop me from using Elixir in my personal projects.
Re:Lovely Week with Elixir by sgadimbayli on Thursday May 21, 2020 @04:08AM (#23255941)
I have a huge dislike to ActiveRecord because its high abuse rate.

Beginners will most certainly will have highly inefficient start with it.

There are others in Ruby world which needs more praise such as Sequel and ROM(which is what Hanami uses also).

With Rails having the monopoly and most gems having AR as dependency, it's hard to see where we will go regarding ORMs in Ruby world.

Re:Lovely Week with Elixir by ch4s3 on Thursday May 21, 2020 @10:57AM (#23259111)
I can definitely see where this criticism comes from. There is a lot of extra data description, and an abstraction that leans towards SQL.

However, that "boilerplate" makes data access and return values super clear. It also allows you to segregate Ecto queries by domain, meaning in a User context you may only have access to certain fields, whereas in a data processing context other fields may be available. This is great for coarse table access control, and you get it almost for free. It also allows you to very easily validate data at the edges of the system.

As for the query language, I can say for sure that there's a learning curve but it's close enough that your 1st guess is usually correct in my experience, and it removes a lot of foot guns like n+1 queries by default.

TL;DR there's some learning curve and extra LOC to write, but you get a lot in return.

Re:Lovely Week with Elixir by dpeck on Wednesday May 20, 2020 @04:43PM (#23251542)
Changesets are beautiful. And they're great for general structure validation outside of databases as well.
Re:Lovely Week with Elixir by ch4s3 on Wednesday May 20, 2020 @05:09PM (#23251828)
Oh yeah, absolutely. They're great for building API clients.
Re:Lovely Week with Elixir by lindgrenj6 on Wednesday May 20, 2020 @03:01PM (#23250475)
Check out the Elixir "protocol" feature, it's similar to interfaces: https://elixir-lang.org/getting-started/protocols.html
Re:Lovely Week with Elixir by QuinnWilton on Wednesday May 20, 2020 @03:06PM (#23250523)
Protocols + the Typeclass library [0] makes for some of the most extensible Elixir code I've worked with.

[0] https://github.com/witchcrafters/type_class

Re:Lovely Week with Elixir by sb8244 on Wednesday May 20, 2020 @07:34PM (#23253279)
Hi Elixir friend! Have you done a blog post on this by chance? I'd be really interested in reading one.
Re:Lovely Week with Elixir by QuinnWilton on Wednesday May 20, 2020 @07:41PM (#23253333)
I haven't, but the creator of the library (Brooklyn Zelenka / @expede) has given a few excellent talks that reference her libraries. This is a personal favourite: https://www.youtube.com/watch?v=JD0FJTmuV_Q
Re:Lovely Week with Elixir by biggestlou on Wednesday May 20, 2020 @04:41PM (#23251523)
I've used protocols, and they are useful as a kind of bare minimum interface/implementation abstraction. But they're nowhere even close to something like Rust traits. Which is totally fine given Elixir's goals.
Re:Lovely Week with Elixir by AlchemistCamp on Wednesday May 20, 2020 @05:54PM (#23252364)
I'm pretty deep into Elixir and have been learning a bit of Rust on the side this year, so this is interesting. Could you elaborate a bit?
Re:Lovely Week with Elixir by Grimm1 on Wednesday May 20, 2020 @03:03PM (#23250493)
I was just about to say, protocols fill the interface slot pretty well
Re:Lovely Week with Elixir by skeletal88 on Wednesday May 20, 2020 @04:58PM (#23251715)
Interesting. I really like Python and SqlAlchemy. Changing objects in the database via changesets and applying them on top of eachother feels kinda alien, when I can't do object.property = something.

The thing that confuses me most about Phoenix and Elixir is how do I actually deploy the application to production? I have my own server where I can run whatever I want (running Ubuntu), so what do I have to do to get my Phoenix application working there? How do I get my code running as a systemd service?

Re:Lovely Week with Elixir by dnautics on Wednesday May 20, 2020 @05:10PM (#23251834)
Doing object.property = something is, I think a mental anti-pattern because it engenders uncertainty about which source of information holds the truth (local object or database), and now you have a needless (mental) distributed state problem. At least in a system with bare structs and changesets, especially in an immutable language, there's no ambiguity about the fact that your data are stale the minute you drive it off the dealership lot and your data synchronization events must pass through a single explicit point of entry. Explicit is better than implicit, after all.

To answer your second question, that's not entirely easy to answer, but I personally use mix release command, ship it to s3 as a tar.gz, then pull it down into the server, unzip, put the command line entry point "start" (there are instructions when you do mix release) into a systemd service, and it's good to go. Couldn't be easier. It takes us several ansible scripts, and annoying wrangling with virtualenvs if something goes wrong for us to create a new Ubuntu Django server from scratch and literally two commands (one is a 5 line shell script) to get Elixir up and running.

Re:Lovely Week with Elixir by ch4s3 on Wednesday May 20, 2020 @05:14PM (#23251872)
1. It's a functional thing, it's quite nice after you use it for a bit, and really powerful because you can use it for any data, and not just when working with a DB.

2. There are several ways. You can use releases [1]; copy the code to the box, run mix release, then ./app start, and point whatever you want to that process. If you're running phoenix you could always compile it on the box and just run mix phx.server. I wouldn't do that though. You could also use a tool like distillery[2] which is kind of like releases. There is another more esoteric option where you build locally without the runtime, but I wouldn't recommend that.

[1] https://elixir-lang.org/getting-started/mix-otp/config-and-r...

[2] https://hexdocs.pm/distillery/tooling/cli.html

Re:Lovely Week with Elixir by joeyspn on Wednesday May 20, 2020 @05:33PM (#23252048)
+1 for distillery, very convenient...

https://github.com/bitwalker/distillery

Re:Lovely Week with Elixir by losvedir on Wednesday May 20, 2020 @06:17PM (#23252628)
Once `mix release` was added natively to Elixir in 1.9, I haven't found the need to use distillery anymore. Is there still a use case?
Re:Lovely Week with Elixir by ch4s3 on Wednesday May 20, 2020 @11:00PM (#23254416)
Distillery has 2 strong use cases; it has config providers which allow for a lot of config flexibility and it can support hot code upgrades.
Re:Lovely Week with Elixir by lawik on Wednesday May 20, 2020 @06:18PM (#23252637)
I like to deploy using Releases as detailed here (https://hexdocs.pm/phoenix/releases.html).

This gives you folder packaged with everything you need to run the application on the architecture you compiled it on. Very straight forward.

If you want to set it up to be a systemd service I guess it would be like any other binary command for systemd. I usually run things under something like Supervisor (http://supervisord.org/)

Re:Lovely Week with Elixir by pmontra on Thursday May 21, 2020 @01:00AM (#23254952)
We use distillery in a project I've been working on for a few years. I know other people that build a docker container and deploy it. Weird for the OTP ecosystem but it works.

By the way how do you deploy Python code? There isn't a standard AFAIK.

Finally, check how systemd handles rabbitmq. It's an Erlang application and you could run and stop your application in the same way.

Re:Lovely Week with Elixir by depr on Wednesday May 20, 2020 @05:18PM (#23251911)
Re:Lovely Week with Elixir by ch4s3 on Wednesday May 20, 2020 @05:43PM (#23252206)
I would strongly caution anyone new to the language against using edeliver. There are a lot of gotchas and edge cases with the scripts that can really bite you. It's super cool if it just works, but miserable if something breaks.
Re:Lovely Week with Elixir by derefr on Wednesday May 20, 2020 @03:33PM (#23250800)
> I don't super love the optional typing thing

It might not be a plus if you're writing a web-app, or some other kind of easily-restarted "shared-nothing business layer" system. But get deep-enough into absorbing the Zen of Erlang (i.e. by trying to write a big-deal telecom system; or by working on a distributable Erlang DBMS like CouchDB), and you'll come to appreciate it. Specifically, you'll realize that it'd actually be impossible for the Erlang runtime system to support hot-code-reload plus automatic distribution plus static typing, all at once. One of them has to give. (I think this is one of those universal "choose only two properties" triangles, like CAP, though I don't think this one has a name.)

If you have a "living" distributed system—one that you don't bring down entirely for each upgrade—then inevitably you'll hit a situation where a node with the fresh new version of a module (V3, let's say), tries to use that module to send a V3 message to a node that is still only running V2 of the module. In a distributed system with static typing, that'll inevitably crash the V2 node—unless you did a whole extra "V2.5" rollout step to first teach V2 about the wire-format of V3 and how to handle it.

Much of the point of Erlang/Elixir's user-facing "data architecture" design—e.g. using partial destructuring pattern-matching (unwrapping tuples one layer at a time) instead of uniquely tagging messages with message-type UUIDs like COM/CORBA—is to "automatically" cope with this, allowing your "living" distributed system to interoperate in the face of cross-node module-version heterogeneity, without having to write explicitly backcompat "also recognize the previous/next version of the message" code during the rollout period.

Every Erlang term sent in a message is, in some sense, like a little extensible file-format; and the tools you're given to "parse" the term—when you use them idiomatically—give you forward-compatible "parsing." As long as you don't validate that a term has a specific "deep" structure corresponding to some static type, then it doesn't matter if your module-V2 actor has actually received—and is now holding onto—a module-V3 parameter in its state. It won't know what to do with it, but nor will that cause any problems as long as it doesn't poke too hard at it. It can even keep hold of it, storing it away for later in its state generically, without understanding exactly what it's received. It'll be there in the state for when the module upgrades to V3, and suddenly cares about that property.

(OTP's supervision system also comes into play here, ensuring that any unhandled edge-cases of this term "parsing" just become temporary restarts of the leaf-actors that receive them, without affecting the stability of the node as a whole. The network upgrade completes; the affected actors come back up running the new module version; the system continues.)

Re:Lovely Week with Elixir by brokencode on Wednesday May 20, 2020 @04:28PM (#23251376)
That’s all true, but I think a Typescript-like system would work really well here. Typescript is very tolerant of the data being different than the type definition, and it doesn’t know or care if your data actually matches the type definition at runtime.

It would be up to the developer to account for different versions of the data when writing out type definitions, and the worst case is that you try to access a property that doesn’t exist or is the wrong type, and it crashes and causes the process to get restarted like what already happens in Erlang.

So it wouldn’t be a guarantee of correctness just like Typescript isn’t, but it could still offer a lot of safety assuming you get the type definition a right.

Re:Lovely Week with Elixir by derefr on Wednesday May 20, 2020 @04:50PM (#23251635)
I mean, that's already what Erlang/Elixir has, in the form of Dialyzer, a runtime "type linter" (which is what the typespecs in the article feed into.)

It's static typing that Erlang can't complete-the-triangle on; not typing generally.

The only problem is that "offline" type-checking like this does nothing to solve one of the main use-cases/pain-points where Erlangers want types (or, at least, think they want types): in the messages that actors receive. You can't make any sort of a type assertion about what other actors in the system are allowed to send this actor, and get that validated; because "other actors" in a distributed system necessarily include ones that aren't even part of your present codebase!

I have a philosophy about this—not sure where I picked it up, but I think it hews to the Zen of Erlang quite well:

If you already know the type of a message, then by definition, it's not a message any more, but just a regular data value. A message is an OOP concept (and Erlang is an OOP language, where processes are the "objects.") An OOP "message" is a piece of data the meaning of which is up to the interpretation of the recipient; where that interpretation can change as the recipient's internal state changes. The whole point of the "receiving a message" code that you write in an Erlang actor-process, is to allow you to do custom logic for that interpreting part. To use the value itself, in making the decision of what the value is.

In fact, I would extend that: the whole point of Erlang as a language is to do that "interpreting" part. Once you know what something is and have put it into a canonical validated structure, you may as well hand it off to native code (using e.g. https://github.com/rusterlium/rustler). If you think of native code as being a pure domain of strongly-typed values, then picture Erlang as the glue that lives in the ugly world of "not yet typed" values, making decisions under partial-information conditions on what types to try to conform received messages into, before they can enter that pure strongly-typed domain. That's Erlang's idiomatic use-case! (You can tell, because using it for that produces absolutely beautiful code; whereas using it to do e.g. crypto math, produces an abomination.)

Which is all to say: the interpretation (or, if you like, constraint) of a message into a typed value is a Turing-complete operation; and the logic for doing so is best represented as an Erlang program. Erlang doesn't need a type system for messages; Erlang is a type system for messages. :)

Re:Lovely Week with Elixir by macintux on Wednesday May 20, 2020 @10:42PM (#23254333)
It’s a bit of a stretch, but your thoughts reminded me of one of Joe Armstrong’s interests, how to document/prove two components were adhering to the protocol they were using to communicate (he was describing the problems of interconnecting two hardware components in the informal talk I attended, but obviously he had a significant interest in software as well).

I miss Joe quite a bit. Such a keen mind with seemingly infinite curiosity.

Re:Lovely Week with Elixir by pmontra on Thursday May 21, 2020 @01:15AM (#23255039)
> A message is an OOP concept (and Erlang is an OOP language, where processes are the "objects.")

Yes. If only GenServer had an OOP syntax instead of a handle this / handle that list of functions which obfuscate what the process actually does. Elixir in particular lost a chance to make it easier to deal with.

Re:Lovely Week with Elixir by dnautics on Thursday May 21, 2020 @03:30AM (#23255750)
It's not too late. You can write your own wrapper around the :gen module, and if it's really good maybe people will adopt it.

I will say one thing:. If you are thinking of BEAM processes as actors/(Kay objects), you're missing the real meat of what makes BEAM processes special; what they really are are atomic units of failure domains. The other stuff is just a useful analogy that lets people grok the code structure by comparing it to something familiar. The trouble then is that people will take habits from OO and apply them to BEAM where blindly copying the organizational form will lead to performance regressions. If you're treating BEAM processes like python or Java or Ruby objects, you're going to bottleneck your system and turn it into a needlessly complex mess.

In short, not all function calls (cheap) should be message passing (expensive). Sorry Alan Kay.

Re:Lovely Week with Elixir by pmontra on Thursday May 21, 2020 @08:50AM (#23257758)
We have very few GenServers in our system, with their supervisors to keep them alive and read back the initial status from the db in case of failure. They're not object in the Ruby or Python or Java way. They really are servers that take care of a specific action. The vast majority of code is function calls in the main process of the system. Still I'd like to be able to program the GenServer in a more understandable way.
Re:Lovely Week with Elixir by dnautics on Thursday May 21, 2020 @12:49PM (#23260885)
Yes. Genserver is quite frankly a mess. I just want to discourage pushing that object metaphor. Have you seen the Dave Thomas ornery video where he calls a genserver a dog's breakfast?

https://youtu.be/6U7cLUygMeI

Re:Lovely Week with Elixir by izelnakri on Wednesday May 20, 2020 @04:31PM (#23251416)
You’ve just summarized my thoughts on Elixir after using it(and still loving it) for years. Thanks :)
Re:Lovely Week with Elixir by 52-6F-62 on Wednesday May 20, 2020 @04:17PM (#23251258)
I've been meaning to do this for so long and I've started at least twice but other work or life have gotten in the way. And I haven't gotten any "quarantine-time" as my industry has been busy!

It's good to hear this, though. I might have to try and re-prioritize learning it again.

Do you have any good resources on hand that you used and would recommend?

Re:Lovely Week with Elixir by dnautics on Wednesday May 20, 2020 @04:59PM (#23251722)
Actually I think the one place where elixir community is relatively lacking is online long form tutorials. There is some fantastic content on YouTube. I quite like plangora for intro stuff and knowthen for more advanced content.