LISP: listp question

BC7 help says:
(listp item)
This function tests if item is a list. If the item following listp is a list, the function returns T. If not, nil is returned.

But using the code below, either entering a point, or hitting enter will display "listp says it's a list". The results of (type) are as expected. Am I missing something here?

(setq pt1 (getpoint "\nEnter a point or hit Enter: "))
(princ "\nresult:\n")
(princ pt1)
(if (listp pt1) (princ "\nlistp says it's a list"))
(if (= (type pt1) 'list) (princ "\ntype says it's a list"))
(princ)

Comments

  • NIL is equal to an empty list, and so (listp NIL) correctly returns T. Just compare (type NIL) and (type '()).

  • Thank you very much for clearing that up.

    This then means that what BC7 Help says about not and null functions:
    "The not and the null functions are very similar. The difference is that not checks whether the item is nil. Null is meant for testing for empty lists."
    is incorrect. In fact there is no difference:
    (null nil) returns T
    (null '()) returns T
    (not nil) returns T
    (not '()) returns T

     

  • You are right - there is no difference between NULL and NOT. Historically NULL was used for lists and NOT for other data types.

  • Just a tip ... to test for a valid answer here, it is sufficient to check for being non-NIL :

    (setq pt1 (getpoint "\nEnter a point or hit Enter: "))
    (if pt1
      (progn
         :
      )
    )

    this is the same as testing like
    (if (/= pt1 nil) ...)

  • Torsten that is a good point. In some of my lisp-programs just checking for non-NIL would suffice and there is no need to use: (if (= (type pt1) 'list).
    A prime example of this:

       (if
    (and
    (setq ss1 (ssget))
    (setq pt1 (getpoint "\nFirst point: "))
    (= (type pt1) 'list) ; superfluous code
    ...

     

     

    The use of (if (= (type pt1) 'list) stems from this type of code (where it is necessary):

       (setq loopSwitch T)
    (while loopSwitch
    (initget "Settings Help")
    (setq result (getpoint "\nPick point or [ENTER=Cancel/Settings/Help]: "))
    (cond
    ((= (type result) 'list) ; a point was picked
    ; ...
    ; ...
    )
    ((= result "Settings")
    ; ...
    ; ...
    )
    ((= result "Help")
    ; ...
    ; ...
    )
    (T ; ENTER was pressed
    (princ "\nFunction cancelled ")
    (setq loopSwitch nil)
    )
    )
    )

     

     

    Still: this will always amaze me:
    (listp nil) returns T
    (atom nil) returns T
    How can nil ("nothing" as it were) be both a list and an atom?!

  • Hello, Roy, thanks for reply ...

    Yes, sometimes it is nessecary to distinguish the result using (listp), and others, if the result can be of different type.

    Regarding NIL - yes, it seems to be a bit funny, but it is logical :
    NIL is not really "nothing" - it is more related to being "empty" ... i.e. an empty list is NIL; an empty symbol is also NIL, but an empty symbol also means "non-existing".
    So NIL value is like both "empty", which also is handles as being "non-existing" ...

    This behaviour ("empty" == "non-existing") comes from very old XLisp design of AutoLISP - from times, where 1 MByte memory was valuable like 100 gramm of golg :-)
    At those times it was simply nessecary to safe each single byte ... so any symbol/variable with "empty" value was immediately cleaned-up by Lisp garbage collection.

    Additionally, everything which is a base object is also an atom ... like a number, a string, and even T and NIL *values*.

    Many greetings, Torsten

This discussion has been closed.