Problem with (json-parse) false/nil

Started by kanen, December 29, 2014, 03:40:50 PM

Previous topic - Next topic

kanen

JSON understands only "false", but Lisp understands only "nil" and they are not the same.



false should translate from JSON to nil in Lisp...



Create a file called test.json:
{
"name": false,
"age": 32,
"employed": true,
"address": {
"street": "701 First Ave.",
"city": "Sunnyvale, CA 95125",
"country": "United States"
} }


(setf json_text (read-file "test.json"))
setf json_lisp (json-parse json_text))

; the result below should be (name nil) and not (name false)

(("name" false) ("age" 32) ("employed" true) ("address"
  (("street" "701 First Ave.")
   ("city" "Sunnyvale, CA 95125")
   ("country" "United States"))) )


In other words, false is not nil!
(lookup "name" json_lisp)
; false
(nil? (lookup "name" json_lisp))
; nil


From the newLisp manual:
QuoteIn newLISP, nil and true represent both the symbols and the Boolean values false and true. Depending on their context, nil and true are treated differently. The following examples use nil, but they can be applied to true by simply reversing the logic.



Evaluation of nil yields a Boolean false and is treated as such inside flow control expressions such as if, unless, while, until, and not. Likewise, evaluating true yields true.
. Kanen Flowers http://kanen.me[/url] .

Lutz

#1
You need to reserve nil for newLISP when lookup fails:

> (lookup "name" '(("name" false) ("age" 32) ("employed" true)))
false
> (lookup "foo" '(("name" false) ("age" 32) ("employed" true)))
nil

"foo" is not a valid object in this case - not part of the JSON data. If you translate JSON "false" to nil, that distinction gets lost and you might think "foo"  is part of the data objects with attribute nil.

kanen

#2
The problem with this approach is that you now have to have an edge-case for JSON importing, which you'd not have to have in an S-Expression. Which makes JSON a different animal when converted to Lisp.  If this is the case, the manual should be very clear about it.
. Kanen Flowers http://kanen.me[/url] .

rickyboy

#3
Quote from: "Lutz"You need to reserve nil for newLISP when lookup fails

I thought that's what exp-default was for.  From http://www.newlisp.org/downloads/newlisp_manual.html#lookup">http://www.newlisp.org/downloads/newlis ... tml#lookup">http://www.newlisp.org/downloads/newlisp_manual.html#lookup:
Quotesyntax: (lookup exp-key list-assoc [int-index [exp-default]])



...



Optionally, exp-default can be specified, which is returned if an association matching exp-key cannot be found. If the exp-default is absent and no association has been found, nil is returned.
(λx. x x) (λx. x x)

rickyboy

#4
Also I see Kanen's point about what is said in the manual about it.  From http://www.newlisp.org/downloads/newlisp_manual.html#json-parse">http://www.newlisp.org/downloads/newlis ... json-parse">http://www.newlisp.org/downloads/newlisp_manual.html#json-parse:


QuoteAll data types conforming to the ECMA-262 standard are translated.

In turn, http://www.ecma-international.org/ecma-262/5.1/#sec-4.3.13">the ECMA-262 standard here says


Quote There are only two Boolean values, true and false.

The newLISP manual says:


Quotenil and true are Boolean data types that evaluate to themselves

And later


QuoteIn newLISP, nil and true represent both the symbols and the Boolean values false and true

So, if the manual says that "all data types conforming to the ECMA-262 standard are translated," shouldn't the boolean types, in particular, be translated too?  Or alternatively, as Kanen said, the manual should say something like "all data types are translated except for ECMAScipt false; so be careful."



I don't know which should prevail.  That's why I'm not a language designer :)  But it seems that one of the two should prevail.  Thoughts?
(λx. x x) (λx. x x)

Lutz

#5
Thanks for the comments Kanen and Rick.



JSON files come from very different domains and the symbolic attribute values true, false and null have different significance and interpretation in all of these domains and in newLISP.



The translation into newLISP s-expressions basically consists of replicating structured JSON data into newLISP nested lists, but the data itself should be taken as close as possible to the source. Strings as strings, numbers as numbers, symbols as symbols.



Going through the code again, I found JSON null being translated into nil and this has been corrected for 10.6.2 now translating JSON null to a LISP symbol null. Note that both null have a different interpretation in the JSON data set and in newLISP. There is a predicate null? in newLISP, but that has a different interpretation. Just like there are true? and nil? predicates but not working as expected on JSON data object values.



Most JSON translators in other programming languages offer functions to deal with the symbolic JSON values true, false, null. E.g: isTrue(), isFalse(), isNull(). In newLISP you could compare to the symbols:

(if (= 'true json-value) ...)
(if (= 'false json-value) ...)
(if (= 'null json-value) ...)

or define functions or better reader expansion macros:

(define (is-json-true val) (= 'true val))

;or using macro, which would result in faster performance avoiding call overhead:

(macro (is-json-true Val) (= 'true Val))

value would contain one of the symbols: true, false or null.



Note that true? nil? and null? would not work because true? would also trigger also on strings and numbers, nil? only on nil and null? on 0,0.0,"" and ().



The documentaion is updated in 10.6.2.