In general, even if you do have a separate boolean type, you need to distinguish between the function which intended to return null and the function which was unable to return anything.
We see here also the distinction between sum types and union types: Maybe Maybe a has three variants: None, Some None, and Some Some a; but (T | null) | null collapses to just T | null.
Yes, and this is what e.g. assoc and member do. But in those cases there's already a container, whereas in a hash table you would have to construct a new one. I do think that multiple values are easier to use and result in more direct code; the problem is that they don't enforce correct usage the way a container does.
The nil / null value is an attempt to cheaply produce from type T a type like Maybe T, or Optional<T>, or basically T | nil. It's sort of practical. OTOH making false and nil indistinguishable is much less convenient than one might think, and leads to subtle errors.
You're saying I should use custom symbols like 'true and 'false and put in checks like (eq 'false x) instead of (null x)? To avoid subtle errors? Honest question.
Postmodern (https://quickref.common-lisp.net/postmodern.htm), a library to interface with Postresql will use the keyword `:null` to represent null, and T and nil to represent boolean true and false.
In which data structures? For example in CL hashes use multiple returns so in 99% of cases you can just not care, and when you do care about the difference you just check the second return value.
I mean distinguishing between `null`, `false`, and `[]` on the JSON side. Most JSON libraries for CL by default parse them all as `nil`. (ST-JSON excepted.)
I still haven't decided if it's a good idea or not, and I've been hacking Common Lisp for more than 20 years.