[LA.pm] Thanks for letting me present
Ben Tilly
btilly at gmail.com
Thu Jun 21 02:05:23 PDT 2012
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"?
More information about the Losangeles-pm
mailing list