[Templates] Accessing variables which contain period or dot in the name

Tosh Cooey tosh@1200group.com
Wed, 06 Jun 2007 12:11:37 +0200


No big deal, I wouldn't "fix" it since the workaround is quite 
reasonable.  The part about $secret(1) is really amazing, and hopefully 
this email will be found by anyone who has the same problems.

Thanks for everything Andy!!

Tosh


Andy Wardley wrote:
> Tosh Cooey wrote:
>  > So of course you *might* expect it to work like this:
> [...]
>  > But it doesn't.
> 
> Hi Tosh,
> 
> Hmmm, yes.  That's strange.
> 
> Ah yes.  Now I see.  It *does* work if you do this.
> 
> VARIABLES = {
>     badguys => {
>      'C.I.A' => ['American', 'Dirty'],
>      'MI6'   => ['British', '007'],
>      'F.S.B' => ['Russian', 'K.G.B.'] }
>     },
> }
> 
> [% FOREACH secret IN badguys.keys %]
>     [% FOREACH keyword IN badguys.$secret %]
>         [% keyword %]
>     [% END %]
> [% END %]
> 
> The reason is that when you've got a variable that already has a dot
> in it, like this:
> 
>    badguys.$secret
> 
> then the parser turns it into this:
> 
>    $stash->get([badguys, 0, $stash->get('secret'), 0]);
> 
> When passed a list ref like that, get() treats each pair of elements
> as (name, args) (with 0 indicating no args) and all is well.
> 
> But when you don't have any dots in a variable, and no args,
> like this:
> 
>     foo
> 
> the parser "optimises" it to this:
> 
>     $stash->get('foo');
> 
> Rather than
> 
>     $stash->get(['foo', 0]);
> 
> And if you have this:
> 
>     secret = 'C.I.A'
>     $secret
> 
> Then it gets optimised to this:
> 
>     $stash->set(secret => 'C.I.A');
>     $stash->get($stash->get('secret'))
> 
> Which is the same as:
> 
>     $stash->get('C.I.A')
> 
> Which the stash then parses into ['C', 0, 'I', 0, 'A', 0]
> thinking you meant that dotop sequence all along because you
> passed it a string and not a list ref.
> 
> So if you define C => { I => { A => [...] } } then you will
> see the values coming back, just as if you typed:
> 
>     [% C.I.A %]
> 
> But that's not what you want :-(
> 
> And just to add to the weirdness of it, if you add an argument
> to the single variable then it works because the parser no longer
> optimises it down:
> 
>     $secret(1)
> 
> This becomes:
> 
>     $stash->get([$stash->get('secret'), [1]]);
> 
> And the value gets returned.  In this case, the (1) argument is ignored
> so it makes no difference to the outcome.  Other than making it work,
> of course.
> 
> So yes, I guess it is a bug.  But I'll probably hold off on fixing it until
> TT3 given that it's something of an edge case.  And you've got a workaround
> (just add an argument), however counter-intuitive it might be!
> 
> Incidentally, this works OK:
> 
>     badguys.${'C.I.A'}
> 
> And this will work in TT3:
> 
>     badguys.'C.I.A'
> 
> I guess that means this will/should work, too:
> 
>     $'C.I.A'
> 
> Cheers
> A
> 

-- 
McIntosh Cooey - Twelve Hundred Group LLC - http://www.1200group.com/