So this is literally Lisp, just with curly braces instead of parenthesis :).
I don't understand this part of the readme:
> The advantage of Mark over S-expressions is that it is more modern, and can directly run in browser and node.js environments.
Does this mean I'm so out of date with JS that this syntax is actually legit JS? Or does Mark run its own parsers, at which point it's just like sexps, except it uses the "more modern" curly brace instead of "less modern" parenthesis?
EDN, in addition to being simpler, also has an optimized transport abstraction, transit, which serializes to application/transit+msgpack (binary) or application/transit+json (often vastly faster deserialization than messagepack because which hits the language native JSON parsers for performance in web browser, python, etc). It surprised me how big a deal hitting native json parsers is, EDN was at the top of our profiler for 100kb payloads but transit+json is zippy. The abstraction also handles value de-duplication and has a human-readable verbose writer.
No, it's close to S-expressions, but it's not a programming language like Lisp.
> just with curly braces instead of parenthesis
Well, and more syntax than S-expressions: it's got both objects and arrays as fundamental structures instead of just lists, and it has commas as noise characters.
> it's got both objects and arrays as fundamental structures instead of just lists
I'm bit sad that various lisps never standardized on a format for this; had they, then maybe we would have S-expressions as a popular data interchange format.
Perhaps more like EDN since it doesn't have a runtime. But yeah, it's s-exps with curly braces. Which in my opinion, look worse than round parentheses … but that's opinion
I really like edn. I wish it were more widely used.
It hits a sweet spot for me between yaml and json. Yaml is easy to type/read, but I feel it's a bit too complex on the parsing side. And json is a pain to type, so I'm reluctant to use it for human entered configuration files.
Being 'more modern' means Mark takes a JS-first or web-first approach in its design. Whether we like it or not, JS has dominated the web. JSON is successful, partly because it takes a JS-first approach. Mark inherits this approach.
I would have rather said it's like QML language (which is used as the basis for Qt QML UI language). Can't find the link to the reference for plain QML. QML is like JSON, but with typed objects, and objects can have children in turn, so you can create tree structures from objects. It's actually very nice, I wish it had parsers for more languages.
> Does this mean I'm so out of date with JS that this syntax is actually legit JS? Or does Mark run its own parsers, at which point it's just like sexps, except it uses the "more modern" curly brace instead of "less modern" parenthesis?
Firstly, I highly respect Lisp personally, and I have no intention of downplaying it. As some have seen, the Lisp spirit is actually in the design of Mark.
Secondly, to clarify what I mean by 'being more modern'. Of course, it does not mean changing from () to <> or {}, will make it more modern or something better.
Being 'more modern' means Mark takes a JS-first or web-first approach in its design. Whether we like it or not, JS has dominated the web. JSON is successful, partly because it takes a JS-first approach. Mark inherits this approach.
Being JS-first, means there'll be least adoption barrier in web.
Being JS-first, of course does not mean JS-only. Mark is designed to be generic and used by other programming languages like JSON.
It's literally common lisp down to the use of pre-expressions with no binding as pragmas. It's like lisp someone dropped on a char and now all the parenthesis have a funny bump.
But it's not literally lisp in the sense that the meta-syntactic stuff isn't there.
Lisp has strong typing, so 1 is 1, not "1" or #\1, which, unless mark has a built in way of annotating types doesn't give this any advantages over s-expressions.
One major weakness of JSON is lack of a corresponding "infoset"; that is, an equivalence predicate. When are two JSON blobs "the same"? There's no sign of anything like this here.
Another is the lack of support for binary data. There's no sign of support for binary data here.
Finally, there's this claim:
> The advantage of Mark over S-expressions is that it is more modern, and can directly run in browser and node.js environments.
Is it more modern? I don't think I care.
Can it directly run in browser and node.js environments? What does that mean? It seems to need a parser. But then, S-expression parsers certainly directly run in browser and node.js environments.
---
IMO, SPKI SEXPs are much more sensible than this design and many, many other designs:
> IMO, SPKI SEXPs are much more sensible than this design and many, many other designs
Yes, yes, ten thousand times yes! I really don't understand why, over two decades hence, the world has stuck with XPKI & ASN.1, and has invented XML & JSON, when SPKI solved the PKI problem for good & canonical S-expressions solved the flexible- and human-readable–data-exchange problems for good.
Since you both seem to know the spec: how would you encode key/value pairs? Or would you have to have a list of nested lists, like
(my_dict (key value) (key value) (key value))
Un-ordered qualities for data can be useful (e.g. they allow you to reorder data to stream "important" stuff first), but I don't see it anywhere in here.
Each existing format have advantages and disadvantages for particular purposes.
Benefit of HTML: You can actually write it by hand and easily see where each element begins and ends, even when the document is longer than a screenfull. Mark has the "}}}}} problem with larger documents, so it is not as suitable for human-written markup.
It is not clear to me how mixed content like <cite>Hello <i>world</i></cite> is expressed in Mark. I expect it will be pretty convoluted.
Benefits of JSON: Maps directly to simple data structures: List, dictionaries and simple values. Similar data structures are supported in almost any language. Mark has "type names" and anonymous text content which complicates serialization and serialization a lot, and is sure to give interoperability (and perhaps security) problems.
So - worst of both worlds? Instead of tying to be an overall worse alternative to all the formats, they should rather focus on a specific niche where Mark can be a better alternative.
Take configuration files, for example. They don't have large amount of textual content like HTML, and they don't need to be transferred between disparate systems.
{size width:100 height:100}
vs
<size width="100" height="100"></size>
vs
{"size": {"width":100,"height":100 }}
In this case, the Mark syntax is simpler and cleaner. Mixed content is not needed, which would make the format simpler. Yeah it is basically the same as S-expressions, but that is not a bad thing.
The HTML example is much better than "}}}}} though, since you can e.g. add a new item at the end of the list without needing a specialized editor to locate the right position. This is one of the reasons for the redundancy in repeating the tag name in the end-tag. In theory Lisp should have the same problem, but usually code (hopefully) rarely have nested blocks larger than a screen, so it is not a big issue in practice, even if )))) looks ugly. Bottom line is code have a different structure than typical hypertext documents, so just because a notation is suitable for one does not mean it is suitable for the other.
HTML has the problem of </div></div></div></div></div></div></div>. Lisp has the problem of '))))))))'. JSON has the problem of '}}}}}}'. And YAML has the problem of deep indentation.
When it comes to worse-case scenario, no one wins. :-(
Oh, that is pretty cool. I didn't know about json5. This would also be quite nice for config files. Regular json is not nice for config files due to lack of comments.
Json5 is still not as "editable" as it looks though. You need to separate values with comma (except the last value), so there is more syntactic noise. So you get:
{
size: {width:100, height:100 /*yay*/},
}
This is not an issue when the text is machine-generated (as Json typically is), but is an issue when it is edited by hand as config files often is.
Comparing {mark} to XML, it doesn't seem to support namespaces which makes the claim to be extensible somewhat dubious. How am I supposed to add custom objects without risking name clashes? Namespaces also make XML kind of fully typed without being tied to a single programming language.
Another strength of XML is support for mixed content which seems rather awkward in {mark}. The following
<p>Some <b>bold</b> text</p>
apparently needs to written as
{p 'Some' {b 'bold'} 'text'}
It would be more honest to mark support for mixed content as "verbose" in the feature table.
Besides, the name {mark} seems like a bad idea. How could you find relevant results when searching for {mark} using a search engine?
I think 'less verbose' just means 'no end tags'. Which I guess is great if you don't mind a long string of brackets at the end of your document.
While it would be cool to have something that was like JSON but could deal with complex documents, I also don't see how this is a huge improvement over XML.
Defining the type of objects is a must when you want to exchange things in a strongly typed environment (Java on the server, TypeScript on the client, for ex).
So +1 for {mark}.
Do you handle multiple typing?
(We use that a lot in Neo4J, and we think it is really neat)
Another comment:
Coming from a Semantic Web background, and using N3 as the exchange format and N3.parse() as my client-side lib, I would advise to have a UID parameter to uniquely identify objects, and a refId syntax, so any parameter can reference some other objects of the data structure. That helps when you want to transmit a graph [1].
My humble 2 cents.
[1]: I would add that it is also useful when you retrieve some refIds that are not defined in the current data structure. You can then ask the server to dereference these refIds, and send another (portion of the) graph, that you can connect with the existing data structure.
Let's say you transmit an object of type Person, that is also a Student and a MartialArtist. Your inheritance graph may define that a Student is also a Person. So not sending the Person type could be fine. But would you define a common subtype for Student+MartialArtist, just because your data serialization handles only one single type per object? Obviously no! You want to send your object with types "Student" and "MartialArtist". I.e multiple types.
I don't understand this part of the readme:
> The advantage of Mark over S-expressions is that it is more modern, and can directly run in browser and node.js environments.
Does this mean I'm so out of date with JS that this syntax is actually legit JS? Or does Mark run its own parsers, at which point it's just like sexps, except it uses the "more modern" curly brace instead of "less modern" parenthesis?
http://blog.cognitect.com/blog/2014/7/22/transit http://cognitect.github.io/transit-tour/
cool project though, good to see s-expressions become more popular
No, it's close to S-expressions, but it's not a programming language like Lisp.
> just with curly braces instead of parenthesis
Well, and more syntax than S-expressions: it's got both objects and arrays as fundamental structures instead of just lists, and it has commas as noise characters.
Well, Common Lisp has both of those as fundamental atoms:
The former creates an instance of a FOO struct with its BAR slot set to 3; the latter is a 3-item array.> it's got both objects and arrays as fundamental structures instead of just lists
I'm bit sad that various lisps never standardized on a format for this; had they, then maybe we would have S-expressions as a popular data interchange format.
Which can easily be added to sexps (see EDN).
https://github.com/edn-format/ednhttps://learnxinyminutes.com/docs/edn/
It hits a sweet spot for me between yaml and json. Yaml is easy to type/read, but I feel it's a bit too complex on the parsing side. And json is a pain to type, so I'm reluctant to use it for human entered configuration files.
var obj = Mark.parse(`{div {span 'Hello World!' }}`);
It has its own parsing and stringify library it looks like: https://github.com/henry-luo/mark#markjs
Secondly, to clarify what I mean by 'being more modern'. Of course, it does not mean changing from () to <> or {}, will make it more modern or something better.
Being 'more modern' means Mark takes a JS-first or web-first approach in its design. Whether we like it or not, JS has dominated the web. JSON is successful, partly because it takes a JS-first approach. Mark inherits this approach.
Being JS-first, means there'll be least adoption barrier in web.
Being JS-first, of course does not mean JS-only. Mark is designed to be generic and used by other programming languages like JSON.
Looks like s-expressions to me and it isn't legit JS.
But it's not literally lisp in the sense that the meta-syntactic stuff isn't there.
In Lisps:
- values have types (bool, symbol, number, list, array, structs, functions, ...)
- variables have by default one type: union of all the above
- in Common Lisp, you can restrict the types of values allowed in a variable
> but this uses type declarations
I must have missed this. If it's not just what struct-like entities are allowed in the markup, where did you see that?
Another is the lack of support for binary data. There's no sign of support for binary data here.
Finally, there's this claim:
> The advantage of Mark over S-expressions is that it is more modern, and can directly run in browser and node.js environments.
Is it more modern? I don't think I care.
Can it directly run in browser and node.js environments? What does that mean? It seems to need a parser. But then, S-expression parsers certainly directly run in browser and node.js environments.
---
IMO, SPKI SEXPs are much more sensible than this design and many, many other designs:
https://people.csail.mit.edu/rivest/Sexp.txt
Yes, yes, ten thousand times yes! I really don't understand why, over two decades hence, the world has stuck with XPKI & ASN.1, and has invented XML & JSON, when SPKI solved the PKI problem for good & canonical S-expressions solved the flexible- and human-readable–data-exchange problems for good.
Benefit of HTML: You can actually write it by hand and easily see where each element begins and ends, even when the document is longer than a screenfull. Mark has the "}}}}} problem with larger documents, so it is not as suitable for human-written markup.
It is not clear to me how mixed content like <cite>Hello <i>world</i></cite> is expressed in Mark. I expect it will be pretty convoluted.
Benefits of JSON: Maps directly to simple data structures: List, dictionaries and simple values. Similar data structures are supported in almost any language. Mark has "type names" and anonymous text content which complicates serialization and serialization a lot, and is sure to give interoperability (and perhaps security) problems.
So - worst of both worlds? Instead of tying to be an overall worse alternative to all the formats, they should rather focus on a specific niche where Mark can be a better alternative.
Take configuration files, for example. They don't have large amount of textual content like HTML, and they don't need to be transferred between disparate systems.
vs vs In this case, the Mark syntax is simpler and cleaner. Mixed content is not needed, which would make the format simpler. Yeah it is basically the same as S-expressions, but that is not a bad thing.And HTML has a problem of </span></li></ul></div></div></div></div></body></html>, all spread over nine different lines, one tag per line.
Take a look at https://github.com/keithj/alexandria/blob/master/definitions... which is Lisp code styled in a standard manner. I don't see any problem there.
When it comes to worse-case scenario, no one wins. :-(
Json5 is still not as "editable" as it looks though. You need to separate values with comma (except the last value), so there is more syntactic noise. So you get:
This is not an issue when the text is machine-generated (as Json typically is), but is an issue when it is edited by hand as config files often is.Another strength of XML is support for mixed content which seems rather awkward in {mark}. The following
apparently needs to written as It would be more honest to mark support for mixed content as "verbose" in the feature table.Besides, the name {mark} seems like a bad idea. How could you find relevant results when searching for {mark} using a search engine?
XML Namespace seems to have a lot issues, thus Mark does not want to enforce something exactly following it.
Namespace in Mark, currently, is left upto the application user to define it.
We might be able to come up with a better way to define namespace.
As for the name, you can just use Mark. I use '{mark}' as an alternative name, to make it more graphical, more impressive.
XML Namespaces is syntactic vinegar.
Less is more.
Ok sure, but does it have schematron,rng, or some sort of validation? How about transformations? Xpath?
There's already a transformation library - Mark Template (https://github.com/henry-luo/mark-template) in beta release.
Mark at the moment supports CSS selector. I'm also thinking about a new Mark-specific selector.
Mark is very new. A lot to be done!
While it would be cool to have something that was like JSON but could deal with complex documents, I also don't see how this is a huge improvement over XML.
Deleted Comment
There seems to be a ton of s-expression parsers in npm already, that can run in browser and in node.js: https://www.npmjs.com/search?q=s-expression
Besides being able to run in js environments, what else does {mark} bring over s-expressions?
- A wise man on the Internet once said
Another comment: Coming from a Semantic Web background, and using N3 as the exchange format and N3.parse() as my client-side lib, I would advise to have a UID parameter to uniquely identify objects, and a refId syntax, so any parameter can reference some other objects of the data structure. That helps when you want to transmit a graph [1].
My humble 2 cents.
[1]: I would add that it is also useful when you retrieve some refIds that are not defined in the current data structure. You can then ask the server to dereference these refIds, and send another (portion of the) graph, that you can connect with the existing data structure.