4 ms·
Actually, Lisps conveniently sidestep the whole issue by refusing to have ANY syntax. Which is fine if you like it. But you could just as easily argue lisp is
by kgo 16y ago
Actually, Lisps conveniently sidestep the whole issue by refusing to have ANY syntax. Which is fine if you like it. But you could just as easily argue lisp is bad for DSLs because you can't, for example, define an infix operator.
- nathanmarz 16y agoHere's infix math from the Incanter library for Clojure: http://data-sorcery.org/2010/05/14/infix-math/ http://data-sorcery.org/2010/05/14/infix-math/
- mquander 16y agoYou can change prefix expressions to infix with a macro, if you like; didn't you read SICP? Your DSL can look however you want it to, as long as there are some parentheses around the ends of it.
- kgo 16y agoExcept you still need to give the macro a name, I don't think you can just write a macro that figures out: (1 + 2) (x = 1 + 2) It needs to be something like (!! 1 + 2) And you need to have spaces. (1+4/5) Won't work. And operator precedence is do-able, but a bitch. Etc... Etc...
- Xurinos 16y agoActually, in CL, you can write a "reader" macro that interprets your first infix examples. You probably do not want to because overriding ()s (as opposed to overriding maybe []s or {}s) is complicated. But you can. As for the issue of spaces, 1+4/5 is just a symbol, which you can interpret as a string, which you can then parse back to symbols. All that said, if I really wanted infix math, I would probably just make something that interprets this: {1 + {2 / 3}{4+5}} Or if I really love my parentheses... (!! (1 + (2 / 3)(4+5)))
- davidw 16y ago> As for the issue of spaces, 1+4/5 is just a symbol, which you can interpret as a string, which you can then parse back to symbols. You can write a parser in any language; nothing magical about Lisp there.
- Xurinos 16y ago> You can write a parser in any language; nothing magical about Lisp there. Your statement is correct; it is just misleading. First, it is irrelevant in that we are talking about parsing the syntax of your language and producing code; not "any language" can do that. You would also have to write an eval for the many languages that do not have an eval. See SICP for an introduction to eval-apply logic. Second, it disregards ease of parsing. It is easier to write a parser in Lisp to translate Lisp-like syntax into Lisp code than to write a parser in another language to translate that language's syntax into that language's code (and exceptions to this are because the language was based on Lisp). This has to do with basic Lisp syntax being a syntax tree and is aided by the CL standard providing many tools for parsing. So yes, you can complicate things a bit by mashing your symbols together, but that's just one extra parsing pass (insert spaces around operators). One READ-FROM-STRING later, and you have a symbol tree. In another language, it might be a series of complicated lexx statements and functions where the language relearns how to do simple addition.
- davidw 16y ago> It is easier to write a parser in Lisp to translate Lisp-like syntax into Lisp code than to write a parser in another language to translate that language's syntax into that language's code Yeah, that's a neat thing about lisp, but it wasn't what the OP really said - he was talking about parsing a random string. Incidentally, I would be curious to get a design guy - one who really knows little about code - to look at blocks of code in different languages and give us his opinion. I have suspicions about what he might say, but it'd be a fun experiment.
- fogus 16y agoIf you don't want the weight of pulling in Incanter libs, here's a pair of functions for infix ops* in Clojure: (def && #(and % %2)) (def || #(or % %2)) (def *rank* (zipmap [- + * / < > && || =] (iterate inc 1))) (defn- infix* [[a b & [c d e & m]]] (cond (vector? a) (recur (list* (infix* a) b c d e m)) (vector? c) (recur (list* a b (infix* c) d e m)) (ifn? b) (if (and d (< (*rank* b 0) (*rank* d 0))) (recur (list a b (infix* (list* c d e m)))) (recur (list* (b a c) d e m))) :else a)) (defn infix [& args] (infix* args)) * from my unfix lib http://fogus.me/fun/unfix http://fogus.me/fun/unfix
- scott_s 16y agoI think "Lisp has no syntax" is an unfortunate meme. Lisp has a syntax. It's a very simple syntax for defining trees, and you're basically using it to write the abstract syntax tree for your program, but it still has a syntax.
- kgo 16y agoYes of course, but in the context of a DSL, you're not really defining a new syntax. You've still got an AST at the end of the day. And of course, this isn't an attack on lisp. If it works for you, cool. But I just don't see how that distinguishes itself from a ruby DSL like say rspec. I think the nicest feature of lisp DSLs is that lisp doesn't have the concept of an operator, and most langaguages make if difficult to define a function called or <- or something like that. But you can do that in Haskell or or ML, it's not really exclusive to S-exps.
- scott_s 16y agoI'm unfamiliar with rspec, but the major difference between designing and implementing DSLs in Lisps versus other languages is ease of code generation. That is, actually generating new code based on what the user of the DSL supplies. In Lisp, this is done because it's trivial to receive the AST that defines what the user wants to do. Then you can generate code directly based on that AST. No need for reflection or any such trickery because it's all just lists of list. In most other languages, if that sort of transformation is even possible, it is much less direct.
- ScottBurson 16y agoI think it's more accurate to say that Lisp has a metasyntax rather than a syntax. Each special form and macro, including user-written macros, has its own syntax; but all of these syntax are layered on top of the standard metasyntax.
- gnaritas 16y agoThis is a good point, and it's one of the things I don't like about Lisp. You can't know the semantics of evaluation without memorizing each form or having a doc handy. The code at the call site itself is not enough.
- bad_user 16y ago> Lisps conveniently sidestep the whole issue by refusing to have ANY syntax. I'm not sure why people repeat that, but Lisp has syntax ... In the same way Xml, Yaml, Json have syntax ... plus it has operators that do stuff, like: quote / eval / for defining methods / for defining macros. Sure, a serialization format for what are basically syntax-trees is lighter than for a language that requires a LALR parser ... but you have to limit yourself to that serialization format in your DSLs.