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

Eric Hammond eric at perl.org
Thu Jun 21 15:04:44 PDT 2012


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
> 


More information about the Losangeles-pm mailing list