[LA.pm] Thanks for letting me present

Ben Tilly btilly at gmail.com
Thu Jun 21 01:20:00 PDT 2012


I have put my presentation up at
http://elem.com/~btilly/template-hashexpand/ for anyone who wants to
go through the slides.

I gave thought to Eric's comment about adding looping, and came up
with a weird suggestion for how to do it.  Add function calls to code
references stored elsewhere in the hash.  So we might allow:

  {
    joiner => sub {
      my ($expander, $hashref, $sep, @args) = @_;
      return join $sep, @args;
    },
    foo => '{% joiner( ' ', Hello, world) %}',
  }

And this would expand to:

  {
    joiner => sub {
      my ($expander, $hashref, $sep, @args) = @_;
      return join $sep, @args;
    },
    foo => 'Hello world',
  }

*However* the function would have complete access to an object that
can trigger hash expansion inside of the current context, and also the
hash reference.  So if you wanted to, you could have it loop, and
insert a bunch of stuff into the hash, using hash expansion to
customize them.  Thus you can have your config expansion insert this
looping capability, and then you can use it wherever it makes sense.

Let's take this idea a few steps further off towards insanity.  The
next utility step would be to allow multi-level expansion in a string.
 So, for instance, you can have:

  {
    foo => '[% foo[% bar %] %]',
    bar => 'blat',
    fooblat => 'gotcha',
  }

which would expand to:

  {
    foo => 'gotcha',
    bar => 'blat',
    fooblat => 'gotcha',
  }

But you could do this with function calls instead if you wanted.  So
one parameter can be expanded to something dynamically determined by
another parameter.  (You could implement this yourself inside of the
function, but why not make it easy.)

The third step is that if a template expansion is *exactly* a variable
expansion, we get that value inserted as is (instead of stringified).
So:

  {
    foo => {
      this => 'that',
    },
    bar => '[% foo %]',
  }

should expand to:

  {
    foo => {
      this => 'that',
    },
    bar => {
      this => 'that',
    },
  }

Combined with the second step, this would allow us to pass real data
structures to function calls inside of hash values that we are
expanding.

And while we're at it, we can always allow an easier quoted string
syntax.  So for instance no expansion would happen if you started the
string with %%.  So:

  {
    foo => '%%[% Hello %]',
  }

would expand to:

  {
    foo => '[% Hello %]',
  }

Now if you squint right, the ability to call functions looks like Lisp
macros.  The ability to suppress template expansion before the call,
then have it happen inside of the function gives us an equivalent to
Lisp macros.  And we can implement the special forms directly in Perl
functions.

Any template expansion system that gives you something with a
recognizable parallel to Lisp (albeit with a different syntax)
qualifies in my books as "sufficiently powerful" for any reasonable
need...

Does anyone have any reaction other than, "He just went off the deep end"?


More information about the Losangeles-pm mailing list