8 ms·
A different take on S-expressions
- kazinator 1y agoWhere is the grotesque code to parse these rectangles? :)
- tearflake 1y ago[dead]
- phoe-krk 1y agoLisp programmer here. Traditional S-expressions, by their definition, ignore most of whitespace; additionally, reading sexprs is always a linear operation without the need to backtrack by more than one character. The suggestion from this post violates both assumptions by introducing a 2D structure to code. To quote this post's examples, it requires the multiline string in (fst-atom """ trd-atom) 00001 00002 00003 """ to be fully read before TRD-ATOM. It also forces the reading function to jump up and down vertically in order to read the structure in * ( ) * e ( ) ( ) * q m ( ) p ( ) * u a a o a 2 * l w * The author also states that (eq (mul (a a)) (pow (a 2))) is less readable than * ( ) * *eq* ( ) ( ) * *mul* ( ) *pow* ( ) * *a* *a* *a* *2* * * Then there's the ending passage: > we hope that the introduced complexity is justified by the data readability expressed this way. I cannot force myself to read this post as anything but a very poor Befungesque joke.
- tgv 1y agoA normal tree would be easier to read eq mul pow a a a 2
- derriz 1y agoTurned 90, maybe? eq: mul: a a pow: a 2
- tgv 1y agoThat's the classical LISP way of doing it: (eq (mul a a) (pow a 2)) or (eq (mul a a ) (pow a 2 ) )
- hyperhello 1y agox*x == pow(x,2)
- derriz 1y agoWe have a winner! Actually, I'd suggest a slight improvement: x*x = x^2
- xigoi 1y agox · x = x²
- TacticalCoder 1y ago(== (* x x) (pow x 2))
- amno 1y ago(= * x x ^ x 2)
- unrealhoang 1y agono yaml programming please :(
- uncircle 1y ago
- unstruktured 1y agoThanks for restoring my sanity. Was quite confused of the value added by the author.
- velcrovan 1y agoIt gets worse/better. Since Racket allows you to hook your own reader in front of (or in place of) the default reader, you can have things like 2D syntax: #lang 2d racket (require 2d/match) (define (subtype? a b) #2dmatch ╔══════════╦══════════╦═══════╦══════════╗ ║ a b ║ 'Integer ║ 'Real ║ 'Complex ║ ╠══════════╬══════════╩═══════╩══════════╣ ║ 'Integer ║ #t ║ ╠══════════╬══════════╗ ║ ║ 'Real ║ ║ ║ ╠══════════╣ ╚═══════╗ ║ ║ 'Complex ║ #f ║ ║ ╚══════════╩══════════════════╩══════════╝) https://docs.racket-lang.org/2d/index.html https://docs.racket-lang.org/2d/index.html
- perrygeo 1y agoThat's amazing and terrible at the same time. I love it.
- phoe-krk 1y agoTruth be told, you can intercept the reader in Common Lisp, too, and here it actually makes some sense since the 2D value is immediately visually grokkable as an ASCII-art table. The proposed 2D sexpr notation does not have this.
- f1shy 1y agoYes that part must be a joke! I’ve seen dozens of attempts to make S-Exp “better” even the original M-Exp. I also did some experiments myself. But at the end, I come back to goo’ol s-exp. Seems to be a maximum (or minimum) found just perchance.
- tearflake 1y agoHere is another example, an axiom from propositional logic: (impl (impl p (impl q r)) (impl (impl p q) (impl p r))) which, vertically indented in a transposed block, looks like this: * ( ) * i ( ) ( ) * m i p ( ) i ( ) ( ) p m i q r m i p q i p r l p m p m m * l p l p p * l l l * which, using transposed lines within the transposed block, finally looks like this: * ( ) * *impl* ( ) ( ) * * *impl* *p* ( ) *impl* ( ) ( ) * *impl* *q* *r* *impl* *p* *q* *impl* *p* *r* * This time I won't make any judgements. Could be good, could be bad, you decide.
- exeldapp 1y agoNot sure if that example helps. You can make any programming language hard to read without some basic formatting. The way I would write the sexpr would be: (impl (impl p (impl q r)) (impl (impl p q) (impl p r))) It's clear when each section begins and ends and doesn't require complex parsing rules.
- tearflake 1y agoThat looks clean, can't argue that.
- stray 1y agoFor very large values of "somewhat peculiar"...
- tearflake 1y agoChanged the "somewhat" to "very" in the document, thank you.
- TOGoS 1y agoThis is fine and interesting, but what I think is lacking in S-expression isn't funky vertical syntax, but a way to directly represent objects that are not lists. Otherwise one needs to invent some representation on top of S-expressions (and then a list isn't necessarily a list anymore; everything goes through an additional layer of encoding/decoding, losing the elegance of S-expressions), or use some extension syntax (usually involving '#'), which varies from language to language and might not even be interpreted by the reader (but logically expand to some list expression that needs to be interpreted again later, so you're not really any better off than with the first approach). I kind of want something like, to borrow JSON-like syntax and gloss over namespacing issues: (foo . {type: listy-cons-cell head: bar tail: (baz quux)}) ...which would be another way to say (foo bar baz quuz), but would make it possible to represent any data structure you like at the same level as atoms, strings, and lists.
- drob518 1y agoSee Clojure’s reader syntax: https://www.clojure.org/reference/reader https://www.clojure.org/reference/reader You can have vectors, hash maps, and sets in addition to lists, symbols, and keywords.
- kgwxd 1y agoI don't get why anyone even tries after Clojure. They got it 100% right. It's easier to read than anything else, and still super simple to parse. Commas are whitespace, use them or don't, where ever you want. Namespaced keywords are great. The data structures themselves act as functions. It's just... done.
- drob518 1y agoYep. There are a couple of places where I think Clojure made the wrong choices, but they are few and far between. Overall, there is so much that was done correctly. I don’t even know if I could program without persistent data structures anymore, for instance.
- deleted 1y ago[deleted]
- fn-mote 1y agoRelated but not the same at all, Racket has a 2D syntax (add on mode) that gives a different way to program tables where the output depends on two different inputs. https://docs.racket-lang.org/2d/ https://docs.racket-lang.org/2d/
- jazzyjackson 1y agoI'll piggyback with my gruesome JSONification of S-expressions. I kinda liked having two kinds of braces [straight] and {curly} to differentiate arrays and objects, and I did have a event-loop-based "parallel" scheduler working to process a tree as soon as prerequisites were fulfilled. I might pick up the old project again someday, I just got hung up on how I wanted to handle error bubbling. With a vertical script like japanese you could easily rotate the whole program 90 degrees to the right (as shown at the bottom of the landing page) https://web.archive.org/web/20240904091932/https://lookalive.software/ https://web.archive.org/web/20240904091932/https://lookalive... { "#!join": [ [ "A triangle with side of ", "#& side", " and base of ", "#& base", "has a hypotenuse of", { "#!sqrt": [ [ { "#!sum": [ [ "#!multiply side side", "#!multiply base base" ] ] } ] ] } ] ] }
- drob518 1y agoAs a Lisp programmer, just no.
- tearflake 1y agoThank you for the criticism. Lots of lispers share your opinion.
- chc4 1y agoThese definitely are extensions that you could add to S-expressions, no one can disagree there.
- somewhereoutth 1y agodispense with the parentheses: (eq (mul (a a)) (pow (a 2))) becomes eq mul a a pow a 2
- danielrico 1y agoLispython I should trademark this name.
- deleted 1y ago[deleted]
- tmtvl 1y agoThat's Wisp, I don't care for it, but people who really like to assign semantic meaning to precise counts of invisible characters may find it interesting.
- derriz 1y agoAbsolutely no counting is required at all so I think your joke falls a little flat. Our visual system has the ability to detect implied straight lines (and other simple geometric outlines) from very small clues. Therefore "seeing" the vertical lines implied by the indentation is effortless - so it's immediately obvious which elements belong to each other. Indentation is an incredibly valuable "brain" hack that manages to instantly communicate hierarchy, not something to be sneered at. We have no such innate ability to match parenthesis - determining hierarchy in a jumble of open and close parenthesis requires precise counting or, typically these days, tool/editor/IDE support.
- thaumasiotes 1y ago> Absolutely no counting is required at all so I think your joke falls a little flat. Really? How do you see the difference between "TAB" and "SPACE SPACE TAB"?
- deleted 1y ago
- pkilgore 1y agoIs this.... is this a joke?
- davesque 1y agoThis is bonkers and I love it.
- tearflake 1y agoIkr? People should loosen a bit, why should everything be so serious?
- gglitch 1y agoIs the empty list also an s-expression? If so, would it not be slightly more correct to define s-expressions as either an atom or a list of zero or more s-expressions?
- wk_end 1y agoAn empty list is atomic! What could it break down into?
- uncircle 1y agoI can only ask “…but why?” I don’t get what this complexity buys us.
- tearflake 1y agoSolves a mess with closing parens. But I'm not sure if it is worth of hassle. Anyway, it exists.
- luizfelberti 1y agoFeels like the complete opposite s-expressions which are the easiest possible thing to parse, this sounds like a complete nightmare to write a parser for. It might even be easier to treat the input string as a 2D grid than as a sequence and have a parsing head that behaves like a 2x2 convolutional kernel... This would make for either a great Advent of Code, or a nightmare interview question, I love it.
- tearflake 1y agoActually it's quite simple. We parse from left to right. When we hit EOL, we return to the beginning of line and increase Y by one. Blocks are parsed in the following way: when we get the beginning count of block opening characters, we move Y by one, loop right while whitespace, until we encounter ending count of block characters. In transposed block, we just switch X and Y, it is easily done with pointers, and use the same code.
- phoe-krk 1y ago(fst-atom """ trd-atom frt-atom """ 00001 asdf 00002 """ fth-atom) qwer 00003 hahaha zxcv """ hehehe """ hohoho """ I'm not sure I'd like the above to be parseable.