Re-implementing apply in Elixir

Note: This article is part of a series working through the exercises in Brian Marick's "Functional Programming for the Object-Oriented Programmer", in Elixir instead of Clojure. The full notes and source code are on GitHub.

Elixir already has a perfectly good apply . But FPOO suggests I try to write my own version, and why not?

This is considerably more verbose than the Clojure example in the book, without really seeming to add much expressiveness:

Perhaps an Elixir-experienced reader can show me a more idiomatic form. Although I think Elixir metaprogramming is likely always going to be wordier than Lisp because of a) its less-concise quoting/unquoting constructs; and b) the fact that the sexp-ish things that Elixir macros work on under the covers are more complex than their lisp counterparts. As an example, here’s the code-as-data version of adding two integers:

Whereas the lisp code-as-data representation of (+ 1 2) is, well… (+ 1 2). Though to be fair, that big ugly keyword list in the middle is optional metadata. The most minimal representation is:

…which is not that much bigger than the lisp version.

Actually, that gives me an idea. Let’s see if we can do this by constructing sexps instead of with quoting and unquoting.

This is a lot shorter. It feels kind of like working with secret knowledge though. The Elixir sexp representation is so different from ordinary written code that it’s hard to look at code that constructs code in this way and visualize what it’s building.

Here are the tests, just to prove this all works.

Here I’m using the new capture operator, introduced in 0.11.0, to capture an anonymous function reference to Kernel.+/2:

Believe it or not, this is a lot more concise than the old way. It’s still frustratingly awkward coming from Lisp, Haskell, or pretty much any other FPL. Or Ruby, for that matter, where we’d probably represent the function (method) to be applied as simply :+. In Clojure, we take a reference to the + function using, wait for it… +.

UPDATE: These tests no longer pass on Elixir 0.12.0. They generate the following error:

I’m not sure how to fix this.

Well, now that I’ve applied myself (hah!) to this little problem, let’s see how Elixir itself implements apply. This is easy, because the Elixir API docs link directly to the relevant code on Github. Bless you for that, Mr. Valim.

Turns out, Elixir just punts it over to Erlang:

I should have guessed this would be the case.