So, XML, YAML, JSON, and the dozen plus other markup notations were not suitable because they used C style delimiters instead of Lisp style delimiters?
Snark aside, what does this buy us that these existing markup languages don't?
I appreciate all that Rich Hickey does for programmers, but aside from his name, this just adds to the noise that already exists in this domain.
I suspect it's just a tool, and the Datomic folks thought they'd make it available. No one said it was going to change the world, right?
What does it buy "us"? Well, it doesn't buy "us" anything. They needed a data interchange format and I assume it made more sense to use Clojure's primitives than parsing up JSON. Why would a project written using a homoiconic language use anything but that language to exchange data between its components?
edit: Said best by this tweet by fogus:
"Clojure devs have been using #Clojure data as an interchange format all along. ..."
> They needed a data interchange format and I assume it made more sense to use Clojure's primitives than parsing up JSON.
Even in JavaScript it's better to parse JSON instead of eval'ing, because you don't want to execute stuff that would "happen" to be contained in the data interchange format.
The word REPL comes from lisp and means Read Eval Print Loop. The significance is that unlike in, say, python, Read and Eval are separate. Read reads a string and turns it into an in-memory data structure, Eval takes a data structure (not a string!) and evaluates it.
Using Read in a lisp is typically safe, so long as you turn off reader macros and the like.
How so? Prefix notation reads left-to-right nicely when you are dealing with verbs. Boolean logic is less natural, but also makes up much less of my programs (especially when using functional patterns like predicates, map, reduce, filter, etc.).
I also think that while Boolean expressions in Lisp are less natural than "this AND that OR another", they are clearer when they get large (with good formatting of course).
In English we say 1 + 2 * 3 as "one plus two times three":
1 + 2 * 3
one plus two times three
But in Lisp when read naïvely left-to-right this becomes "times add one two three", which is nonsense in English.
(* (+ 1 2) 3)
times add one two three
Most people cite "lots of brackets" as their reason for disliking s-expressions, but I think the unfamiliar ordering is a less superficial criticism. Of course, for those of us manipulating ASTs they're very natural, because we see language as trees.
People always mention the infix operators, but really, how often do you come across them in your code? Unless you're working on something highly mathematic, it really isn't that big of a deal. Otherwise, sexprs visually are a matter of rearranging parentheses for basic function calls.
Of course 1 + 2 * 3 is more familiar that way, vs the Lisp way. But you have the Lisp way wrong (unless your example was Smalltalk)... it would be:
(+ 1 (* 2 3))
Which could be read left-to-right as "sum 1 and the product of 2 and 3".
Also, most math functions in Lisp are variadic. So if you have this in infix:
x + y + z + 1
// x plus y plus z plus one
You could do it in Lisp as:
(+ x y z 1)
;; sum x y z and one
There are plenty of cases where an algorithm is naturally expressed as a map or a reduce, where infix or prefix has nothing to do with it. I don't find myself using a lot of the kind of math that would be better in infix.
It might even be useful to give math operators new names in Lisp, because of the way that things like < > = == are a bit awkward when read as their equivalents in infix. They are all variadic, after all.
Compare:
(x == 10 && y == 10) && (x < y && y < z && z < 100)
Vs.
(and (== x y 10) (< x y z 100))
That's already an improvement, but the reading is strange. So what if we alias those operators?
(all-true? (same? x y 10) (ascending? x y z 100))
I don't know if I'd actually use those names, and I don't think I would do this in code, but you get the point. You can even tell how a list of numbers is sorted in Lisp by simply doing:
Lisp disappointed a lot of people in the early 2000s. It wasn't ready for a close-up examination by people who cut their teeth on Perl, Python, and Java. All the little inconveniences, the lack of software repos, the lack of organized open-source projects, the attitude that people shouldn't expect to get work done right away, the "why do you need a library for X when you can write it in twenty lines of code?" The Lisp community was pretty satisfied with the way it did things (which I think was more a reasonable attitude than it appeared from the outside) but they were not prepared to explain themselves to a mob of curious people with entirely different expectations for a programming language community.
Erasing that initial bad impression may be a generational thing. Even heroin goes through cycles where a new generation comes along that hasn't seen anyone die of heroin, they make heroin cool for a while, and then the horrifying results inoculate the culture against the idea that heroin is cool for another fifteen or twenty years. Lisp will get another chance, and it can afford to wait.
Also, I think next time around it won't be Lisp, the universal solution. It will be a Lisp. It might not even be called Lisp. It might be called "Clojure" or something odd like that ;-)
Can't get a hold on a blog article from an old lisper expressing his lack of understanding about the so-called lisp library problem. It was a clear summary of the fallacy.
More and more I hear people 'they've been doing this in lisp all along' so I make a naive guess that in the future lisp genes will reappear in more favorable settings and won't get dismissed as they were before. It's already happening as for gc's and closure right ?
Above JSON: Sets, keywords, integer type, hashmaps in which the key doesn't have to be a string, extensible data types (most of which jacobolus points out as well)
JSON is a lowest common denominator. The features that you just specified are not directly available in JavaScript. Therefore data represented in this new format will be very, very clunky to access from JavaScript.
You say "lowest common denominator," I say "subset of JavaScript." In fact, JSON objects are clunky to access in some languages, like C. JavaScript's lack of proper sets and maps is a weakness of the language's standard libraries and is in fact being corrected. It seems quite unreasonable to me to use JavaScript as some sort of Platonic ideal of a programming language, where anything that has a different feature set is automatically bad.
It's kind of a big leap to go from "This is not a strict subset of JavaScript" to "You're ignoring the web." If you really want to deal only with JavaScript-native data structures, I can't see any reason why you couldn't deserialize EDN into those. If you really like the added data structures in EDN and don't want to lose those in your JavaScript program, you could just use Mori or something similar.
If improvement in JavaScript, which sits in browsers that developers have no control over, is a prerequisite for the success of a protocol, that protocol will be irrelevant in the web world.
In general when you're trying to achieve interoperability, any features and distinctions supported in your data format that are available in one language and not in another will be causes of interoperability problems.
For instance with JSON, the format allows you to differentiate between values that are numbers and values that are strings. Languages like PHP, Perl and JavaScript do not particularly care about that distinction, and therefore coding values consistently is hard in those languages. (You can guess, but sometimes guess wrong - your zip codes are usually represented as numbers and sometimes strings.) Languages like Ruby and Python do care about the distinction, and so applications can have difficulty accepting JSON from the previous languages.
This new format allows more places for this kind of issue to exist. We have distinction between different types of integers. We have symbols (2 kinds if you have them). We have sets. We have 2 different kinds of lists. And we have a plethora of possible extensions, every one of which can behave differently in different implementations.
When both sides speak Clojure, this is going to be a very convenient choice. When they don't, every one of these obvious features is going to be a source of headaches down the road.
That is why data exchange formats should be in a least common denominator between the languages in question.
If I were to agree with some of your points, it would have to be the distinction between a list and a vector seems rather silly.
Having those as distinct different types in a data exchange-format seems awfully (lisp/functional-language) implementation specific. IMO conversion from "generic list" to "whatever type of list makes sense in your domain" should really be done outside of an data-interchange format. A data-exchange format should not need to meddle with any list besides "generic list".
I do think sets (as opposed to lists) brings valuable semantics, though I can see how that is up for debate.
Otherwise, you bring up fair points, but I don't mind a format with ambition. Merely presenting a new JSON would not be very exciting.
There is some redundancy between vectors and lists, admittedly.
However, edn is not without legacy. Part of that legacy is Lisp and s-expressions, and deserves some respect and accommodation. If that means readers map the [] and () to the same code path, well, that's not much work. Writers can always write only [] if they prefer.
Having the distinction has proven tremendously useful to Clojure, and might to other applications as well. In particular, consider DSLs written in edn, which, like Clojure, might need to distinguish calls or grouping from list/vector data. For all the bitching that goes on about parens, few people would want to work in a language without them :)
Maps with non string keys are handled differently even in languages that do support them. Are two instances of an object used as a key the same for example. This may vary depending on the type of the object.
> The features that you just specified are not directly available in JavaScript.
JavaScript has hashmaps with non-string keys, they're just not exposed by JSON. Also a set can be treated as an array in a non-clunky manner. Likewise for treating an integer as a Number.
I'm not sure the design goal of edn is to actually be consumed from JavaScript though?
Stuart Halloway mentioned in one of his talks that SOAP, iirc, did way too much and that as a reaction to that, JSON went too far in the bare bones direction. Looks like edn is the balance Rich Hickey and associates have struck. From a Clojure programmer point of view, I like what I see.
From what I can tell, not much, but it adds another form of extension (via tags) which you can arguably say you also had in XML (via namespaces).
Other than that, the major difference seems to be that EDN does not have a root-element or requirement for such, and as mentioned in the introduction can be used for streaming and real-time content etc.
Snark aside, what does this buy us that these existing markup languages don't?
I appreciate all that Rich Hickey does for programmers, but aside from his name, this just adds to the noise that already exists in this domain.