Am I missing something?
Am I missing something?
1. Telling apart optional arguments to a function that weren't given from arguments that were given and were NIL. Typically giving a default value for the argument is sufficient to avoid the problem, but you can also add an extra parameter that tells whether the argument was given.
(defun foo (&optional (x :default-value xp))
;; X holds the argument given by the caller, or the keyword
;; :DEFAULT-VALUE if nothing was given.
;; XP is T if the argument was given, or NIL if it was not given.
)
2. Finding an item that may be NIL. Functions such as GETHASH (which looks up a key in a hash table) usually allow you to specify a default value, and they will return a second value to indicate whether something was found. ;; Increment the value of KEY in TABLE, or if the key doesn't
;; exist, use 10 as a default, increment that and set the
;; result to the table.
(incf (gethash key table 10))
(multiple-value-bind (value existsp) (gethash key table)
;; VALUE holds the value if it exists, or NIL if it doesn't.
;; EXISTSP is T if the key exists, or NIL if it doesn't.
)
Notice that in CL additional return values can be ignored if you're not interested in them, so you only need to use MULTIPLE-VALUE-BIND when you actually need it. You could also wrap it in a trivial macro if you're using it a lot. (defmacro if-some-let ((var form) &body (then &optional else))
(let ((somep (gensym "SOMEP")))
`(multiple-value-bind (,var ,somep) ,form
(if ,somep ,then ,else))))
(if-some-let (val (gethash key table))
(format t "Found: ~a~%" val)
(format t "Didn't find.~%"))If you want an empty list that isn't nil, you have to implement your own list type.
If you want a symbol called "NIL" that isn't self-evaluating and Boolean false, you have to use your own package.
It is actually the same in most dynamic programs also. A given expression, variable or object slot is understood to be a list, boolean flag or a symbol.
The fact that the domains of lists, Booleans and symbols happen to intersect is not relevant and doesn't really even come up. "Oh, this value a symbol too; nice, but we're not using it as one".
The empty list being false keeps a fair bit of unnecessary verbiage out of list manipulating code.
Variables and object slots being initialized to a default value of nil means that they serve as empty lists or false booleans, which is handy. A block of code which requires an initially stack can just be wrapped with (let (stack) ...). stack is ready to be pushed upon.
Really, when we consider everything, there is actually one item that is sometimes a bother: in a nested list structure, there is ambiguity between nil being just a symbol and a nested list. These two objects are equivalent: (a nil b) and (a () b).
If you're dealing with such data in which you need every possible word to map to a symbol that isn't an empty list, use a separate package, so that the "nil" token in the external data goes to mypackage:nil and not common-lisp:nil. (Treating such external data in a separate package is a good idea for other reasons, too).
That said, pretty sure you can find the specific answer if you need it.
What's so strange about it? That's how it has always been in C for example, Python didn't have a boolean type either for a good while, and lots of languages are like that.
(values value present-p)
For example, `get-hash`: http://clhs.lisp.se/Body/f_gethas.htmIn that context it's hard not to simply conclude that CL would be at a disadvantage.
Other conversions are possible of course. This scheme has the advantage of allowing you to naturally iterate over JSON arrays as lists in application code, but you have to take care of the fact that :false evaluates to T, by for example writing your own macros for "if".
This might read like a nightmare, but Lisp makes it really easy to customize everything about it self, which can be beautiful, if you're into that.
Perhaps because of the surrounding language?
Probably not, since C also has the same issue, and it's not very important there either, while at the same time being totally different as a language from Lisp.