Nit: the technical term for "integrated language" mentioned here is domain-specific language. People spin off DSLs from Ruby all the time.
Incidentally, one could argue that SQL is the most widespread DSL there is.
Edit: The author mentions this is basically a DSL in his post, which I missed the first time around. Not sure why he didn't just stay with that nomenclature though.
The distinction being drawn here is between a DSL which is defined in terms of pre-existing syntax, and one which defines its own syntax.
The "integrated languages" that are discussed do not need to be stored in strings, or have some sort of special pre-processing step to coexist with the primary language. In Clojure, a Cascalog query is a first-class structure simply by virtue of being defined in terms of Clojure syntax. Integrating LINQ into C#, on the other hand, required modifying both the compiler and IDE. And as pointed out in the OP, SQL is a second-class citizen pretty much everywhere you look, which leads to issues like injection.
Metalua, Nemerle, Boo (and even Perl to some extent) ... among other languages have support for compile time macros / interacting with the compiler's pipeline.
def res = linq <# from c in customers where c.City == "London" #>;
Of course, it requires a prefix "linq" + the actual code to be delimited ... but that's not a requirement, as that macro could've been built to look exactly as the C# equivalent (the current form being chosen to prevent ambiguities both for the compiler and the programmer).
So the argument that you need Lisp-like syntax for adding syntax to a language without storing it in strings or through pre-processing ... is bullshit.
The only difference between a language like Nemerle and Lisp is that in Lisp a macro is easier to write, while in Nemerle you need some knowledge about the compiler's parser / AST and pipeline.
But having easy-to-write macros ... I'm not sure it's such a good thing ... and in Nemerle you're not limited in the kind of syntax you can add to the language. In fact Nemerle is a simple core language where many of the useful things in it are built as macros.
This deficiency of not being "integrated" is also true to a lesser degree in Ruby.
Ultimately, you get the thing to behave how you want with the syntax you want, but under the hood you're not getting code as data that you can manipulate as freely and naturally as you can in lisp. Instead you hack on the language's object models and method dispatch to get the syntax to line up with the one you have in your head.
In this sense, beauty is only skin deep in Ruby when it comes to DSLs. (It's nice and all, but it's apples to oranges vs lisps.)
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.
I 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.
Yes 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.
I'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.
I 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.
This 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.
Similar, but different. Operator overloading doesn't affect evaluation. You know immediately what is being evaluation now and what isn't, not so in Lisp, and this matters a great deal.
You 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.
Actually, 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:
> 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.
> 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.
If 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))
> 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.
Incidentally, one could argue that SQL is the most widespread DSL there is.
Edit: The author mentions this is basically a DSL in his post, which I missed the first time around. Not sure why he didn't just stay with that nomenclature though.