Arc

Arc is a dialect of Lisp created by Paul Graham and Robert Morris.

Tutorial: [1 ]

Official website: [2 ]

Wikipedia article: [3 ]


AMG: I found many things in the tutorial to be quite interesting, but I'm not sure which are unique to Arc and which are from previous Lisp systems. (My experience with Lisp is limited to a brief overview in college that was poorly taught and heavily biased against Lisp. This didn't cause me to be biased against Lisp, only largely ignorant of how it is used in practice.) Anyway, let's take a few:

A lambda expression is defined as a list (imagine that!), which is elements surrounded by parentheses and delimited by whitespace. The first element is fn, and the second is a list of argument names. Subsequent elements are expressions to be evaluated. The return value of the lambda expression is the result of the evaluation of the final expression. Purely functional lambdas (those without side effects) only have one expression. In the tutorial, lambdas are simply referred to as functions, so that's what I'll call them.

(fn (x) (+ x 10))

So far this is nothing surprising. The thing I found interesting is the shorthand for single-argument functions, which the tutorial claims are used very often in Lisp programs. Such a function is written without either the fn or the argument list, only the (single) expression. The expression is surrounded by square brackets, and an underscore is used as the name of the argument. Think of it as a "blank" to be filled in.

[+ _ 10]
[if (odd _) (+ _ 10)]

Well, I thought that notation was kind of cool. At first it looked really weird to me, until I saw the underscore as a "blank". Then it made sense.

Next up is the zap operator. (I am guessing that an operator is a named function.) It takes two arguments, a single-argument function and an object. It passes the object to the function, then changes the value of the object to whatever the function returned.

arc> (= x 10)
10
arc> (zap [+ _ 1] x)
11
arc> x
11
arc> (= x '(2 9 3 7 5 1))
(2 9 3 7 5 1)
arc> (zap [sort < _] x)
(1 2 3 5 7 9)
arc> x
(1 2 3 5 7 9)

This is like [set x [func $x] in Tcl or (= x (func x)) in Arc. It's just shorter to write. ;^) It reduces the number of times that the object has to be written. I guess it was designed from a similar motivation as the shorthand for single-argument functions.

Why do I say "object" and not "variable"? Because zap's second argument doesn't have to be a variable name. It can be an expression that yields an object in a structure. The = operator is also able to reach inside structures in this way.

arc> (= x '(0 1 2 3))
(0 1 2 3)
arc> (zap [+ _ 1] (car x))
1
arc> x
(1 1 2 3)

Another thing I found neat was the shorthand for functional composition, when the "outer" functions are all named (are operators) and each accept one argument. Simply concatenate the names with colons. The result is a new function. I imagine this cuts down on the number of parentheses used in a program. Also a leading tilde can be used instead of composing with the no function.

arc> (map odd:car '((1 2) (4 5) (7 9)))
(t nil t)
arc> (map no:odd:car '((1 2) (4 5) (7 9)))
(nil t nil)
arc> (map ~odd:car '((1 2) (4 5) (7 9)))
(nil t nil)

When interpreting the above, remember that nil (the empty list) is used to represent false, that anything else is true, and that t is the canonical true value returned by a boolean function. So odd:car is a function that accepts a list as its argument and returns true (t) if its first element is odd or false (nil) if otherwise.