Dear friends,
I'm starting to write a chapter for an upcoming book on domain specific languages. The chapter is called (tentatively):
Extensible languages -- blurring the distinction between DSLs and GPLs
GPL meaning General Purpose Language in this context ;-)
My intention is to demonstrate how the task of implementing a DSL is made easier when it boils down to an extension or subset of your original GPL (hence reusing its infrastructure), instead of being a totally different language, only written on top of the other.
Obviously, I'm going to illustrate this with Common Lisp, and I intend to speak of dynamicity (not only dynamic typing, but in general all things that can be deferred to the run-time), introspection, intersession, structural or procedural reflexivity, meta-object protocols (not sure about this one), macro systems and JIT-compilation. Also, more specifically to Lisp, reader macros (compiler macros maybe?), the condition system (and its ability to *not* unwind) and restarts.
Right now, I would like to know if any of you have DSL "pearls", nice examples of DSLs that you have written in Lisp by using some of its features in a clever or elegant way. I would also gladly accept any point of view or comment on what's important to mention, in terms of design principle or anything else, things that I may have missed in the list above.
Thank you very much in advance!
LOOP macro
On Wed, Jul 20, 2011 at 6:32 AM, Didier Verna didier@lrde.epita.fr wrote:
Dear friends,
I'm starting to write a chapter for an upcoming book on domain specific languages. The chapter is called (tentatively):
Extensible languages -- blurring the distinction between DSLs and GPLs
GPL meaning General Purpose Language in this context ;-)
My intention is to demonstrate how the task of implementing a DSL is made easier when it boils down to an extension or subset of your original GPL (hence reusing its infrastructure), instead of being a totally different language, only written on top of the other.
Obviously, I'm going to illustrate this with Common Lisp, and I intend to speak of dynamicity (not only dynamic typing, but in general all things that can be deferred to the run-time), introspection, intersession, structural or procedural reflexivity, meta-object protocols (not sure about this one), macro systems and JIT-compilation. Also, more specifically to Lisp, reader macros (compiler macros maybe?), the condition system (and its ability to *not* unwind) and restarts.
Right now, I would like to know if any of you have DSL "pearls", nice examples of DSLs that you have written in Lisp by using some of its features in a clever or elegant way. I would also gladly accept any point of view or comment on what's important to mention, in terms of design principle or anything else, things that I may have missed in the list above.
Thank you very much in advance!
-- Resistance is futile. You will be jazzimilated.
Scientific site: http://www.lrde.epita.fr/~didier Music (Jazz) site: http://www.didierverna.com
pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
Not sure if I'd call it a "pearl", but here's one data point. Hell, I'm not even sure if this counts as a DSL or not, most of what I know of DSLs comes from blog posts and ruby fanatics.
I had a legacy electronic voting system (IIS/VBscript/SQL Server) and wrote some lisp to configure elections. The lisp code output the T-SQL needed to configure the election, and then the VBScript was driven from that data.
Here's an abbreviated example:
(with-election ("3/29/2011 8:00PM" "3/31/2011 7:00PM" "Law") (with-position ("President" :types '("Law Undergrad")) (make-candidates "name 1" "name 2" "name 3")) (make-referendum "Amendment 1" "<strong>Thing To Change</strong> <p>HTML body for the voting UI</p>"))
The :types indicated who was eligible to vote for the position, and there were some other options to those macros. The with-* forms are macros to setup the context, and the make-* functions generate the appropriate SQL strings and write them to a stream (usually a file).
The macros in the sample do a few things:
1. with-election: sets a dynamic variable in lisp for the stream all the SQL strings are written to in make-* functions, allowed easy testing of make-* functions via the REPL 2. with-position: sets a variable in the T-SQL script used by INSERT statements produced by make-candidates. This actually macroexpands to imperative code: (progn (make-position ...) (make-candidates ...)). The macro usage is mostly to get indentation and visually group the relationships
So, not sure if I'd call this a pearl and it's arguably a DSL, but it's sure a lot easier for me to use than direct T-SQL or the ridiculous VBScript web interface.
Other things I've used that might fall into the DSL category:
* cl-who http://weitz.de/cl-who/ * cl-interpol http://weitz.de/cl-interpol/ * clsql's SQL-READER syntax (http://clsql.b9.com/manual/ref-syntax.html)
HTH,
Ryan Davis Acceleration.net Director of Programming Services 2831 NW 41st street, suite B Gainesville, FL 32606
Office: 352-335-6500 x 124 Fax: 352-335-6506
On 7/20/2011 9:32 AM, Didier Verna wrote:
Dear friends,
I'm starting to write a chapter for an upcoming book on domain specific languages. The chapter is called (tentatively):
Extensible languages -- blurring the distinction between DSLs and GPLs
GPL meaning General Purpose Language in this context ;-)
My intention is to demonstrate how the task of implementing a DSL is made easier when it boils down to an extension or subset of your original GPL (hence reusing its infrastructure), instead of being a totally different language, only written on top of the other.
Obviously, I'm going to illustrate this with Common Lisp, and I intend to speak of dynamicity (not only dynamic typing, but in general all things that can be deferred to the run-time), introspection, intersession, structural or procedural reflexivity, meta-object protocols (not sure about this one), macro systems and JIT-compilation. Also, more specifically to Lisp, reader macros (compiler macros maybe?), the condition system (and its ability to *not* unwind) and restarts.
Right now, I would like to know if any of you have DSL "pearls", nice examples of DSLs that you have written in Lisp by using some of its features in a clever or elegant way. I would also gladly accept any point of view or comment on what's important to mention, in terms of design principle or anything else, things that I may have missed in the list above.
Thank you very much in advance!
I think the chapter on binary data types in PCL is a reasonable example of a certain kind of DSL. Is this whole book about DSLs? I'll be interested to see it. And glad they're getting at least one Lisper.
-Peter
On Wed, Jul 20, 2011 at 6:32 AM, Didier Verna didier@lrde.epita.fr wrote:
Dear friends,
I'm starting to write a chapter for an upcoming book on domain specific languages. The chapter is called (tentatively):
Extensible languages -- blurring the distinction between DSLs and GPLs
GPL meaning General Purpose Language in this context ;-)
My intention is to demonstrate how the task of implementing a DSL is made easier when it boils down to an extension or subset of your original GPL (hence reusing its infrastructure), instead of being a totally different language, only written on top of the other.
Obviously, I'm going to illustrate this with Common Lisp, and I intend to speak of dynamicity (not only dynamic typing, but in general all things that can be deferred to the run-time), introspection, intersession, structural or procedural reflexivity, meta-object protocols (not sure about this one), macro systems and JIT-compilation. Also, more specifically to Lisp, reader macros (compiler macros maybe?), the condition system (and its ability to *not* unwind) and restarts.
Right now, I would like to know if any of you have DSL "pearls", nice examples of DSLs that you have written in Lisp by using some of its features in a clever or elegant way. I would also gladly accept any point of view or comment on what's important to mention, in terms of design principle or anything else, things that I may have missed in the list above.
Thank you very much in advance!
-- Resistance is futile. You will be jazzimilated.
Scientific site: http://www.lrde.epita.fr/~didier Music (Jazz) site: http://www.didierverna.com
pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
Peter Seibel peter@gigamonkeys.com wrote:
Is this whole book about DSLs? I'll be interested to see it. And glad they're getting at least one Lisper.
Yes. I'll let you know when the project is finalized.
We have been working on what we call domain oriented languages for some time ranging from the first visual programming language for the MIT programmable brick (later Mindstorms) http://www.cs.colorado.edu/~ralex/papers/PDF/VL95-LEGOsheets.pdf
to AgentCubes (a 3D environment for end-users): http://www.cs.colorado.edu/~ralex/papers/PDF/AgentCubes_JVLC_article_inpress...
Both of these programming environment are built in Common Lisp, are based on the concept of rules and have domain oriented interfaces to turn visual languages (via Lisp macros) into Lisp code.
Not sure this is what you are looking for but many people (teacher, students, ...) are using these kinds of domain oriented languages to build games and simulations: http://www.9news.com/news/local/article/202987/222/Teachers-play-video-games...
best, Alex
On Jul 20, 2011, at 7:32 AM, Didier Verna wrote:
Dear friends,
I'm starting to write a chapter for an upcoming book on domain specific languages. The chapter is called (tentatively):
Extensible languages -- blurring the distinction between DSLs and GPLs
GPL meaning General Purpose Language in this context ;-)
My intention is to demonstrate how the task of implementing a DSL is made easier when it boils down to an extension or subset of your original GPL (hence reusing its infrastructure), instead of being a totally different language, only written on top of the other.
Obviously, I'm going to illustrate this with Common Lisp, and I intend to speak of dynamicity (not only dynamic typing, but in general all things that can be deferred to the run-time), introspection, intersession, structural or procedural reflexivity, meta-object protocols (not sure about this one), macro systems and JIT-compilation. Also, more specifically to Lisp, reader macros (compiler macros maybe?), the condition system (and its ability to *not* unwind) and restarts.
Right now, I would like to know if any of you have DSL "pearls", nice examples of DSLs that you have written in Lisp by using some of its features in a clever or elegant way. I would also gladly accept any point of view or comment on what's important to mention, in terms of design principle or anything else, things that I may have missed in the list above.
Thank you very much in advance!
-- Resistance is futile. You will be jazzimilated.
Scientific site: http://www.lrde.epita.fr/~didier Music (Jazz) site: http://www.didierverna.com
pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
Prof. Alexander Repenning
University of Colorado Computer Science Department Boulder, CO 80309-430
vCard: http://www.cs.colorado.edu/~ralex/AlexanderRepenning.vcf
It seems to me that most people don't understand the rudiments of CL's ability for creating DSL's and live in the land of Blub.
If you're going to discuss creation of DSLs, it might be an idea to first relate the aspects of CL using compiler terminology.
Here are some random thoughts (not all are accurate, but represent an attempt to translate CL concepts into Blub):
- CL is a language that has Lex and Yacc built into it. You can change the syntax of CL to suit your problem.
- Lisp s-expressions are concrete parse trees.
- The CL "reader" is a scanner. You don't need to build a scanner, since CL already provides you with one.
- CL symbols are "tokens".
- The CL scanner can read programs from a number of sources - not just files - e.g. strings, keyboard, streams, etc.
- Physicists commonly create DSL's. They define a notation with which to describe a domain, then use the notation to solve problems in the domain.
- Few other languages can change their own syntax. Examples of self-modifying syntax can be found in term-rewriting systems, such as the language TXL.
- CL macros are parsers.
- CL macros are code emitters.
- CL macros are source-to-source program transformers.
- CL backquote/comma/at-sign notation is used to splice and modify concrete parse trees into other shapes.
- The CL compiler compiles s-expressions into machine code.
- If one creates s-expressions, one can use the CL compiler to compile them into machine code at runtime.
- The CL compiler is a JIT compiler.
- The CL repl interactively compiles s-expressions to machine code, then executes them, then prints the results of the execution.
- The CL language defines a rich library of operators for modifying concrete parse trees.
- To a CL'er, infix notation is just unnecessary syntactic sugar. Many novice CL'ers try to create macros that understand infix notation early on in their careers, but as they become more familiar with the power of CL, they drop the syntatic sugar and use parse trees directly.
- The CL printer contains a notation for displaying structure sharing. This facilitates debugging of optimizers which transform trees into graphs.
- To write a DSL in CL, one first writes a macro that parses s-expressions. Then, the macro is extended with backquotes to emit new s-expressions. The emitted s-expressions are automatically fed to the CL compiler and compiled to machine code.
- Unfortunately, the C language uses the name "macro" for a facility that is far less powerful than that of CL. In C, the macro facility can only parse a syntax that looks like simple symbols and function calls and a special #if syntax that is not even part of the C language definition. In CL, the macro facility can parse any s-expression and utilitize any CL function during code emission.
- With C macros, the programmer does not have the option to change the syntax of the macro language. With CL macros, the programmer has full control of the macro syntax.
- CL has the ability to link/load modules at runtime, "on the fly".
- CL invented the concept of JIT (is this factually true?).
- Forward references in CL are automatically handled by the runtime linker. The linker fixes up references on the fly to improve runtime efficiency (I know that I first saw this facility in UTAH Lisp in 1977).
- The CL scanner, compiler and linker sit in memory all (most) of the time, hence, CL is an all-in-one bundled DSL/compiler toolkit. Some CL's give you the ability to remove the compiler when creating a .exe, if you no longer need it.
- The builtin CL macroexpand function gives the programmer the ability to debug his/her DSL compiler by viewing the emitted code (much like CPP's command line option that leaves the expanded code in a text file).
- CL's rich suite of syntactic and compiler tools came about due to early AI research into automatic code generation.
- CL lambdas (closures) are thunks.
- CL closures are trampolines.
- CL closures and Scheme's call-with-continuation are the ultimate goto's. Any control flow can be modelled and compiled with these facilities.
- CL closures and Scheme's call-with-continuation can be used to create compilers using the concepts of denotational semantics.
- Cl closures are (kind of) like Smalltalk's "blocks".
- CL closures are another example of the rich language-building facilities of CL, not commonly found in most languages.
- CL closures can be used to create anonymous functions, similarly to anonymous classes used in Java.
- The facilities of CL make it possible to model and compile just about any kind of runtime semantics, including very non-linear ones, e.g. PAIP prolog.
- Prolog provides an simple way to build parsers, if efficiency is not of utmost concern. A number of prologs are available to CL programmers, so one can have the best of both worlds. [I use paip prolog to parse diagrammatic syntax.]
hth
pt
Paul gave an excellent overview.
I would also describe the ability of CL of "re-plumbing" itself (shameless plug: the DEFINER library :) ) and, of course, as a standard example from ages ago, Prolog-like languages and the slew of logic languages build on top of CL.
cheers
MA
On Jul 20, 2011, at 18:47 , Paul Tarvydas wrote:
It seems to me that most people don't understand the rudiments of CL's ability for creating DSL's and live in the land of Blub.
If you're going to discuss creation of DSLs, it might be an idea to first relate the aspects of CL using compiler terminology.
Here are some random thoughts (not all are accurate, but represent an attempt to translate CL concepts into Blub):
CL is a language that has Lex and Yacc built into it. You can change the syntax of CL to suit your problem.
Lisp s-expressions are concrete parse trees.
The CL "reader" is a scanner. You don't need to build a scanner, since CL already provides you with one.
CL symbols are "tokens".
The CL scanner can read programs from a number of sources - not just files - e.g. strings, keyboard, streams, etc.
Physicists commonly create DSL's. They define a notation with which to describe a domain, then use the notation to solve problems in the domain.
Few other languages can change their own syntax. Examples of self-modifying syntax can be found in term-rewriting systems, such as the language TXL.
CL macros are parsers.
CL macros are code emitters.
CL macros are source-to-source program transformers.
CL backquote/comma/at-sign notation is used to splice and modify concrete parse trees into other shapes.
The CL compiler compiles s-expressions into machine code.
If one creates s-expressions, one can use the CL compiler to compile them into machine code at runtime.
The CL compiler is a JIT compiler.
The CL repl interactively compiles s-expressions to machine code, then executes them, then prints the results of the execution.
The CL language defines a rich library of operators for modifying concrete parse trees.
To a CL'er, infix notation is just unnecessary syntactic sugar. Many novice CL'ers try to create macros that understand infix notation early on in their careers, but as they become more familiar with the power of CL, they drop the syntatic sugar and use parse trees directly.
The CL printer contains a notation for displaying structure sharing. This facilitates debugging of optimizers which transform trees into graphs.
To write a DSL in CL, one first writes a macro that parses s-expressions. Then, the macro is extended with backquotes to emit new s-expressions. The emitted s-expressions are automatically fed to the CL compiler and compiled to machine code.
Unfortunately, the C language uses the name "macro" for a facility that is far less powerful than that of CL. In C, the macro facility can only parse a syntax that looks like simple symbols and function calls and a special #if syntax that is not even part of the C language definition. In CL, the macro facility can parse any s-expression and utilitize any CL function during code emission.
With C macros, the programmer does not have the option to change the syntax of the macro language. With CL macros, the programmer has full control of the macro syntax.
CL has the ability to link/load modules at runtime, "on the fly".
CL invented the concept of JIT (is this factually true?).
Forward references in CL are automatically handled by the runtime linker. The linker fixes up references on the fly to improve runtime efficiency (I know that I first saw this facility in UTAH Lisp in 1977).
The CL scanner, compiler and linker sit in memory all (most) of the time, hence, CL is an all-in-one bundled DSL/compiler toolkit. Some CL's give you the ability to remove the compiler when creating a .exe, if you no longer need it.
The builtin CL macroexpand function gives the programmer the ability to debug his/her DSL compiler by viewing the emitted code (much like CPP's command line option that leaves the expanded code in a text file).
CL's rich suite of syntactic and compiler tools came about due to early AI research into automatic code generation.
CL lambdas (closures) are thunks.
CL closures are trampolines.
CL closures and Scheme's call-with-continuation are the ultimate goto's. Any control flow can be modelled and compiled with these facilities.
CL closures and Scheme's call-with-continuation can be used to create compilers using the concepts of denotational semantics.
Cl closures are (kind of) like Smalltalk's "blocks".
CL closures are another example of the rich language-building facilities of CL, not commonly found in most languages.
CL closures can be used to create anonymous functions, similarly to anonymous classes used in Java.
The facilities of CL make it possible to model and compile just about any kind of runtime semantics, including very non-linear ones, e.g. PAIP prolog.
Prolog provides an simple way to build parsers, if efficiency is not of utmost concern. A number of prologs are available to CL programmers, so one can have the best of both worlds. [I use paip prolog to parse diagrammatic syntax.]
hth
pt
pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
-- Marco Antoniotti, Associate Professor tel. +39 - 02 64 48 79 01 DISCo, Università Milano Bicocca U14 2043 http://bimib.disco.unimib.it Viale Sarca 336 I-20126 Milan (MI) ITALY
Please note that I am not checking my Spam-box anymore. Please do not forward this email without asking me first.
On Wed, Jul 20, 2011 at 3:32 PM, Didier Verna didier@lrde.epita.fr wrote:
Dear friends,
I'm starting to write a chapter for an upcoming book on domain specific languages. The chapter is called (tentatively):
Extensible languages -- blurring the distinction between DSLs and GPLs
GPL meaning General Purpose Language in this context ;-)
My intention is to demonstrate how the task of implementing a DSL is made easier when it boils down to an extension or subset of your original GPL (hence reusing its infrastructure), instead of being a totally different language, only written on top of the other.
Obviously, I'm going to illustrate this with Common Lisp, and I intend to speak of dynamicity (not only dynamic typing, but in general all things that can be deferred to the run-time), introspection, intersession, structural or procedural reflexivity, meta-object protocols (not sure about this one), macro systems and JIT-compilation. Also, more specifically to Lisp, reader macros (compiler macros maybe?), the condition system (and its ability to *not* unwind) and restarts.
Right now, I would like to know if any of you have DSL "pearls", nice examples of DSLs that you have written in Lisp by using some of its features in a clever or elegant way. I would also gladly accept any point of view or comment on what's important to mention, in terms of design principle or anything else, things that I may have missed in the list above.
Not really "pearls", but lately I found myself using more and more of Lisp at macroexpansion time, which seems to be what you're looking for. Two examples:
- for my DO+ (doplus) iteration macro - a somewhat iterate-like construct with a simpler implementation that does not use a code walker - I used structures quite heavily. do+ controls iteration via a series of clauses that are macros (either built-in or written by users) that have a peculiar aspect: they don't expand to proper Lisp code, but return structures or lists of structures [1]. do+ macroexpands its clauses (recursively when needed) and uses the returned structures to drive the building of its own expansion. Basically I explicitly used macros as compile-time functions, defining my own limited "AST" (not really a tree but a flat list of structures) which is not Lisp's but is later translated to Lisp, so it's one extra indirection than what is typically found in macros. I think this shows nicely how the distinction between code and data is blurry in Lisp, and as a consequence the distinction between DSL and GPL is blurry as well. This allows the implementation to remain simple: do+ is a little less than 350 lines of code, but only roughly half of them are the actual macro and its supporting code, the rest are built-in clause macros and other minor stuff.
- I also have sketched a HTML generation library - tentatively called tag-pool - where I used CLOS generic functions at macroexpansion time to drive the expansion of tag macros to HTML-outputting code. Contrary to the popular approach, used by CL-WHO among others, to represent HTML as a limited sexp-based DSL where tag names are keywords and a single macro does all the translation work, I have one macro per tag. For CLOS dispatch purposes, to each tag is also associated a class, but it's used only at expansion time, the output code does not instantiate any CLOS object. Tag macros follow a CLOS-based protocol to emit the various bits of HTML like attributes, body, and so on. Users can specialize methods that are part of the protocol to finely control how tag macros are translated, for example providing defaults for certain attributes, or post-processing some attribute's value, etc. As an example, the SCRIPT macro translates its Lisp body to JavaScript using Parenscript, by specializing a single generic function. The body code can itself contain HTML-generating macros and those are translated to HTML-emitting JavaScript as well. Again, a key feature of Lisp (CLOS and generic function dispatch) is used at macroexpansion time to make the implementation of the DSL simpler and more easily extensible.
You can find both examples here: http://code.google.com/p/tapulli/ although only do+ is documented and reasonably complete.
[1] ok, technically a structure *is* proper Lisp code since it is a self-evaluating object and it can be externalized...
Best, Alessio
This is pretty tragic for me because I made and open-sourced a bunch of "pretty good" DSL's, unfortunately they're still not cleaned up and completely undocumented. Also, all the usage examples of them are buried in some big abortive undocumented proprietary project with lots of newb-code (most of my mastery of Common Lisp was acquired by making this project), however I'm its sole author and own all the rights so I might consider open-sourcing it (perhaps under the GPL or something?). I had not considered this possibility until now mostly out of shame for the low overall quality of this code (with some peaks of high-quality I think, which might interest you).
I don't know under what kind of time constraints you're working, it's obvious that I won't have time to cleanup and document all of these in time, however perhaps if I do a bit of digging in these old projects (that I'm not even sure still build) I might be able to point you to the right places and maybe we can dig out a few examples of "pearls" in this mountain of shit? Who knows...
Anyway, here are some pointers.
I like how Lisp allowed me to use almost without any change the spec of Redis to define its commands in cl-redis library ( https://github.com/vseloved/cl-redis/blob/master/commands.lisp). This gives, IMHO, the best possible decoupling from the implementation, which allows for easy refactoring of the underlying mechanisms (performed twice in the course of the library's existence) and seamless addition of new commands.
It's a good example of what Rainer Joswig called "putting parenthesis around the specification and making it run" ( http://lispm.dyndns.org/mov/dsl-in-lisp.mov)
Best regards, Vsevolod
On Wed, Jul 20, 2011 at 4:32 PM, Didier Verna didier@lrde.epita.fr wrote:
Dear friends,
I'm starting to write a chapter for an upcoming book on domain specific languages. The chapter is called (tentatively):
Extensible languages -- blurring the distinction between DSLs and GPLs
GPL meaning General Purpose Language in this context ;-)
My intention is to demonstrate how the task of implementing a DSL is made easier when it boils down to an extension or subset of your original GPL (hence reusing its infrastructure), instead of being a totally different language, only written on top of the other.
Obviously, I'm going to illustrate this with Common Lisp, and I intend to speak of dynamicity (not only dynamic typing, but in general all things that can be deferred to the run-time), introspection, intersession, structural or procedural reflexivity, meta-object protocols (not sure about this one), macro systems and JIT-compilation. Also, more specifically to Lisp, reader macros (compiler macros maybe?), the condition system (and its ability to *not* unwind) and restarts.
Right now, I would like to know if any of you have DSL "pearls", nice examples of DSLs that you have written in Lisp by using some of its features in a clever or elegant way. I would also gladly accept any point of view or comment on what's important to mention, in terms of design principle or anything else, things that I may have missed in the list above.
Thank you very much in advance!
-- Resistance is futile. You will be jazzimilated.
Scientific site: http://www.lrde.epita.fr/~didier Music (Jazz) site: http://www.didierverna.com
pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
You might want to examine https://github.com/franzinc/net-xml-generatorwhich is (sort-of) a DSL for generating and pretty-printing XML. It uses reader macros and the pretty-printer so that XML elements can be freely intermixed and nested inside Lisp code. (Unlike HTML, XML has an unbounded set of tags, so defining a finite set of keywords won't work.) Download the zip and view the xhtml blurb in a browser. It self-referentially contains the Lisp code that generated it, which is probably harder to do in other languages.
Well, since we are talking about XML stuff, I have another shameless plug myself then :)
http://within-parens.blogspot.com/2011/06/printing-xhtm.html
All in all the pretty-printer is very nice, it'd be nice to have an agreed upon jazzed up version of CLOS dispatching.
Cheers
MA
On Jul 20, 2011, at 23:51 , Steve Haflich wrote:
You might want to examine https://github.com/franzinc/net-xml-generator which is (sort-of) a DSL for generating and pretty-printing XML. It uses reader macros and the pretty-printer so that XML elements can be freely intermixed and nested inside Lisp code. (Unlike HTML, XML has an unbounded set of tags, so defining a finite set of keywords won't work.) Download the zip and view the xhtml blurb in a browser. It self-referentially contains the Lisp code that generated it, which is probably harder to do in other languages. _______________________________________________ pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
-- Marco Antoniotti, Associate Professor tel. +39 - 02 64 48 79 01 DISCo, Università Milano Bicocca U14 2043 http://bimib.disco.unimib.it Viale Sarca 336 I-20126 Milan (MI) ITALY
Please note that I am not checking my Spam-box anymore. Please do not forward this email without asking me first.
XML, good point. XMLisp combines S-expressions and XML into X-expression via CLOS, MOP, Lisp reader and Lisp printer: - paper: http://www.cs.colorado.edu/~ralex/papers/PDF/X-expressions.pdf - code (all in one file) http://code.google.com/p/xmlisp/source/browse/trunk/XMLisp/sources/XMLisp/XM... - application: http://code.google.com/p/xmlisp/
best, Alex
On Jul 21, 2011, at 1:00 AM, Marco Antoniotti wrote:
Well, since we are talking about XML stuff, I have another shameless plug myself then :)
http://within-parens.blogspot.com/2011/06/printing-xhtm.html
All in all the pretty-printer is very nice, it'd be nice to have an agreed upon jazzed up version of CLOS dispatching.
Cheers
MA
On Jul 20, 2011, at 23:51 , Steve Haflich wrote:
You might want to examine https://github.com/franzinc/net-xml-generator which is (sort-of) a DSL for generating and pretty-printing XML. It uses reader macros and the pretty-printer so that XML elements can be freely intermixed and nested inside Lisp code. (Unlike HTML, XML has an unbounded set of tags, so defining a finite set of keywords won't work.) Download the zip and view the xhtml blurb in a browser. It self-referentially contains the Lisp code that generated it, which is probably harder to do in other languages. _______________________________________________ pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
-- Marco Antoniotti, Associate Professor tel. +39 - 02 64 48 79 01 DISCo, Università Milano Bicocca U14 2043 http://bimib.disco.unimib.it Viale Sarca 336 I-20126 Milan (MI) ITALY
Please note that I am not checking my Spam-box anymore. Please do not forward this email without asking me first.
pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
Prof. Alexander Repenning
University of Colorado Computer Science Department Boulder, CO 80309-430
vCard: http://www.cs.colorado.edu/~ralex/AlexanderRepenning.vcf
Didier Verna didier@lrde.epita.fr writes:
Dear friends,
http://groups.google.com/group/comp.lang.lisp/browse_frm/thread/0245342429c6...
Notably, in this type of DSL, you'll note how you can mix Lisp expressions with expressions in the new languages, at several levels.
@[Icals method:(pressPop:(:id)sender) ; resultType:(:id) ; objcl body: ; (declare (ignore sender)) ; (loop ; lisp :for i :from 0 :below 3 ; :do [(aref (icals-stack self) i) setIntValue:[(aref (icals-stack self) (1+ i)) intValue]])] ^^ ^^ || || |+-- lisp |+--- lisp +--- objcl +---- objcl
It might be worthwhile comparing the sources of an early Objective-C front-end such as POC (that includes only the parsing of Objective-C syntax, and generation of the C code for the usual C compiler, and thus is functionnaly equivalent to ObjCL), with the lisp sources of ObjCL.
http://users.telenet.be/stes/compiler.html (objc-3.2.11.tar.gz)
Another cut example I did many years ago (showing my NYU colors) along the lines of what Pascal shows here is the "SETL syntax" in CL. I still have the code. Here is the stupid PRIMES
(defun primes (max) [n in (range 3 max 2) such-that (not (exist m in (range 3 (min (1- n) (+ 2 (sqrt n))) 2) such-that (= (mod n m) 0)))])
Cheers
MA
On Jul 21, 2011, at 01:57 , Pascal J. Bourguignon wrote:
Didier Verna didier@lrde.epita.fr writes:
Dear friends,
http://groups.google.com/group/comp.lang.lisp/browse_frm/thread/0245342429c6...
Notably, in this type of DSL, you'll note how you can mix Lisp expressions with expressions in the new languages, at several levels.
@[Icals method:(pressPop:(:id)sender) ; resultType:(:id) ; objcl body: ; (declare (ignore sender)) ; (loop ; lisp :for i :from 0 :below 3 ; :do [(aref (icals-stack self) i) setIntValue:[(aref (icals-stack self) (1+ i)) intValue]])] ^^ ^^ || || |+-- lisp |+--- lisp +--- objcl +---- objcl
It might be worthwhile comparing the sources of an early Objective-C front-end such as POC (that includes only the parsing of Objective-C syntax, and generation of the C code for the usual C compiler, and thus is functionnaly equivalent to ObjCL), with the lisp sources of ObjCL.
http://users.telenet.be/stes/compiler.html (objc-3.2.11.tar.gz)
-- __Pascal Bourguignon__ http://www.informatimago.com/ A bad day in () is better than a good day in {}.
pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
-- Marco Antoniotti, Associate Professor tel. +39 - 02 64 48 79 01 DISCo, Università Milano Bicocca U14 2043 http://bimib.disco.unimib.it Viale Sarca 336 I-20126 Milan (MI) ITALY
Please note that I am not checking my Spam-box anymore. Please do not forward this email without asking me first.
On Jul 20, 2011, at 6:32 AM, Didier Verna wrote:
Right now, I would like to know if any of you have DSL "pearls", nice examples of DSLs that you have written in Lisp by using some of its features in a clever or elegant way. I would also gladly accept any point of view or comment on what's important to mention, in terms of design principle or anything else, things that I may have missed in the list above.
One perspective that I haven't seen addressed yet is: know your audience and related concepts.
Last year, I wrote a tool for processing large quantities of dirty .csv files: more than can fit into RAM, multiple files comprising a single dataset, column sequence changing across files, junk in cell values, different number of columns across files, etc. And extremely short turn-around time.
The idea was to process this data without having to clean it up first, such that one might gain some insights (sums, uniques, bucketing, etc.) helpful in determining whether or not the data was of any value or gain clues on how to proceed further. Proper database ETL would be too time consuming.
My intended audience was a statistical analyst that favored mousing around Excel spreadsheets while letting prior SAS training go unused because of not wanting to write scripts. (That should have been the first clue to be concerned, but oh, what we do for friends!)
Ultimately, the tool was useful to me, and that was sufficient to meet deadlines.
But the DSL code became overly complex due to this extraneous design criteria of accommodating someone who doesn't want to write scripts in the first place.
Instead of a few simple macros such as WITH-MESSY-CSV appropriate to a Lisp programmer, I effectively created a register machine with "simple" commands: include/exclude filtering, sum, count, unique, look-up, group-by, etc.
Otherwise, the approach was sound enough: load relatively small .csv files as look-up tables and iterate over the entire dataset in a single pass, applying lexically scoped blocks of filtering & calculations. Convert only named columns of interest regardless of position changes across files, parse numbers on demand only for those operations that required it, skip unparseable rows as last resort, etc. Some error in results-- but some results with reduced confidence are better than none in this case.
Lessons learned: (a few more while I'm here)
1. Know your audience, and build for the correct users.
2. Build the right tool. (I'm a systems programmer; a good stats person would likely have come up with a better work-flow, likely using R so rich reports could also be generated quickly.)
3. Good language design can be challenging. I would have been better off (perhaps) stealing SQL or XQuery's FLOWR conventions than inventing my own "simple" set of commands. (Syntax is another matter... as you know.)
4. Being adept at backquotes, comma substitution and unrolling lists is not necessarily enough skill to create a good, clean DSL implementation. But keep trying. Do your best to make one for "keeps". Then throw it away, anyway. It's important to not hold anything back in the first version. Ah, experience! (I'll likely go at this one again just for the fun of it.) e.g., unrelated project from years ago: http://play.org/learning-lisp/html.lisp
5. Collaborate: Get input from others. My co-workers who also use Common Lisp were many time-zones and an ocean away, busy with looming deadlines of their own. However, their 10 years CL experience to my 5 (and their far deeper stats familiarity) would certainly have helped here.
-Daniel
-- first name at last name dot com
+1
May I also say that there are entire scientific, financial, and accounting communities that should be barred from using Excel?
Cheers -- MA
On Jul 22, 2011, at 09:14 , Daniel Pezely wrote:
...
Lessons learned: (a few more while I'm here)
Know your audience, and build for the correct users.
Build the right tool. (I'm a systems programmer; a good stats person would likely have come up with a better work-flow, likely using R so rich reports could also be generated quickly.)
Good language design can be challenging. I would have been better off (perhaps) stealing SQL or XQuery's FLOWR conventions than inventing my own "simple" set of commands. (Syntax is another matter... as you know.)
Being adept at backquotes, comma substitution and unrolling lists is not necessarily enough skill to create a good, clean DSL implementation. But keep trying. Do your best to make one for "keeps". Then throw it away, anyway. It's important to not hold anything back in the first version. Ah, experience! (I'll likely go at this one again just for the fun of it.)
e.g., unrelated project from years ago: http://play.org/learning-lisp/html.lisp
- Collaborate: Get input from others. My co-workers who also use Common Lisp were many time-zones and an ocean away, busy with looming deadlines of their own. However, their 10 years CL experience to my 5 (and their far deeper stats familiarity) would certainly have helped here.
-Daniel
-- Marco Antoniotti, Associate Professor tel. +39 - 02 64 48 79 01 DISCo, Università Milano Bicocca U14 2043 http://bimib.disco.unimib.it Viale Sarca 336 I-20126 Milan (MI) ITALY
Please note that I am not checking my Spam-box anymore. Please do not forward this email without asking me first.
(1+ *)
I am knee-deep daily in one of those communities. Time and time again, I request that people send me the raw text files of data as opposed to poorly importing them into an Excel spreadsheet. Or, I'll get some spreadsheet "analysis" that contains brittle calculations that require lots of hand editing if you wish to update data, (select ranges, etc.). If people are going to rely on Excel to the extent that they do, I wish they'd at least learn VBA.
I have a large body of lisp code that is purely an abstraction layer to insulate me from a very poorly conceived DSL for a finite element analysis package. Having the lisp abstraction is like a productivity accelerator. The more I have abstracted, the more productive I am and the more time I have to implement higher level abstractions.
Tom ---------------------------------------------------------------- Thomas M. Hermann Odonata Research LLC http://www.odonata-research.com/ http://www.linkedin.com/in/thomasmhermann
On Fri, Jul 22, 2011 at 2:54 AM, Marco Antoniotti < antoniotti.marco@disco.unimib.it> wrote:
+1
May I also say that there are entire scientific, financial, and accounting communities that should be barred from using Excel?
Cheers
MA
On Jul 22, 2011, at 09:14 , Daniel Pezely wrote:
...
Lessons learned: (a few more while I'm here)
Know your audience, and build for the correct users.
Build the right tool. (I'm a systems programmer; a good stats person
would likely have come up with a better work-flow, likely using R so rich reports could also be generated quickly.)
- Good language design can be challenging. I would have been better
off (perhaps) stealing SQL or XQuery's FLOWR conventions than inventing my own "simple" set of commands. (Syntax is another matter... as you know.)
- Being adept at backquotes, comma substitution and unrolling lists is
not necessarily enough skill to create a good, clean DSL implementation. But keep trying. Do your best to make one for "keeps". Then throw it away, anyway. It's important to not hold anything back in the first version. Ah, experience! (I'll likely go at this one again just for the fun of it.)
e.g., unrelated project from years ago:
http://play.org/learning-lisp/html.lisp
- Collaborate: Get input from others. My co-workers who also use
Common Lisp were many time-zones and an ocean away, busy with looming deadlines of their own. However, their 10 years CL experience to my 5 (and their far deeper stats familiarity) would certainly have helped here.
-Daniel
-- Marco Antoniotti, Associate Professor tel. +39
- 02 64 48 79 01
DISCo, Università Milano Bicocca U14 2043 http://bimib.disco.unimib.it Viale Sarca 336 I-20126 Milan (MI) ITALY
Please note that I am not checking my Spam-box anymore. Please do not forward this email without asking me first.
pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
If you have people making messy spreadsheets that are hard to maintain, you might want to look at this. I have not used it myself:
But it's from Howard Cannon, Symbolics co-founder and main inventor of Flavors, an ancestor of CLOS.
-- Dan
On Fri, Jul 22, 2011 at 9:56 AM, Thomas M. Hermann < thomas.m.hermann@odonata-research.com> wrote:
(1+ *)
I am knee-deep daily in one of those communities. Time and time again, I request that people send me the raw text files of data as opposed to poorly importing them into an Excel spreadsheet. Or, I'll get some spreadsheet "analysis" that contains brittle calculations that require lots of hand editing if you wish to update data, (select ranges, etc.). If people are going to rely on Excel to the extent that they do, I wish they'd at least learn VBA.
I have a large body of lisp code that is purely an abstraction layer to insulate me from a very poorly conceived DSL for a finite element analysis package. Having the lisp abstraction is like a productivity accelerator. The more I have abstracted, the more productive I am and the more time I have to implement higher level abstractions.
Tom
Thomas M. Hermann Odonata Research LLC http://www.odonata-research.com/ http://www.linkedin.com/in/thomasmhermann
On Fri, Jul 22, 2011 at 2:54 AM, Marco Antoniotti < antoniotti.marco@disco.unimib.it> wrote:
+1
May I also say that there are entire scientific, financial, and accounting communities that should be barred from using Excel?
Cheers
MA
On Jul 22, 2011, at 09:14 , Daniel Pezely wrote:
...
Lessons learned: (a few more while I'm here)
Know your audience, and build for the correct users.
Build the right tool. (I'm a systems programmer; a good stats
person would likely have come up with a better work-flow, likely using R so rich reports could also be generated quickly.)
- Good language design can be challenging. I would have been better
off (perhaps) stealing SQL or XQuery's FLOWR conventions than inventing my own "simple" set of commands. (Syntax is another matter... as you know.)
- Being adept at backquotes, comma substitution and unrolling lists is
not necessarily enough skill to create a good, clean DSL implementation. But keep trying. Do your best to make one for "keeps". Then throw it away, anyway. It's important to not hold anything back in the first version. Ah, experience! (I'll likely go at this one again just for the fun of it.)
e.g., unrelated project from years ago:
http://play.org/learning-lisp/html.lisp
- Collaborate: Get input from others. My co-workers who also use
Common Lisp were many time-zones and an ocean away, busy with looming deadlines of their own. However, their 10 years CL experience to my 5 (and their far deeper stats familiarity) would certainly have helped here.
-Daniel
-- Marco Antoniotti, Associate Professor tel. +39
- 02 64 48 79 01
DISCo, Università Milano Bicocca U14 2043 http://bimib.disco.unimib.it Viale Sarca 336 I-20126 Milan (MI) ITALY
Please note that I am not checking my Spam-box anymore. Please do not forward this email without asking me first.
pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
Speaking of XML, there's another good example of a special-purpose DSL, designed for efficient processing of OSM map data, described here: http://swizard.livejournal.com/142027.html (text in Russian).
On Wed, Jul 20, 2011 at 4:32 PM, Didier Verna didier@lrde.epita.fr wrote:
Dear friends,
I'm starting to write a chapter for an upcoming book on domain specific languages. The chapter is called (tentatively):
Extensible languages -- blurring the distinction between DSLs and GPLs
GPL meaning General Purpose Language in this context ;-)
My intention is to demonstrate how the task of implementing a DSL is made easier when it boils down to an extension or subset of your original GPL (hence reusing its infrastructure), instead of being a totally different language, only written on top of the other.
Obviously, I'm going to illustrate this with Common Lisp, and I intend to speak of dynamicity (not only dynamic typing, but in general all things that can be deferred to the run-time), introspection, intersession, structural or procedural reflexivity, meta-object protocols (not sure about this one), macro systems and JIT-compilation. Also, more specifically to Lisp, reader macros (compiler macros maybe?), the condition system (and its ability to *not* unwind) and restarts.
Right now, I would like to know if any of you have DSL "pearls", nice examples of DSLs that you have written in Lisp by using some of its features in a clever or elegant way. I would also gladly accept any point of view or comment on what's important to mention, in terms of design principle or anything else, things that I may have missed in the list above.
Thank you very much in advance!
-- Resistance is futile. You will be jazzimilated.
Scientific site: http://www.lrde.epita.fr/~didier Music (Jazz) site: http://www.didierverna.com
pro mailing list pro@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
Thank you all very much for the feedback. I guess I have a lot to read for the holidays now...