[LA.pm] [perl-org] Re: Thanks for letting me present

Ben Tilly btilly at gmail.com
Thu Jun 21 15:38:10 PDT 2012


I took this too seriously because it was a fun problem to think about
while I was loopy on the caffeine that I used to stay awake on my way
home...

As for YAML files through Template::Toolkit, there is a bootstrap
problem.  Where do you get the parameters that you will use to expand
those templates?  From the same configuration that you're generating
out of the parsed output?  It seems to me that a better hack is to
generate that part of the hash from a map statement that exists in
pure Perl.  (Even if you're using YAML for most of your data, if you
use the Config::Any solution I showed to load it, you can easily
generate part of your configuration in pure Perl.)

The limitation is that you don't have the easy option to modify that
map statement based on an override in a child hash.  But that's
probably not a significant limitation.

On Thu, Jun 21, 2012 at 3:04 PM, Eric Hammond <eric at perl.org> wrote:
>
> Is it too late to say "I was joking"?
>
> Once it gets that complicated, how about just running YAML files through
> Template::Toolkit?  Existing components, powerful, and well understood.
>
> BTW, Thanks for presenting, Ben.  I loved the mix of theory and practice.
>
> --
> Eric Hammond
>
> On 06/21/2012 02:05 AM, Ben Tilly wrote:
>> Hrm, I guess I gave all of the architecture, but didn't show what the
>> answer to Eric's problem could look like.  Let me do that.
>>
>>   {
>>     range => sub {
>>       my ($expander, $hashref, $from, $to) = @_;
>>       return [$from..$to];
>>     },
>>     insert_foreach => sub {
>>       my ($expander, $hashref, $var, $range, $key, $value) = @_;
>>       for (@$range) {
>>         my $expanded = $expander->expand({
>>           $var => $_,
>>           key => $key,
>>           value => $value,
>>         });
>>         $hashref->{$expanded->{$key}} = $expanded->{$value};
>>       }
>>       return undef; # We do not use this again.
>>     },
>>     subdomain_count => 5,
>>     subdomain_template => {
>>       domain => '%%m[% i %].campusexplorer.com',
>>       foo => 'bar',
>>     },
>>     dummy => '[%
>>         insert_foreach(
>>           i,
>>           [% range(1, [% subdomain_count %]) %],
>>           %%m[%i],
>>           [% subdomain_template %],
>>         ) %]',
>>   }
>>
>> And then expanded we would get:
>>
>>   {
>>     range => sub {
>>       my ($expander, $hashref, $from, $to) = @_;
>>       return [$from..$to];
>>     },
>>     insert_foreach => sub {
>>       my ($expander, $hashref, $var, $range, $key, $value) = @_;
>>       for (@$range) {
>>         my $expanded = $expander->expand({
>>           $var => $_,
>>           key => $key,
>>           value => $value,
>>         });
>>         $hashref->{$expanded->{$key}} = $expanded->{$value};
>>       }
>>       return undef; # We do not use this again.
>>     },
>>     subdomain_count => 5,
>>     subdomain_template => {
>>       domain => 'm[% i %].campusexplorer.com',
>>       foo => 'bar',
>>     },
>>     dummy => undef,
>>     m1 => {
>>       domain => 'm1.campusexplorer.com',
>>       foo => 'bar',
>>     },
>>     m2 => {
>>       domain => 'm2.campusexplorer.com',
>>       foo => 'bar',
>>     },
>>     m3 => {
>>       domain => 'm3.campusexplorer.com',
>>       foo => 'bar',
>>     },
>>     m4 => {
>>       domain => 'm4.campusexplorer.com',
>>       foo => 'bar',
>>     },
>>     m5 => {
>>       domain => 'm5.campusexplorer.com',
>>       foo => 'bar',
>>     },
>>   }
>>
>> I guess that it is a matter of opinion whether this proposed cure is
>> worse than the disease...
>>
>> By the way where I randomly chose %%, a better Lisp analogy would be `
>> (backtick).
>>
>> On Thu, Jun 21, 2012 at 1:20 AM, Ben Tilly <btilly at gmail.com> wrote:
>>> 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"?
>> _______________________________________________
>> Losangeles-pm mailing list
>> Losangeles-pm at pm.org
>> http://mail.pm.org/mailman/listinfo/losangeles-pm
>>
> _______________________________________________
> Losangeles-pm mailing list
> Losangeles-pm at pm.org
> http://mail.pm.org/mailman/listinfo/losangeles-pm


More information about the Losangeles-pm mailing list