Hacker News new | ask | show | jobs
by reikonomusha 2310 days ago
It’s a practical language that sometimes chooses less elegant ways to do things in favor of a complete, robust engineering experience. For instance, the fact defined functions sit in a different namespace than values creates mostly aesthetic ugliness where named functions and named values have different treatments.

    (defun f (x) (* x x))
    (setq g (compose f f))
    (g 5)
This is wrong in Common Lisp on many levels: f must be referred to as #'f, and g cannot be called as such, you must use funcall: (funcall g 5)

These might go against the sensibilities one might have had in learning a Lisp in the first place. But in practice, these don’t stop you from writing solid, readable code.

It won’t feel as “clean” or “academic” as Scheme, but you’ll feel it easier to build large and efficient programs without pulling your hair out.

3 comments

If I were doing the above a lot, I'd write compose as a macro (or better yet a compiler macro). In that case, the only thing above that needs to be changed is the setq, which would have to be written as

  (setf (fdefinition g) (compose f f))
Still different from Scheme, but some of the differences can be papered over with macros.
Programming with a lot of higher order functions won't feel as clean in Common Lisp due to the #' and funcall.

Basic Lisp programming with lists is a lot cleaner in a Lisp in which the empty list is false, and in which accessing nonexistent parts of a list (including the empty list) is a safe no-op that yields nil.

Ashwin Ram's (cdr (assq key a-list)) almost works in Common Lisp in the form of (cdr (assoc key a-list)). See: https://ashwinram.org/1986/01/28/a-short-ballad-dedicated-to...

Imperative programming is better supported in Common Lisp because the evaluation of the arguments of most forms, including function calls, is ordered, mainly left to right, so side effect embedded in expressions will show stable, portable behavior. Scheme function calls have unspecified evaluation order, much like C. (In Common Lisp, the only unspecified aspect is whether the function cell is sampled before the arguments are evaluated, or just before the function is called. It's extremely rare for the arguments of a function call to be redefining the function cell, needless to say.)

Common Lisp forms return a predictable value. If it doesn't make sense for a form to return a value, its value is not "undefined", but either just nil or else "no values". When a value returns no values, and an attempt is made to use its value anyway, then nil is produced as the value. You will not see some annoying #<undefined> in a Lisp REPL coming from a procedural construct.

I like it. But the really nice thing about lisp is if there's something I dont like, I can just hack the evaluator to fix it.