It makes a good point. However, it got me thinking that for cases like the binary-search example in the article, it might be nice to see all of the alternatives in the code and easily be able to switch between them.

One way to accomplish this in Lisp is to abuse the #+ and #- reader macros:

#+but-i-could-not-do-that-because"Some people find a do-loop to hard to read
(and 'too' too hard to spell, apparently)."

#-now-i-know-better-and-can-do-this(/ (* n (1+ n)(1+ (+ n n))6))

This is less than ideal for a number of reasons, including: one needs to make sure to pick “feature” names that won’t actually ever get turned on, the sense of + and - seem backwards here, and switching to a different alternative requires editing two places.

(but-i-could-not-do-that-because"Some people find a do-loop to hard to read
(and 'too' too hard to spell, apparently).")

(now-i-know-better-and-can-do-this(/ (* n (1+ n)(1+ (+ n n))6)))))

If I wanted to try the my-first-attempt-was-something-like-this clause, I could stick a *** before that clause or change its name to *** or final or blessed, or I could move that clause into the last spot.

There is still an onus on the developer to chose useful alternative names. In most production code, one wants to clean out all of the dead code. On the other hand, during development or for more interactive code bodies, one might prefer to be able to see the exact “How” that goes with the “Why” and easily be able to swap between them.

I use a reader macro that combines the #+feature style “comment next form” with a line comment. I’ve grown to like it quite a bit.

It grew out of my frustration reading code that used #+(or) to comment forms without noting why they were commented.

Here’s an example:

(defun sum-to-n (n)
#; we don’t need to loop
(loop for i from 1 to n sum i)
; because the following computes the same value:
(/ (* n (+ n 1)) 2))

It is probably not as clear as your `alternatives` for `alternatives` specific use case, but I find it convenient for similar sorts of things. I’ve published it as `comment-line-suppress-forms` in the repository at https://github.com/m-n/dishes .

Imho the right tool for tracking code history is version control system. And history is nothing else than alternatives. You could keep interesting spots (alternatives) with tags or alternatively with branches.

No, I don’t think so.
You can’t keep a tag or branch for *every single thing* that you try out.

What *might* be possible (with git, mercurial, and so on) to have a *branch* for each function where you explore various ways – and then “merge” to only a single one of them.
That entails quite a bit of digging to see the reasoning for an entire call path, though.

IMHO, source control is the place to keep all of the bugs for posterity. The point here was to find an alternative to explanatory comments like this one:

/* A binary search turned out to be slower than the Boyer-Moore
algorithm for the data sets of interest, thus we have used the more
complex, but faster method even though this problem does not at
first seem amenable to a string search technique. */

Having the old versions in source control is never as useful as one would hope. I never want to start using the code from eight months ago. So much has happened since then. If I think a binary search might be better now that the datasets have morphed, without the comment above, am I even going to think to look in source control to see if someone checked in a working version of it? If I do find one, then I have to check out the tagged version from the way-back machine, copy that one function aside somewhere, check out the current version again, integrate that old version into the latest source code (which is the only one that reads the new data format and the only one that fixes that bug in the curve-fitting algorithm).

I’m not saying that I want to keep around the bug-ridden chunks of code. In most cases, these alternatives would be a maintenance headache as I found when the do-loop that I put in all three examples had the wrong terminating condition and was summing (* n n) instead of (* i i). However, I think there are some cases where one might like an easier way to explore the alternatives than having to do the source control dance.

@Philipp Marek
This may be true for such small alternatives in one function, but: most alternatives are different algorithms implemented by several functions. Those must match each other. Furthermore, if you atr just interested in the current implementation you have to search for that, and you have to make shure to know which one is currently selected.

I sometimes like to keep alternative versions of functions around as well. For example, when I made a perlin noise implementation it was good to keep the reference implementation around (I just tagged “-reference” after the function name).

For an API it is also nice to have long descriptive function names and shorter ones to preserve the holy horizontal space. I link these using #’defalias:

Related posts:

Building the language up to you One of the things that’s often said about Lisp is that it allows you to build up the language to you. Here are two examples that really drive home that point, for me. The Problem Domain I read an article about Treaps on reddit yesterday. The article used pretty direct...

Code Clarity Revisited In an earlier post, I showed a simple loop written in several programming languages. The loop had to sum the weights of each items in a list. Dmitry pointed out a much clearer loop in Lisp using the (loop …) construct. (loop for item in item-list sum (weight item)) I...