Ale Language Design
Ale is a Lisp dialect that takes syntactic cues from both Scheme and Clojure.
Where Scheme treats parentheses and square brackets as being one in the same. Ale treats them the way that Clojure does – meaning parentheses are used to delimit lists, while square brackets are used to delimit vectors. Ale takes advantage of this by incorporating the syntactic difference into its language design, a move that (hopefully) improves consistency and readability.
For example, in Clojure a function that accepts multiple argument patterns might look like this:
(fn ([x y z] (+ x y z)) ([x y] (* x y)))
While in Ale, a similar lambda would look like this:
(lambda [(x y z) (+ x y z)] [(x y) (* x y) ])
If you Scheme, then you’ll probably notice that this syntax is very similar to the
case-lambda form. But because Ale discriminates between lists and vectors, it can treat
case-lambda as the very same form.
In Clojure, a
cond operation would look like this:
(cond (> x 2) (* x 50) (= x 2) (* x 100) (< x 2) 0 :else 1)
You’ll noticed that the conditional pairs are determined positionally rather than explicitly grouped. Ale sticks with the Scheme tradition here:
(cond [(> x 2) (* x 50) ] [(= x 2) (* x 100)] [(< x 2) 0 ] [:else 1 ])
The one difference about Ale and Scheme is that the pairing is required to be performed using a vector rather than allowing either a vector or list. This ensures that whenever you see a cond call, there is very little cognitive burden related to what you’re reading.
Similary, in Clojure a call to
let will look like this:
(let [x 99 y 37 z (+ x y)] (/ z 3))
Where the pairs are positional rather than syntactically grouped. Ale would require a syntax like this:
(let* ([x 99 ] [y 37 ] [z (+ x y)]) (/ z 3))
If you only have one binding to perform, you can also leave out the list:
(let [x 99] (* x 2))
Defining top-level functions follows the same pattern as lambdas. So in Clojure, a function like this:
(defn sum ([value] value) ([value & values] (+ value (apply sum values))))
Would be written in Ale like this:
(define-lambda sum [(value) value] [(value . values) (+ value (apply sum values))])
Of course, a function with one signature is more straight-forward:
(define-lambda neg (value) (- 0 value))
But if you’re going to do that, you might as well just use the standard
define approach, à la Scheme:
(define (neg value) (- 0 value))