[Templates] listifying "scalars"

Jess Robinson castaway@desert-island.demon.co.uk
Mon, 20 Nov 2006 22:11:42 +0000 (GMT)


On Mon, 20 Nov 2006, Jess Robinson wrote:

>
>
> On Mon, 25 Sep 2006, Jess Robinson wrote:
>
>>
>>  Hi folks,
>>
>>  The 2.15 has an enhancement whereby using .list on a "scalar" should turn
>>  it into a list. I quote the word "scalar", because it appears to really
>>  mean "simple scalar", i.e. not references, or blessed refs. The docs
>>  should probably reflect this.
>>
>>  Anyway, that leaves me with a problem. My sub returns a list of blessed
>>  objects, except that when there's only one, TT conveniently de-listifies
>>  the result, however since I'd like to access it as a list anyway, I used
>>  .list on it, which conveniently turns it into a list of hashrefs with
>>  values and keys.. i.e. treats it as a hashref. Code that worked in 2.14,
>>  in the SQL::Translator test suite i.e.:
>>
>>  [% table.pkey_fields.join(", ") %]
>>
>>  Now fails to work in 2.15, when the result of pkey_fields is a single
>>  object.. Adding .list does not fix this.
>>
>>  Any ideas how to fix this backwards compat problem, or how to make the
>>  test suite work with lists of blessed scalars?
>>
>>  Jess
>
> Since nobody appears to want to play this game, I've delved in the fun Stash 
> code myself.. after much debugging it appears that:
>
> Calling a sub that returns a list of items is a list iff there is more than 
> one item in it, in TT. (This behaviour is used internally and thus I guess 
> can't be changed).
>
> Calling "list" or "first" or any other list method on a single blessed 
> hashref causes, in the first instance, the hash_list method to be called 
> (that only appeared in v2.15, and is already marked as planned to disappear 
> again by v3.. what is it for?), and in the second instance, .first fails to 
> be called at all, as the old ploy of dropping through to try scalar and list 
> ops when no matching method was found has been effectively turned off.. Was 
> this on purpose?
>
> The relevant change is this code in Stash.pm:
>
> ## under     elsif (ref($root) && UNIVERSAL::can($root, 'can')) {
>
> 2.14:
>
>            if (UNIVERSAL::isa($root, 'HASH')
>                 && defined($value = $root->{ $item })) {
>                 return $value unless ref $value eq 'CODE';      ## RETURN
>                 @result = &$value(@$args);
>             }
>
> Which drops through if it's hash-based and theres no such value
>
> 2.15:
>
>             if (UNIVERSAL::isa($root, 'HASH') ) {
>                 if( defined($value = $root->{ $item })) {
>                     return $value unless ref $value eq 'CODE'; ## RETURN
>                     @result = &$value(@$args);
>                 }
>                 elsif ($value = $HASH_OPS->{ $item }) {
>                     @result = &$value($root, @$args);
>                 }
>            }
> Which doesn't..
>
>
> So, a) shall I make a test patch that fails, b) patch Stash.pm to fall 
> through, or c) go patch the code that seems to rely on an undocumented 2.14 
> feature?

Oops, c) was supposed to mean: "Go patch MY code that relies on 
an undocumented feature" .. (or SQL::Translators, anyway)

Jess