5 ms·
Seems like an argument in favor of domain-specific languages: identify the domain, and create something just powerful enough to suffice. Indeed, most of the ar
by Shog9 11y ago
Seems like an argument in favor of domain-specific languages: identify the domain, and create something just powerful enough to suffice.
Indeed, most of the arguments made are the same that were used as justifications for DSLs a while back:
> The problem with this kind of freedom is that every bit of power you insist on have when writing in the language corresponds to power you must give up at other points of the process — when ‘consuming’ what you have written.
A good DSL lets you create, for example, business rules that are easy to maintain (for those familiar with the business) but don't prevent me from swapping out the implementation that drives them for something better on down the line.
- cpeterso 11y agoWhat would a DSL for creating DSLs look like? And could it be self-hosted? It's turtles all the way down. :)
- jpolitz 11y agoRacket and #lang are a pretty good start. http://www.ccs.neu.edu/home/matthias/manifesto/sec_pl-pl.html http://www.ccs.neu.edu/home/matthias/manifesto/sec_pl-pl.htm...
- kyllo 11y agoLisp macros can be thought of as a DSL for creating DSLs. And yes, Lisp can be self-hosted.
- nickpsecurity 11y agoLISP, Forth, SNOBOL, REBOL/RED, PROLOG, Stratego Programming System, BNF, ASF+SDF... the list goes on and on. We can stop here, though. :)
- sparkie 11y agoKernel is ideal for creating small embedded languages, where you can selectively expose parts of the parent language to perform general purpose computation, without giving any access to sensitive code. Kernel is like Scheme, except environments are first class objects which you can mutate and pass around. A typical use for such environment is for the second argument of $remote-eval, to limit the bindings available to the evaluator. If you treat an eDSL as a set of symbols representing it's vocabulary and grammar, then you bind them to a new environment with $bindings-environment, then passing a piece of code X to eval with this resulting argument as the second environment, will ensure X can only access those bindings (and built-in symbols which result from parsing Kernel, such as numbers), and nothing else. There's a function make-kernel-standard-environment for easy self-hosting. Trivial examples: ($define! x 1) ($remote-eval (+ x 2) (make-kernel-standard-environment)) > error: unbound symbol: x ($define! y 2) ($remote-eval (+ x y) (make-environment ($bindings->environment (x 1)) (make-kernel-standard-environment))) > error: unbound symbol: y ($remote-eval (+ x y) ($bindings->environment (x 1) (y 2) (+ +))) > 3 ($define! x 1) ($define! y 2) ($remote-eval (+ x y) (get-current-environment)) > 3 $remote-eval is a helper function in the standard library which evaluates the second argument in the dynamic environment to get the target environment, then evaluates the first argument in that. The purpose of this is to provide a blank static-environment for o to be evaulated, so no bindings from the current static environment where $remote-eval is called from are made accessible to the first argument. ($define! $remote-eval ($vau (o e) d (eval o (eval e d)))) If you're familiar with Scheme, you may notice the absensce of quote. And contrary to the opinions in the article, Kernel is the most expressively powerful language I know, and I'd recommend everyone learn it. You have a powerful but small and simple core language, from which you can derive your DSLs with as little or much power as you want them to have.
- cpeterso 11y agoThanks! I will check out Kernel. The ability to restrict the environment is key. Creating a DSL in standard Lisp would create a more powerful environment: the DSL would include all Lisp features plus the domain features.