I’ve been fiddling in Ruby with our long-standing Agile Skills exercise, payroll. The idea in those articles is to show how reasonable objects can evolve quickly, without a lot of design up front. I’ll probably continue that as time becomes available. As I’ve been thinking about that, I’ve been thinking functional map-reduce kinds of thoughts about how I might approach processing the payroll.

That got me thinking that it might be good to stretch my brain a bit and learn a language that’s actually function-oriented. Tweeting for suggestions, I found Dave Thomas’s Elixir keynote video.. His enthusiasm made me decide to take a look at Elixir. I bought Dave’s book, from Prag, and have started playing.

As is my fashion, I’ll write about what’s going on, because I enjoy doing it, and there are a couple of people who enjoy watching me fumble around and try to learn new things. I hope you’re one of them.

Dave’s book, by the way, is not like the billion-page Ruby pickaxe book. In his Elixir book, Dave shows us plenty of Elixir, but not all of it. His purpose is to interest his readers in “thinking differently” by working with a language whose paradigm is outside what one is used to. So if you decide to learn Elixir, you may need more tutorial or reference material. So far, I’m using the Elixir site itself: the materials there are pretty good.

Different Paradigm

Elixir is quite different from your everyday OO or procedural languages. It has similar-appearing syntax, but even the simplest things are different.

You can write something like [name, age] = ["Ron", 42], and if you then refer to the variable age, you’ll find 42, but not because it has been assigned. Instead, Elixir uses a pattern-matching approach, so it has associated those words but not assigned them per se. Or so we’re told: the notion hasn’t entirely sunk in. The pattern notion definitely turns up in the creation of conditionals, which are often done by providing less and less restrictive patterns, picking off special cases and then moving on to general ones.

For example, one might write factorial as shown in Dave’s book, this way:

defmodule Factorial do
  def of(0), do: 1
  def of(n), do: n * of(n-1)
end

This defines a function named of, so that you can write Factorial.of(10). Cute, huh. But the pattern notion is shown in that we have two defs for of, defining factorial of zero, and of n. When you say Factorial.of(10), the pattern matching finds that you didn’t say of(0), so it does 10 * of(9), and so on until it gets down to of(0), returns 1, and unwinds the recursion.

Yes, it seems not unlike the usual if-statement style of recursive factorial, but we are assured that it is not. Pattern-matching is different, we’re told. Part of what I’ll write about here is how that begins to make sense in my mind.

In addition, we’re told, Elixir wants us to think in terms of transforming data rather than recording state. Dave gives a really nice example of that in his keynote and there are others in the book. I’m just starting out, so I have a notion of what that might mean but it’s not clear yet.

So we’re working with a language that wants us to think differently. For me, that’s really the point.

Different Language

Years ago, last century in fact, I worked with LISP, the canonical functional language, and with some other functional languages. They really do make you think differently, as you apply various functions to collections of data, transforming them into what you want. You may have felt a little of that if you’ve gotten into the map-reduce way of thinking in other languages.

Elixir is not LISP, and I’m not sure I like that. Elixir has a lot of data types, including several things that I’d call collections. It has tuples, lists, maps. It even has binary data. And maps seem to include dictionaries and keyword-oriented things. Some of these are built into the language, and some are built up with library modules.

Speaking of modules, there are structs, which are modules defining a thing that looks a lot like a struct or record in other languages. Here’s one I’ve done, out of context but it should give you a sense of it:

defmodule Employee do
  defstruct id: 0, name: "", rate: 0 
end

This would let you define a function returning a list of Employee structs, maybe like this:

defmodule Pay
  def employees do
    [ %Employee{id: 1, name: "bill", rate: 100},
    %Employee{id: 2, name: "jake", rate: 75 }]
  end
end

You could associate that list of Employee structs with a variable (remember pattern matching) with something like employees = Pay.employees.

Anyway, Elixir has quite a few things that look like data types to me, and it has lots of quaint and curious syntax. More than I like, as a matter of fact. LISP, or its modern sibling Clojure, has a very uniform syntax, though these languages aren’t without some syntactic conveniences themselves. But Elixir has move a long way away from the LISP notion that “it’s all functions and lists, and functions are lists too”. Since I’m here to build up some function thinking, this may get in the way. If it does, I might wander over to Clojure or something else.

This is all play, and learning, after all, and I’m not going to do it if it isn’t fun. We’ll see as we go.

Why not [insert language of choice here]?

People suggested many other languages to me, including Clojure, LISP, F#, Haskell, Scala, Elm, and surely others. I’ve picked Elixir to start with mostly on the strength of Dave’s keynote. His enthusiasm was enough to get me to jump in.

In Elixir’s favor, it has a very nice notion of lightweight threads, communicating by messages, and it is very fault-tolerant, we’re told. The notion of spawning a bunch of threads to do something seems interesting and possibly useful. Other languages surely have similar things, but anyway it seems a place to start.

Maybe we’ll stay here, maybe we won’t. In the spirit of the “Seven Languages in Seven Weeks” books, we’ll play with Elixir for a while and then see what happens.

So far …

Dave’s keynote includes a couple of very interesting examples, one where he encodes a list by replacing its head with encoded bits until sequences of equal values are all absorbed, and another where he describes solving a problem by applying a series of transformations.

So this has given me a tiny glimmer of what one might do with our hoary old payroll app. Payroll can be seen as a kind of pipeline: in fact, the original C3 payroll was implemented as a “line” of operations, built in objects.

So I’m working with the payroll idea, mostly because I know enough about it that I won’t run out of stories when I need them, so that I can be working with the programming rather than trying to invent some new problem to solve that I don’t understand.

Elixir has a REPL kind of thing, interactive Elixir, or iex, and mostly I’ve been playing with that. iex can compile source programs, loading into itself whatever is in the file, so you can define modules and the like. But mostly, you can type in expressions and find out that they don’t work. That’s good. As soon as I’ve learned all the sequences of characters that are not good programs, whatever is left will be good programs. Right? Right? I hope so.

I’ve begun by typing in the examples in Dave’s book, then doing some of my own. I find that I often divert over to the Elixir documentation, to learn a little more about something that catches my interest, or to get more detail than Dave is giving in his exposition.

As I go, I’m also typing payroll kinds of things into iex, building up little snippets of ideas of notions of vague thoughts of payroll code. Here are a few of those:

iex(51)> joe = %{id: 1, name: "joe", rate: 10 }
%{id: 1, name: "joe", rate: 10}
iex(52)> %{name: "joe", rate: r} = joe
%{id: 1, name: "joe", rate: 10}
iex(53)> r
10
iex(55)> Map.get(joe, :rate)
10
iex(57)> Map.to_list(joe)
[id: 1, name: "joe", rate: 10]
iex(58)> joe
%{id: 1, name: "joe", rate: 10}
iex(59)> joe.rate
10

Here, I’m playing with a Map representing an employee, with an id, name, and pay rate. (The Employee struct evolves from this play.) I define joe (associate the Map shown with variable joe.) Then this line

%{name: "joe", rate: r} = joe

uses pattern matching to associate joe’s rate with the variable r, which I display at line iex(53). Then I use Map.get to fetch joe’s rate. I could have assigned that to r instead of associating it. I’m just poking at the different options, trying to get a sense of how you say things in Elixir.

So in the sequence above, given a Map named joe, I’ve found three ways to get joe’s rate: matching, Map.get, annd then at line 59, just saying joe.rate, which is a bit of syntactic sugar to fetch a value from a map (if the map keys are symbols, which in this case they are). You’ll have seen similar sugar in Ruby or other languages where you could say joe.rate instead of joe[:rate]. You could say joe[:rate] in Elixir, by the way. So four ways to get joe’s rate. Whee.

Damn, Ron, this seems chaotic

Yes. I’m not writing an article based on months of learning Elixir, taking you through some made-up orderly tutorial that will teach you things in the order I think you should learn it. And I’m not writing a reference manual based on months of Elixir.

Instead, I’m sharing the chaotic process that goes on as I begin to learn this language. I like to think that if your process of learning something like this leaves you confused a lot of the time, you’ll be happy to discover that it happens to me, and to share my thoughts as I did out of whatever hole I dig myself into. And if you don’t enjoy what’s happening here, please just move on to another topic: there are lots of topics here.

I guess I should have mentioned that sooner.

Anyway, it is chaotic. What we have here is the result of a few hours of playing with Elixir when I wasn’t supervising the shelves being built in my garage, or opening doors for the cat. Future articles will be more contemporaneous with the doing: this first one I wanted to have just a bit under my belt before I started.

Well, where are we?

Here is the complete contents of my pay.exs file, my only saved file so far:

defmodule Pay do
  def base(time_card, employee) do
    [id: _id, base: base, ot1: ot1, ot2: ot2] = time_card
    [id: _id, rate: rate] = employee
    base*rate + 1.5*ot1*rate + 2*ot2*rate
  end

  def fed_tax(gross), do: 0.25*gross

  def employees do
    [ %Employee{id: 1, name: "bill", rate: 100},
    %Employee{id: 2, name: "jake", rate: 75 }]
  end
end

defmodule Employee do
  defstruct id: 0, name: "", rate: 0 
end

This has two functions in it, base and fed_tax. The base function is given two lists, a time card and an employee list. You can see their form there above. The time card has employee id, and base hours, overtime one hours, and overtime two hours. The employee list has employee id and pay rate.

(I see that these names should be more meaningful. We’re playing here, and almost everything we type is wrong, which leads me to use short names. Watch what happens as time goes on: the names will probably improve.)

Notice that fed_tax takes a value as its parameter, gross. Presumably the author means this to be gross pay. We should refactor the code to say gross_pay. But what’s going on here is that I wanted to play with Elixir’s pipe operator, |>. In iex, I can say

iex(106)> tc = [id: 1, base: 40, ot1: 10, ot2: 10]
[id: 1, base: 40, ot1: 10, ot2: 10]
iex(108)> emp = [id: 1, rate: 10]                 
[id: 1, rate: 10]
iex(109)> Pay.base(tc,emp)       
750.0
iex(110)> Pay.base(tc,emp) |> Pay.fed_tax
187.5
iex(111)> 

The call to base returns 750, which is the correct pay for a $10 per hour employee who works 40 hours regular, 10 and time and a half, and 10 and double time. (I don’t pay well, but there’s lots of work.)

Then we can pipe the base pay (which happens to equal gross pay, go with me here) into the fed_tax function and get the federal tax (at 25%), $187.50.

That was the whole point of the module, letting me write that first pipe operation that makes a little sense in my application. There are plenty of pipe examples in the book and documentation, but this one is my own. When I’m working through books, I type in some of their examples, but I like to type in examples of my own. It helps me get a sense of how I might use the language to solve my problems.

The Pay module started with the keyword lists for timecard and employee, and then later I built that struct. I’ve just put everything in the one file for now, and will continue to do so for a while yet. As I’m learning, I want to see things together as I try to assemble bits that can work. As the program and my learning grow, I’ll start breaking things into separate files.

For now …

For now, that’s what I’ve got: a few hours of playing with Elixir, getting a sense of how it works and what I might do. Later today, I’ll toss all this stuff away and start again, in a somewhat more orderly fashion. It’s still early days, though, so there’s lots more learning to do.

Chet likes to tell a story from back when I wrote Adventures in C#, which was a very large book in this kind of style. Chet ran into a fellow who had read the book and had liked it. He said “Ron will be going along and say ‘I’ll try this now’, and I’d be saying ‘That’s not going to work’ and sure enough a page or so later Ron is all ‘Well, that didn’t work’. That’s what programming is really like.”

At least that’s what programming is really like for me, in a new language. Try stuff, don’t like it, try something else. I hope you’ll follow along. And let me hear from you if you’ve got helpful ideas other than “STOP DOING THAT”.

Thanks!