Arc has been released for less than one week, and already it’s been flamed to death on the Internet. I read the tutorial during the week and found nothing interesting about it, except maybe treating container structures (lists, alists, tables) as functions.
Tonight, I decided to play around with Arc. I started implementing solutions to the 99 Lisp Problems in both Scheme and Arc. For the first few problems, the solution are almost identical, so there’s not much to talk about there. However, once I got to the problems that required a case analysis, the new structure of if (Arc’s equivalent of COND), I found something that I deeply disliked.
Here’s the solution to the 8th problem (compress) in Scheme and Arc:
; Scheme (define (compress l) (cond ((null? l) '()) ((null? (cdr l)) l) ((equal? (car l) (cadr l)) (compress (cdr l))) (else (cons (car l) (compress (cdr l)))))) ; Arc (def compress (l) (if (no l) nil (no (cdr l)) l (is (car l) (cadr l)) (compress (cdr l)) (cons (car l) (compress (cdr l)))))
The difference is the following: Scheme’s cond puts each case into parentheses and the default case uses the else keyword, so the syntax is (cond (predicate-1 statements-1) (predicate-2 statements-2) ... (else statements-else)). There are two advantages to this syntax:
- Because of the presence of the else keyword, everything at this indent level is a condition, a predicate. So it’s easy to scan down to see what the conditions are. In the case of compress, I can easily see that the cases are if l is empty, if the cdr of l is empty, if the car and the cadr or l are equal and all other cases. Just a quick glance is necessary to identify those, because the indentation tells me.
- Because a predicate and its statements are enclosed together in parentheses, when you close the parens with an editor that does parens-matching, it’s easy to know when to stop closing parens: when the one at the beginning of the line flashes.
In an attempt to make programs shorter, Paul Graham decided that the extra parentheses and the else keyword were too much. So he removed both. The absence of the enclosing parentheses had the consequence that I always closed one parentheses too many. But the more important problem is that the indentation of the last statement is the same as the predicates, so I can’t just tell by glancing at the code if it’s the statement of the default case or if it’s another condition.
In the tutorial, Paul Graham aligns his example very nicely:
(if a b c d e)
That’s nice in theory, but in practice, my editor doesn’t automatically align those. I could put it like this manually:
(def compress (l) (if (no l) nil (no (cdr l)) l (is (car l) (cadr l)) (compress (cdr l)) (cons (car l) (compress (cdr l)))))
But it’s annoying to do all the time.
More on my impressions of Arc as I feel like writing them.