nil and 'nil

Started by Cyril, March 19, 2008, 03:12:22 PM

Previous topic - Next topic

Cyril

Everyone knows that in newlisp, unlike other lisps, nil is not the same as empty list, although both are considered false in boolean contexts. Let me remember:


> (if nil 'yes 'no)
no
> (if '() 'yes 'no)
no
> (= nil '())
nil


But not everyone probably know that in newlisp there are not two, but three false values, two of them are equal to each other!



What the bogus? Let us see:


> (if nil 'yes 'no)
no
> (if 'nil 'yes 'no)
no
> (= nil 'nil)
true


So far so good. Where the problem is?


> (symbol? 'nil)
true
> (symbol? nil)
nil


'nil is symbol, while nil is not. More then:


> (ends-with "abc" "[a-z]" nil)
true
> (ends-with "abc" "[a-z]" 'nil)
value expected in function ends-with : 'nil


A flag argument may be nil only, not 'nil.

Some low-level investigation:


> (& 0xf ((dump nil) 1))
0
> (& 0xf ((dump 'nil) 1))
5


So, the conclusion: nil and 'nil are different values, although they are both boolean false and are equal by standard equality test.



Now let me imagine myself being a celebrity and giving an interview:



Q: Do you think this is an error? Should it be fixed?

A: Definitely no. This is a useful compromise, which allows a lot of code to be written in a natural way. I prefer to keep it this way.



Q: Do you think this should be documented?

A: Definitely YES!



;-)
With newLISP you can grow your lists from the right side!

Lutz

#1
The main reason that the symbol: nil is also taken as boolean false is, that sometimes the symbol nil is undistinguishable from the boolean value nil when it is not quoted, as in the following example:


; symbols
> (set 'lst '(nil nil nil)) ; nil is a symbol
(nil nil nil)
> (map symbol? lst)
(true true true)
> (map true? lst)
(nil nil nil)

; boolean
> (set 'lst (list nil nil nil)) ; nil is evaluated and boolean
(nil nil nil)
> (map symbol? lst)
(nil nil nil)
> (map true? lst)
(nil nil nil)


'ends-with' and 'starts-with' are the only two functions which do not accept the quoted symbol 'nil as boolean false flag, but will be converted in the next version. All other functions taking flags have already been converted:



command-line, trace, join, dup, randomize, bayes-query, unify, net-close, net-lookup, net-send-to, net-eval, net-ping, diffrence, intersect, explode, upper-case, lower-case, title-case, delete, name.



and can take a quoted 'nil.

Cyril

#2
Quote from: "Lutz"'ends-with' and 'starts-with' are the only two functions which do not accept the quoted symbol 'nil as boolean false flag, but will be converted in the next version.


'ends-with' and 'starts-with' are the only two functions that act differently with nil flag and without any flag at all. All other functions treat nil in the same way as the absence of flag. This is consistent with the general rule that nil is the default value for absent arguments. I believe that 'starts-with' and 'ends-with' are different for a reason, but it would be nice if this unusual exception will be explicitly noted in documentation.



Update: oops! 'sym' is the third. 'sym' too treats nil flag argument in other way that absent flag argument, and it too accepts nil only, not 'nil.


Quote from: "Lutz"command-line, trace, join, dup, randomize, bayes-query, unify, net-close, net-lookup, net-send-to, net-eval, net-ping, diffrence, intersect, explode, upper-case, lower-case, title-case, delete, name.


I have failed to find any flag arguments in unify, net-eval, net-ping and net-send-to (but found in net-send-udp). Also no flag in upper-case and lower-case. Which is wrong -- this list, documentation, or me?



Also it seems to be an error in documentation on 'trace'. The manual says: "Tracing is switched on when exp evaluates to anything besides nil or an empty list ()", while in fact trace, like all other functions from this list, checks for nil (or 'nil) only, treating empty list as any other non-nil value.



P.S. Sorry if my postings today are too picky. I opine that newlisp is a great language, and to discuss what looks like it's disadvantages seems to be the right way either to fix them, or to learn why they are advantages really. I am in no way going to be offensive.
With newLISP you can grow your lists from the right side!

Lutz

#3
unify: this is an undocumented flag forcing to bind the symbols in the associations returned:


> (unify '(A B) '(2 A))
((A 2) (B 2))
> A
nil
> B
nil
> (unify '(A B) '(2 A) '() true) ; undocumented flag
()
> A
2
> B
2
>


net-ping: the flag is a yet undocumented feature reporting the os error number to distinguish between not reaching the host or host down.



upper-case, lower-case: you are right, missed this because I was looking for the getFlag() routines in C source, which is the same for 'title-case'



net-eval: the boolean parameter is inside the parameter lists, scroll to "Raw mode" in the documentation, missing in the top syntax pattern



sym: will be converted too



trace: needs change in docs


QuoteSorry if my postings today are too picky ... I am in no way going to be offensive.


don't worry, you are helping to improve newLISP, and I appreciate any of your observations very much :-)