Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Which internal DSL are there in Perl? (Domain Specific Languages - Part 1)

by LanX (Bishop)
on Aug 03, 2017 at 02:08 UTC ( #1196599=perlmeditation: print w/replies, xml ) Need Help??

Taking some definitions from Wikipedia and Martin Fowlers Book: (emphasizes added)

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.

  • SQL appears as embedded string inside Perl code is only parsed after leaving Perl thru DBI
  • And TT may be parsed with Perl but is not parsed as Perl.
So far for external DSLs , but what are good examples for internal DSLs in Perl?

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:
print ul( li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy']) );
This example will result in HTML output that looks like this:
<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

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 ...
(original example)

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!

Replies are listed 'Best First'.
Re: Which internal DSL are there in Perl? (Domain Specific Languages - Part 1)
by shmem (Chancellor) on Aug 03, 2017 at 07:17 UTC
      Absolutely, but why didn't you publish?

      FWIW I worked on a similar project, but took some other design decisions. (Attributes are not proper functions)

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

        Absolutely, but why didn't you publish?

        Because, well... tests, pod, you name it... then, mainly because HTML::Writer is more a proof of concept than of productive use: because it is quite slow and because of inherent namespace pollution - all those functions derived from a DTD, yecch! security... I foresaw a lot of issues with that, and since chromatic pointed me to Technical Debt, I didn't dare to. Had somebody expressed interest to work that out with me into a module proper, with defined use cases and what not, making it more generic and so on... but no. At that time I had to move on, and other things to do. It rests in the vault of unfinished projects.

        <update>
        If you (as in "anybody") want to grab that code and make it into a CPAN module, feel free to do so. But please include references to tmoertel and me. And I would appreciate if you contact me (via PM here or my CPAN mail handle shmem-at-cpan.org) to discuss things. Thanks.
        </update>

        <update2>
        The module is now on github and will eventually make its way to CPAN.
        </update2>

        FWIW I worked on a similar project, but took some other design decisions. (Attributes are not proper functions)

        Publish or show, or it didn't happen ;-)

        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
Re: Which internal DSL are there in Perl? (Domain Specific Languages - Part 1)
by hippo (Canon) on Aug 03, 2017 at 08:03 UTC

    Surely the plethora of OO helpers (Moose, Mouse, Moo, Mo, etc.) qualify?

    I'm not entirely clear whether PDL would count as internal or external.

      > Surely the plethora of OO helpers

      I already thought about them, but I'd rather try to classify them as syntax extensions or syntactic sugar, because the domain is part of the host language.

      But the distinction is fuzzy since techniques and requirements are similar.

      For comparison LINQ is often called a DSL, while it's integral part of C#. (Language Integrated Query), at the same time there are ports for other host languages as external libraries, which are not fully equivalent, but surely a DSL. (Basically an expert in the LINQ domain could help using them, without knowing the host language in depth)

      I'm not aware about a port of any M* lib to another language. ...

      > I'm not entirely clear whether PDL would count as internal or external.

      I had a quick look into the docs and it's really too wast to tell.

      I can see operator overloading (internal) and a dependency to Filter::Simple (external)

      And despite the L in the name, it doesn't look independent enough to be a DSL.

      maybe I'm missing a good tutorial, it certainly has elements of all in its large code base.

      You see im struggling to find objective definitions, maybe it's better to concentrate on the applied techniques... :)

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

        I already thought about them, I'd rather try to classify them as syntax extensions or syntactic sugar

        I would include them. They form a language to describe classes and attributes, and their relations.

Re: Which internal DSL are there in Perl? (Domain Specific Languages - Part 1)
by Anonymous Monk on Aug 03, 2017 at 05:34 UTC
Re: Which internal DSL are there in Perl? (Domain Specific Languages - Part 1)
by ikegami (Pope) on Aug 04, 2017 at 20:54 UTC
    • Quoting:
      • q: Escaping rules
      • qq (incl qx, qr, m, s (search part)): Escaping rules and interpolation
    • Formatting:
      • sprintf
      • strftime
      • forms
      • Perl6::Form
      • Template languages (e.g. Template-Toolkit)
      • pack
    • Query languages:
      • SQL
      • XPath
      • CGI::HTML::Functions
      • Find::File::Rule
      • Regular expressions
      • Regular expressions sub-languages:
        • Character classes
        • Extended bracketed character class
        • Properties
        • etc
    • Parsing:
      • Various grammar languages (e.g. Parse::RecDescent)
      • strptime
      • unpack
    • Other:
      • tr///
      • POD

    Another category is parts of the language that don't match the rest, such as the flags for m and other operators.

    There are also small "languages" too small to mention, such as `use overload`.

        ah, you just want internal DSLs. I just added File::Find::Rule (a query language parsed as Perl), then.

Re: Which internal DSL are there in Perl? (Domain Specific Languages - Part 1)
by Anonymous Monk on Aug 03, 2017 at 05:36 UTC
      Absolutely! :)
        Hahah that's so neat! If I see a youtube video of your talk, I'll know where some of the content came from!
Re: Which internal DSL are there in Perl? (Domain Specific Languages - Part 1)
by melezhik (Monk) on Aug 03, 2017 at 18:31 UTC
    A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://1196599]
Front-paged by kcott
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (6)
As of 2018-08-14 06:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Asked to put a square peg in a round hole, I would:









    Results (144 votes). Check out past polls.

    Notices?