Subject: Re: symbolp and nil
From: Erik Naggum <erik@naggum.net>
Date: 20 Apr 2001 23:44:55 +0000
Newsgroups: comp.lang.lisp
Message-ID: <3196799095379608@naggum.net>

* Christian Lynbech
> I was quite surprised to learn that NIL and () both makes `symbolp'
> return true. This is no accident or bug, the symbolp section in the
> hyperspec has it as one of the examples.

  `nil' and () are identical.  This is a tremendous feature.  Without it,
  you would have to convert all expressions to explicit boolean values to
  test their value, because only #false would be false and probably also
  only #true would be true.  Scheme suffers greatly from having dispensed
  with this "polymorphic" design in their misguided zeal for an utterly
  impractical "purity".  When (if () :true :false) yields :true, you know
  you have experienced bad language design.

> Could someone enlighten me to the wisdom of this feature?

  It means that nothing is a thing, instead of not a thing, which would
  have made everyone test for thingness before they could use a thing.

  That the empty list has a "virtual" car and cdr slot which are also nil
  is such an elegant pun that it should be rewarded.  Scheme freaks will
  never understand this, but the ability to refer to such a special value
  as "false" in more than one way is tremendously useful and makes for very
  elegant and compact code.  There's a very nice poem about this that has
  probably been posted several times, but it bears repeating:



    A SHORT BALLAD DEDICATED TO THE GROWTH OF PROGRAMS
    ==================================================
                      by
                  Ashwin Ram

    This is a tale of a sorry quest
    To master pure code at the T guru's behest
    I enrolled in a class that appealing did seem
    For it promised to teach fine things like T3 and Scheme

    The first day went fine; we learned of cells
    And symbols and lists and functions as well
    Lisp I had mastered and excited was I
    For to master T3 my hackstincts did cry

    I sailed through the first week with no problems at all
    And I even said "closure" instead of "function call"
    Then said the master that ready were we
    To start real hacking instead of simple theory

    Will you, said he, write me a function please
    That in lists would associate values with keys
    I went home and turned on my trusty Apollo
    And wrote a function whose definition follows:

        (cdr (assq key a-list))

    A one-liner I thought, fool that I was
    Just two simple calls without a COND clause
    But when I tried this function to run
    CDR didn't think that NIL was much fun

    So I tried again like the good King of yore
    And of code I easily generated some more:

        (cond ((assq key a-list) => cdr))

    It got longer but purer, and it wasn't too bad
    But then COND ran out and that was quite sad

    Well, that isn't hard to fix, I was told
    Just write some more code, my son, be bold
    Being young, not even a moment did I pause
    I stifled my instincts and added a clause

        (cond ((assq key a-list) => cdr)
              (else nil))

    Sometimes this worked and sometimes it broke
    I debugged and prayed and even had a stroke
    Many a guru tried valiantly to help
    But undefined datums their efforts did squelch.

    I returneth once more to the great sage of T
    For no way out of the dilemma I could see
    He said it was easy -- more lines must I fill
    with code, for FALSE was no longer NIL.

        (let ((val (assq key a-list)))
           (cond (val (cdr val))
                 (else nil)))

    You'd think by now I might be nearing the end
    Of my ballad which seems bad things to portend
    You'd think that we could all go home scot-free
    But COND eschewed VAL; it wanted #T

    So I went back to the master and appealed once again
    I said, pardon me, but now I'm really insane
    He said, no you're not really going out of your head
    Instead of just VAL, you must use NOT NULL instead

        (let ((val (assq key a-list)))
           (cond ((not (null? val)) (cdr val))
                 (else nil)))

    My song is over and I'm going home to bed
    With this ineffable feeling that I've been misled
    And just in case my point you have missed
    Somehow I preferred (CDR (ASSQ KEY A-LIST))



#:Erik
-- 
  I found no peace in solitude.
  I found no chaos in catastrophe.
			-- :wumpscut: