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

The meditation Embedding a mini-language for XML construction into Perl by tmoertel immediately comes to mind (XML domain), and a derived HTML::Writer module. Do these qualify as internal DSL, since code written in them is executed as perl?

Update: tmoertel gave a talk on the subject for the Pittsburgh Perl Mongers. The slides are still available via the Wayback Machine.

perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
  • Comment on Re: Which internal DSL are there in Perl? (Domain Specific Languages - Part 1)

Replies are listed 'Best First'.
Re^2: Which internal DSL are there in Perl? (Domain Specific Languages - Part 1)
by LanX (Saint) on Aug 03, 2017 at 11:43 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'
        > because it is quite slow and because of inherent namespace pollution

        you mention two very important problems I wanted to name in my talk

        • performance: One needs to reduce runtime as much as possible, like by memoization
        • namespace polution: The effects of the embedded language must be contained to a lexical scope.
        You are already using one basic tool to achieve this: blocks.

        performance

        All your html/xml elements take a code-block as *{$_} = sub(&) { _elem($name, @_) }; and should per default memorize the result and return the pre-calculated result.

        Of course one would need exception for cases where dynamic elements have to be interpolated, like in loops, either by explicitly deactivating memoization or by parsing the block for closed over variables.

        namespace

        1. The most obvious solution is to use a package , something like

        render { package HTML::DSL; HTML { HEAD { TITLE { "foo bar"}; }; ... }

        2. Of course it would be syntactically "sweeter" if the package was automatically included.

        The way to go is to use B::Deparse 's coderef2text to get the source and to re-eval it with an included package declaration in the first line.

        Actually it's a bit more complicated, because you might have closed over variables inside the block which would loose their binding after evaluation.

        That's why you need to inspect to take care for this, I already wrote code for this in my Macro module (github only).

        This is actually the way how many (most) DSL's are constructed in Ruby, they "re-eval" the code (instance_eval or instance_exec) from inside a block.

        And since they ran into the same problem with lost bindings of closure vars, a module called Docile was created to reestablish the bindings ...

        ... or in their own words "the hard part", where most folks making a DSL in Ruby throw up their hands

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