Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I like that the article was non judgement. The real world is messy and Common Lisp formalized existing practice among several branches of an already old language from before programming language theory.

There are a number things worth “fixing” and it’s delightful that so much interest and implementation in this regard has been sustained for so long.

But to the ideologues, I can only quote Emerson: "A foolish consistency is the hobgoblin of little minds, adored by little statesmen and [programming] philosophers and divines."



To help someone learn to use a language, we should be judgemental and call special attention to all of its shortcomings and gotchas. I don't see value in sweeping them under the rug. That kind of language advocacy is a zero-sum game (or negative-sum).

For example:

> ... it is not at all strange that there is an object whose type is both list and symbol.

Actually, it is strange, and unfortunate. One should think about examples of code that might store different types of values in a variable or data structure, using e.g. `symbolp` and `listp` to distinguish the different representations, and consider how the collision between the symbol nil and empty list could produce unexpected behavior. One must be aware and remain vigilant.

> the things which are not necessary are that it be a symbol, and that it represent falsity.

Other non-necessary things: `car` and `cdr` special cases for `()`, self-evaluating `()`.

> CL requires precisely one implementationally-weird object, while Scheme requires two, or three if you count #t

There is nothing intrinsically weird about having an empty list object. The only thing weird about it is the behavior of `car`, `cdr`, and `symbolp` in CL.

Also, there is nothing weird about having a proper boolean type. On the other hand, if CL's `(type-of 't)` actually returns `boolean` and not `symbol`, as the article indicates, then that is indeed weird.


If you want that kind of clarity, use another lisp, like Scheme, that doesn't have the legacy quirks. There are plenty to choose from that make different choices.

That's kind of my point.


Lisp dialects that have deviated from these choices require the programmer to write hideously verbose code, unable to take advantage of the economic idioms they afford.


What useful idiom is afforded by nil being a symbol?


There are a number of benefits.

One is that, in the role of the list terminator, nil effectively serves as a symbol. It is unique, and tested for its identity: if the cdr of the cell of a list is the nil object, then that is the last cell. This is how symbols are used. Anything that is exploited for its unique identity should be a symbol.

Nil isn't necessarily implemented the same way as other symbols. It could actually be a null pointer. One way to look at it is that something now known as the GoF Null Object Pattern is at work. All the functions which take a symbolic argument, such as symbol-name, symbol-value, symbol-package, ... are made to work with a nil argument. Just like (car nil) is made work with a nil argument, even though nil isn't a cons.

Being able to pass nil to symbol functions makes some things work that otherwise wouldn't, which can reduce the code. All the special case testing (if necessary) is done in the library already.

Say we have a hash table H which maps keys to symbols.

We can do, say, (symbol-value (gethash K H)). If K is not found in the table, gethash will return nil. Because nil is a symbol, (symbol-value nil) works fine and returns nil. If that's what we want in the not found case, it keeps our code short and sweet.

Whenever some slot or variable defaults to nil, it's not only defaulting to a false value, and empty list, but to a valid symbol object that can be passed to symbol API's.

If the empty list weren't a symbol, it could be notated (), and nothing but that. That notation works grewat when we are dealing with the empty list semantics. It's not so nice when () is denoting false, other than () kind of looking like a zero. When () denotes the bottom type in the type system, things are also not nice; all other types are either symbols or expressions like (or integer string). It's much nicer to have a word like "nil" for all these roles.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: