[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