This is a Lisp dialect with the intention of establishing important modern features into the greatness that is Lisp.
While there is no rule for it, certain patterns for naming functions are well-established in Coda.
|Predicate||Determine if the parameter(s) fulfill some kind of condition, in this case an empty list.|
|Destructive||Store a new value in the place of an older one; in this case set a variable to a value, discarding the old one.|
|Constructor||Make a new instance of an object, in this case an array.|
|Conversion||Convert some value into another, usually of a different type; this example would give the Unicode codepoint of the given character.|
|Secondary / Recursive||Sometimes it's useful to define a secondary or recursive function, while using the primary as an interface which accesses the secondary internally. The convention is to name the secondary with a prime.|
Unlike Common Lisp, and taking some hints from Scheme and Clojure, Coda uses special values
for truth and falsehood, namely
#f. The special forms for
COND, as well as any function that requires a
predicate, such as
FILTER, must evaluate either
-- no other value will cut it. Similarly,
nil is now a special value that
represents, well, nothing. It is not the same as the empty list
semantics of many of the list functions are unaffected, e.g.
(cdr (list "LISP")) =>
(list "LISP") = (cons "LISP" '()).
There are too many equality functions in Lisp. Instead, normal functions will be overloaded like using CLOS-like techniques; this also creates an illusion of "type classes" like in Haskell. It would work something like the following:
(defgeneric :string (= s1 s2) (and (= (length s1) (length s2)) (all (dotimes (length s1) (λ (x) (= (subseq s1 x) (subseq s2 x)))))))
Unfortunately, this slows down evaluation when the type of the the first argument cannot be inferred at compile-time. But I think it's worth it to avoid the 3,720 different equality functions currently in use.