DSLs are small languages, focused on a particular aspect of a software system. You can't build a whole program with a DSL, but you often use multiple DSLs in a system mainly written in a general purpose language.DSLs come in two main forms: external and internal
An external DSL is a language that's parsed independently of the host general purpose language: good examples include regular expressions and CSS
Internal DSLs are a particular form of API in a host general purpose language, often referred to as a fluent interface.
They are represented within the syntax of a general-purpose language. It’s a stylized use of that language for a domain-specific purpose.
People find DSLs valuable because a well designed DSL can be much easier to program with than a traditional library.
This improves programmer productivity , which is always valuable. In particular it may also improve communication with domain experts , which is an important tool for tackling one of the hardest problems in software development.
Now there are some more frequently used examples in Perl which come to mind like SQL and Template languages like in Template::Toolkit2
[% FOREACH file=files %] [% IF ( matches = file.date.match('dd/mm/(\d+)') ) %] <a href='#'>[% matches.0 %]</a> [% END %] [% END %]
Both qualify as are for sure as DSLs.
They are sub-languages which can be used by "domain experts" without any knowledge of Perl.
And they are external, because neither SQL nor TT commands are implemented as Perl functions or follow Perl syntax.
Well designed traditional modules and classes are sometimes close to represent a sub-language but they still come with a lot of boilerplate.
For instance an expert in the domain of TCL/TK may (probably?) not care much if the "host" language is Perl or Python or Ruby as long as he can call the commonly known methods. (see http://www.tkdocs.com/ for comparison of snippets in various languages).
But the necessity to constantly repeat an $obj-> or PACK::AGE:: on the left hand side of a command doesn't make it a completely "fluent" approach.
(On a side note: avoiding to repeat this LHS for method calls seems to be the principal mechanism in Ruby for transforming a simple class to what Rubyists like to call a "DSL", a bunch of function calls inside a block are somehow interpreted as method calls on the same object, hence very similar to the with(obj) {} mechanism in JavaScript - please correct me if not)
Now, what are examples for internal DSLs in Perl?
The only widely known one which comes to my mind is CGI::HTML::Functions which used to be part of CGI
For example, here's one way to make an ordered list:This example will result in HTML output that looks like this:print ul( li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy']) );<ul> <li type="disc">Sneezy</li> <li type="disc">Doc</li> <li type="disc">Sleepy</li> <li type="disc">Happy</li> </ul>
Nice but IMHO it could be even more fluent.
But are there others?
There is for instance Rex which I suppose was inspired by Ruby's Puppet
use Rex -feature => ['1.0']; desc "Get Uptime"; task "uptime", sub { say run "uptime"; }
And I think I could theoretically implement most Assembler languages as Perl code just with some minor changes. I just need to implement ASM-commands as uppercase subs, quote literals and adjust the comment symbol.
like
(original example)CPX '3' ;# Year starts in March to bypass BCS 'MARCH' ;# leap year problem DEY ;# If Jan or Feb, decrement year MARCH: EOR '$7F' ;# Invert A so carry works right ...
But there must be more examples of internal DSLs in Perl ...
Could you please help me to find and classify them?
Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Je suis Charlie!
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |