[Templates] format plugin can't work with TT list refs

Andy Wardley abw@andywardley.com
Mon, 13 Oct 2003 19:52:29 +0100


Stas Bekman wrote:
>   foo = [ 1 2 3 ];
>   USE format_foo = format("%d %d %d");
>   format_foo(foo);

[...]

> basically coercing the list ref into IV, instead of interpreting it as a 
> list. Did I miss something obvious or is that a bug in that plugin?

It's more of a limitation in the design.  TT treats all lists as list
references and doesn't have a nice way to return the contents of the 
list.  i.e. you can't do the Perl equivalent of @$listref.

The problem is in the stash.  Say you were to write a new list
vmethod that returned the items in the list:

  $context->define_vmethod( list => items => sub { @$_[0] } );

You would expect to use it like so:

    format_foo(foo.items)    # doesn't work in TT2

However, when the stash calls the vmethod (in fact any method, or sub),
it automatically folds a list of items into a reference to a list of 
items.  foo.items returns a list, but format_foo() gets passed a list 
ref.

I originally did this to support as many existing Perl modules that may
return items.  In hindsight, it was a bad design decision.  It is useful
but causes action-at-a-distance that probably catches more people out than
it helps.  The documentation has long since said that returning a naked
list of items (i.e. not a reference to a list) is frowned upon and may 
not be supported in future versions.

TT3 is that future version.  As well as being able to write vmethods that
return multiple items, as in the above example, I think I might also support
'@' as a shortcut sigil.

    format_foo(foo.items)   # should work in TT3
    format_foo(@foo)        # also work in TT3

I'm using '@' in the same way as '$' is used in TT, to indicate interpolation
of a variable rather than being an indicator of the underlying data type, 
as it is in Perl.  In TT is should be possible to put a '@' in front of 
any variable.

    @hash     # same as hash.items    
    @list     # same as list.items
    @text     # same as text.items

In certain cases, these will be no-ops, as per the current .list .hash and
.item vmethods that effectively cast one type to another.  

A