That's excellent!  Constant folding in the TT will open the door for many
other things that would have been too restrictive, I think.

I actually did the same kind of hack by subclassing Template::Directives by
allowing the "map" to be supplied... It would sub-in the constants at
template compile-time.  What you've done looks like a much cleaner and
extensible alternative, .. I'm going to grab my CVS copy and check it out.

Thanks again, Andy.

-Bryan
 

-----Original Message-----
From: Andy Wardley
To: Shannon, Bryan
Cc: '[EMAIL PROTECTED]'
Sent: 7/7/2002 9:14 AM
Subject: Constant folding and namespace handlers (was: DBI Hash access
faster?)

On Sat, Jul 06, 2002 at 02:59:34PM -0500, Shannon, Bryan wrote:
> I'm writing to the list to see if someone else has run into this
situation
> and/or figured out a better way to handle it.

In addition to my other suggestion, this reminded me of the constants
folding solution that Chris Nandor and I hacked up for Slashdot.

I've now folded this into TT within a general mechanism for hooking into
the compilation of template variables.  The obvious benefit for the
average man is that constant folding can significantly speed up the 
runtime processing of templates.  In your case, it also provides
the hook to monkey around with your own variable compiling magic.

But first, here's an example showing constant variables:

   my $template = Template->new({
       CONSTANTS => {
          title => 'My Web Site',
          col   => {
              back => '#ffffff',
              text => '#000000',
          },
       },
   });

Now, when you reference variables like these:

   [% constants.title %]
   [% constants.col.back %]

they get folded at compile time into their constant values, making
your template process that much faster.  You can have any kind of 
constant variables, hashes, lists, objects, etc., and you can even 
call virtual methods and other crazy stuff.  All at compile time.

You can use the CONSTANTS_NAMESPACE => 'const' option, for example, 
if you prefer to write something like:

   [% const.title %]  etc.

The underlying mechanism behind all this is controlled by a NAMESPACE
hash which maps top-level variable namespaces (e.g. constant or const
in these examples) to a compiler handler which returns either a constant
value, or some Perl code to fetch a dynamic value at run time.

The new Template::Namespace::Constants module implements the handler
for constant folding.

So the first example is equivalent to:

   my $template = Template->new({
       NAMESPACE => {
          constants => Template::Namespace::Constants->new({
              title => 'My Web Site',
              col   => {
                  back => '#ffffff',
                  text => '#000000',
              },
           },
       },
   });
  
And of course, you can add your own namespaces and handlers in here.
Such as:

   my $template = Template->new({
       NAMESPACE => {
          data => My::Namespace::DataMunger->new( ... ),
       },
   });
 
Your DataMunger's ident() method would turn something like this:

   [% data.fieldx %]

which it would receive as an ident list like this:

   [ 'data', 0, 'fieldx', 0 ]

into the Perl code that looked something like this:

  $stash->get(['data', 0, 4, 0]);

which represents something like this:

   [% data.4 %]

Magic!

Implementing a namespace handler requires you to get your hands a little
dirty with the low-level specifics of how the templates get parsed and
compiled into Perl code.  But the hook is now there if you decide to use
it and Template::Namespace::Constants gives you an example to work from.

Shout if you need help.

All these changes are in CVS and about to be released as 2.07b.  Must
each lunch first!

Enjoy!
A


Reply via email to