I don't hate using it as a language, it's fine, but because it's different enough than other languages it confuses people.
I don't hate using it as a language, it's fine, but because it's different enough than other languages it confuses people.
Its not particularly hard to represent JSON’s type system in CL and deserialize JSON to CL objects.
Its also not particularly hard to construct and use a model of CL data in JSON from CL. (Its even easier with YAML.)
OTOH, yes, JSONs data model is almost exactly JS’s data model (minus anything callable, which js a lot of JS, and with a slightly different model of numbers, but anything that doesn’t exactly match JS’s model is canonically unreliable and so discouraged), So with any thing other than JS using JSON, you have to determine if your use case is modeling your language’s data in JSON or JSON’s data model in your language, while with a particular subset of JS you can just ignore the distinction.
That is, JSON is not a representation of objects in your language. It's your application that holds a representation of JSON data. If you're not paying attention to the translation layer between your native objects and the JSON ones, you'll hit problems sooner or later.
But as a practical solution you could de-serialize false into, say, :false, in order to distinguish them from empty lists, and then do a post-processing step to turn those into nils if you wanted to.
That's the approach that st-json [0] builds on:
- true and false become :true and :false, respectively
- [] becomes nil
- {} becomes #s(st-json:jso :alist nil)
---
[0] in QuickLisp and at https://github.com/marijnh/ST-JSON
You just contradicted yourself.
If someone wants to do some hobby/small-scale but complex programming in LISP, what kind of dialect should they use? Scheme/Racket or something else?
The reason I like CL is that I find it is a local optimum impedance match for my brain in language design space. But that is at least in part because I have been using it for 35 years so I am used to its quirks (of which there are many). But it also has lots of really nice features, some of which are still unique to CL and which I find indispensable to my coding style. Generic functions are at the top of that list, and a close second is the macro system.
I'd be willing to argue that this is indicative of JSON's unnecessary complexity (inherited from its source language... why does JavaScript need a false and an empty array and a null and even an undefined?), but reasonable developers can disagree on that point.
Why does Lisp need a 0 and a nil? Because numbers are conceptually different from lists, and the number 0 is conceptually different from no number at all.
Why does JavaScript need a false and an empty array and a null and an undefined? Because all of those represent different concepts. Trying to stuff as many concepts as possible into a single representation doesn't necessarily make a language better (though I'm certainly not claiming that JavaScript is the epitome of good language design).
You can't iterate a null in JavaScript, but that's a design decision of the language that could have gone another way; `for (const elem of null) {do();}` could have been specified to be valid JavaScript that never calls `do()`, but it wasn't because it wasn't.
- null + null === null ; list + null === list; null + list === list
- null.length === 0 /* should probably make it a runtime error to write this property, or allow it but have the result be a list with length elements, all undefined */
(Note: somewhat hilariously, null + null is already defined in JavaScript. It, of course, is 0. Wat. ;) )
Whether null and empty list should be different or the same is an old argument, and both directions lead to different problems. http://thecodelesscode.com/case/6
It is, at least, something a language with good static typing can mitigate by disallowing null as a list argument. And then there's Java...
> You'd just end up needing an extra boolean parameter
Correct. Or an Option() wrapper or another box. Such an unusual construction is fine because, as you noted, the cases where one would want to distinguish null from empty list are rare. Rare cases should stick out.
The fact that in JavaScript (and Java), every argument that takes an array could also take null and mean something different by it, triggering a runtime error as a result, is a design foot-gun. Rarely are both null and [] as different symbols appropriate; those languages made that a by-default-always-allowed feature.
Wat?
You might want to signify that you are not passing a list instead of you are passing an empty list. Same way that happens with any other type…
> The fact that in JavaScript (and Java)
Well in JS it's completely insane. With typed python if you say "list of XXX" null is not accepted by linters. You need to specify it's also an option.
I think we are talking around agreement here, which is that JavaScript was not particularly well-designed.
https://stackoverflow.com/questions/13796751/json-undefined-...
And javascript integers (or lack thereof) don't match CL integers. So if you want to interoperate between distinct languages you do have to consider the differences anyway.