Home / Blog Menu ↓

Learning Elixir, part 2

Continuing on with working my way through the Elixir introduction. I’m trying to figure out how to keep this from taking forever (especially since I’m only doing this in little bits of free time here and there), so there’ll be a bit less commentary than last time.

Binaries, strings, and charlists

I love that you can use ? to show the code point in front of a character literal. (Not that ord("a") or "a".charCodeAt(0) is all that harder.)

Pattern matching on binaries and bitstrings is good.

Keyword lists and maps

I like being able to use atoms as the keys in keyword lists and maps. It’s a small thing, but it’s nice.

Ooh, do-blocks are just syntactic sugar. (Apparently I really like it when control flow statements are just special syntax on top of lower-level constructs like keyword lists.)

Modules and functions

Okay, like in Rust, modules are named in code (with defmodule) rather than named implicitly by whatever the containing file is called. I think I like that it’s explicit.

I don’t think I’ve seen private functions specified by changing the function definition keyword (def to defp in this case). Usually what I’ve seen is a separate keyword (private) or private-by-default (Rust) or capitalization change (Go) or mere convention with underscores (Python). Cool.

Ooh, guards on function definitions. I like this. Function overloading++. (Har har.) I know you can get the same behavior with conditional statements in a single function body, and that’s probably less verbose, but still. This seems easier to reason about.

Function capturing is interesting. I guess it’s needed because the parentheses in function calls are optional.

Default arguments with \\. Huh. Moving things up to a function head if there’s more than one default argument is also interesting. Brings back the old C/C++ days with header files.

Recursion

Guards on function definitions: great for recursion. I like being able to separate out the base/termination case like that.

I think multiple function clauses might be clearer than Enum.reduce for writing reduce algorithms. (Though I do like having the function at the end with Enum.reduce — in JavaScript, it feels like the initial value is often harder to see when it’s at the end after the function body.)

Enumerables and streams

Being able to map/reduce on ranges is nice and is something I wish more languages had. (I’ve had to do this in JavaScript a couple times recently.)

The famed pipe operator at last! Looking forward to using it in practice, since it does seem like it makes chains of function calls easier to understand.

Streams look nice.

Processes

Okay, so these are kind of like lightweight threads, similar to goroutines in Go. That makes more sense (referencing my questions in the last post). I like the send/receive syntax a bit more than Go’s channel syntax, too.

Ooh, the after timeout! I really like that that’s built in.

The docs on linked processes make it sound like you build your own supervisors in Elixir, which sounds amazing. Can’t wait to learn more about that. (I’ve always used external processes like supervisord.)

This bit about sending messages to and from processes being the normal way to maintain application state? That’s really intriguing — something I haven’t really seen before. (At least not from the perspective of being built in to the language.) Looking forward to seeing what this looks like in practice.

IO and the file system

The names of File.cp_r/2 and File.rm_rf/1 make me irrationally happy. Especially given the danger of the latter. Ha.

Oh interesting, files are processes under the hood. Beginning to suspect this may be an everything-is-a-process type language. Which is new to me and very interesting.


Okay, we’ll stop there for now. Halfway through the introduction!