code

Damien Katz Criticizes Erlang

March 10th, 2008  |  Published in code, erlang, functional  |  Bookmark on Pinboard.in

Damien Katz has been using Erlang for CouchDB, and has posted some criticisms of the language and runtime based on his experiences with them. Erlang, like any language, has its issues, and Damien’s criticisms are mostly reasonable and are worth reading. Well, except for this one:

Immutable variables in Erlang are hard to deal with when you have code that tends to change a lot, like user application code, where you are often performing a bunch of arbitrary steps that need to be changed as needs evolve.

In C, lets say you have some code:

int f(int x) {
x = foo(x);
x = bar(x);
return baz(x);
}

And you want to add a new step in the function:

int f(int x) {
x = foo(x);
x = fab(x);
x = bar(x);
return baz(x);
}

Only one line needs editing,

Consider the Erlang equivalent:

f(X) ->
X1 = foo(X),
X2 = bar(X1),
baz(X2).

Now you want to add a new step, which requires editing every variable thereafter:
f(X) ->
X1 = foo(X),
X2 = fab(X1),
X3 = bar(X2),
baz(X3).

If you had to write that code the way Damien did, then yes, that would suck. But here’s a better way to write it:

f(X) ->
    lists:foldl(fun(F, Last) -> F(Last) end,
        X, [fun foo/1, fun fab/1, fun bar/1, fun baz/1]).

This code applies the anonymous function passed as the first argument to lists:foldl for each element of the third argument — the list of funs, Erlang-speak for functions — starting with the value X as the value passed as Last and using the return value of F(Last) as the next value of Last. The overall return value of lists:foldl is the final value of Last. With this approach, modifying the functions applied to X also requires editing only a single line, specifically the list of funs.

In general, if you’re used to imperative languages and you find yourself writing step-by-step Erlang code like in the original example above, think functions and lists instead.

P.S. If you’ve never seen it, read Damien’s Signs You’re a Crappy Programmer (and don’t know it). One of my favorite blog postings, and I especially like the first two items in his list.

Elisp

January 24th, 2008  |  Published in code, emacs, emacs-lisp  |  Bookmark on Pinboard.in

Today I saw two blog postings about emacs-lisp, which is unusual given the feeds I pay attention to. I’ve been using emacs since 1985, and so over the years I’ve written more than my share of elisp. I didn’t know anything about Lisp when I started, so I learned by doing, first by just reading other code, then experimenting and adopting more and more patterns and approaches as I came to understand them. Over the years I’ve studied Lisp here and there on my own and so have improved my elisp, I think, but I’d never call myself an expert. I’ve never worked closely with anyone who enjoyed writing elisp as much as I do, so with nobody to bounce ideas off of, I’m sure there’s still much I can learn.

The first posting I saw today is about the proper handling of association lists, or alists. An alist is a list of key/value pairs, and one critical way they’re used in emacs is for the auto-mode-alist, which indicates what editing mode a given file should be set into when it’s visited. The mode is chosen by attempting to matching each key in the alist against the name of the file being visited; when one matches, it treats the associated value as a function and executes it in the file’s buffer. Such functions usually set the editing mode of the buffer. The keys are typically regular expressions that match file suffixes.

The author of that post had been using the aput function to replace elements of the auto-mode-alist with the editing modes he preferred, but recent changes to emacs resulted in aput being moved to the assoc package, so it was no longer directly available for use in the author’s ~/.emacs startup file. The author’s search for a substitute function to use instead resulted in him getting some bad advice about how alists are handled, and his posting explains how things really work.

One obvious way to fix the problem is to simply (require 'assoc), which would load the assoc package and make aput available. The author didn’t to want to do that, probably to avoid dragging in everything else the package defines. So, he instead resorted to using the push function to prepend elements to the auto-mode-alist to indicate his preferred editing modes. As he explains, file loading always searches the alist from head to tail, and so will always find his settings first, even if the same key patterns occur later in the list.

Another way to do it — a more fun way, perhaps — is to write your own version of aput. The code is interesting because it requires you to pass the alist essentially by reference to the function so it can modify it. The second elisp posting I saw today was Steve Yegge’s “Emergency Elisp” tutorial, and he mentions pass-by-reference but doesn’t really say how to do it, so let’s look at a way to do that. Here’s my version of aput:

(defun my-aput (alist key value)
  (let ((al (symbol-value alist))
        cell)
    (cond ((null al) (set alist (list (cons key value))))
          ((setq cell (assoc key al)) (setcdr cell value))
          (t (set alist (cons (cons key value) al))))))

This doesn’t do exactly what the real aput does, since it doesn’t handle the case where a key with a nil value is passed, but that’s not needed for the auto-mode-alist case. The function expects the alist, the key, and the value. As the three cases of the cond statement show:

  1. if the alist is empty, set it to a list consisting only of the new key/value pair;
  2. if we find the key, replace its associated value with the value passed in;
  3. otherwise prepend the new key/value pair to the front of the alist.

The key to making this work, though, is that we don’t really pass the alist. Instead, we pass the symbol for the alist. The symbol is kind of like a reference, in that it lets us get at the value of the alist, which we do in the first line of the function via the symbol-value function. Our first condition tests the alist to see if it’s nil; if so, we set a new alist value for the symbol. Our third condition (which always runs if the first two don’t, since it tests the value of t, which is always true) also sets a new value for the symbol by prepending a new key/value pair onto the current alist value.

To call it, we do this:

(my-aput 'auto-mode-alist "\\.erl\\'" 'erlang-mode)

Note how we quote the auto-mode-alist, so rather than evaluating it and passing its value, we pass just its name, or symbol, effectively giving us pass-by-reference.

Elisp is the primary reason I keep using emacs. It’s amazingly powerful. You can make it do all kinds of editing chores for you. A lot of people today tend to rely on their IDEs, and I even tried to move to Eclipse a few years ago, but I just don’t think there’s any IDE that can match the power and extensibility that elisp gives you. I’m sure I’ll get a few disagreeable comments for that remark, but they’ll almost certainly be from people who don’t know elisp.

Since I’m not an elisp expert, though, my explanation might be off in some way, and it’s probably possible to improve my code. All constructive criticism is welcomed!