3 ms·
This is what I consider to be a wart of Common Lisp: somewhat unsightly, not the most desirable thing to have, but rarely if ever impeding on your ability to do
by reikonomusha 5y ago
This is what I consider to be a wart of Common Lisp: somewhat unsightly, not the most desirable thing to have, but rarely if ever impeding on your ability to do anything. Common Lisp as a language “knows” that NIL can be troublesome, so the rest of the language typically gives you facilities to avoid its pitfalls. Examples:
- GETHASH returns two values: the element found (or nil), and whether it found the element or not.
- GETF (which extracts a value from a property list) has a third optional argument for the value to return of the property isn’t found. It’s easy to make a unique sentinel value if you’re worried about collisions, for instance with an uninterned symbol:
(let* ((not-found '#:not-found)
(x (getf props 'key not-found)))
(unless (eq x not-found)
;; do something only if KEY was found
))
In this case, it’s not possible for PROPS to ever contain the NOT-FOUND value.
NIL is one of the things Lisp had to compromise on to truly make it a “Common” Lisp.
- kazinator 5y agoThe issues with nil aren't return values from containers. That problem exists regardless of what object you return for representing "not found", since that object could be a legitimate value in the container. It is an inherent problem of in-band signaling, and the only fix is out-of-band signaling: multiple API calls, multiple values, wrapped values (e.g. returning a hash entry object containing a key and value), or alternative control flows (e.g. not-found exception). Now there is a real issues with nil being a symbol, Boolean false and empty list, and it is this: In a heterogeneous, recursively varying data structure, there are are possible ambiguities as to what nil represents: - is it a recursive element of the nested list structure: an empty sub-list? - is it just a symbolic element, so that we consider (a b nil t) to be a list of four symbols? - does it indicate false? In many cases, this problem does not exist for various possible reasons: - the data structure does not use multiple representations. Thus if nil is seen, it is known that it is a symbol, Boolean false or empty lists. - the data structure does use nil in multiple roles, but they are disambiguated by syntax: such as fixed positions in syntactic nodes, or other conventions. However, even if the problem is nonexistent in a given scenario, the data structure itself doesn't make it clear; there is still a possible readability problem for someone not familiar with the conventions. Someone staring at the data structure still has to guess about what is the meaning of a given nil, and refer to the documentation or, failing that, code. Furthermore, the system itself has a "printability problem". The Lisp printer has to decide whether to render nil as nil or as (). Sometimes you see suboptimal choices like the system emiting (LAMBDA NIL (FOO)) where you'd like to see (LAMBDA () (FOO)). This is the price we pay for the conveniences brought about by nil.