#!/usr/bin/perl use strict; use Test::More; # Pure perl mock-up of builtin list() counterpart to scalar() sub list { return @_[ 0 .. $#_ ]; } # Our example demo function, it doesn't do anything useful however # ---------------------------------------------------------------- sub incr_str_returned_from { my $sub_ref = shift; # You might be a careful professional and pick one explicitly: # my $scalar = ( $sub_ref->() )[-1]; # But you might be not and forget to make sure a given # sub-ref returns something useful in scalar context. You might # consider it to return a list and conclude that you'll simply # increment the last value in it. But this is not safe: my $scalar = $sub_ref->(); return ++$scalar; # (Did you know: Perl increments alphabetic # strings like numbers of base 26) } my @expected = qw( xxx foo bar baz ); is_deeply [ Client::Module::valid_scalars_1() ], \@expected, "test without list() in list context"; is_deeply [ Client::Module::valid_scalars_2() ], \@expected, "test with list() in list context"; is incr_str_returned_from(\&Client::Module::valid_scalars_1) => 5, "Oops, grep without list() maybe 'misbehaves' in scalar context:" ." gets number of elements"; is incr_str_returned_from(\&Client::Module::valid_scalars_2)=>'bba', "list(grep ...) in scalar context:" ." evaluates to last value like literal lists"; my %hash = ( a => 3 ); my @test1 = \( $hash{a}, @expected, 'zzz' ); is scalar grep( { ref eq 'SCALAR' } @test1 ), 2, "Without list(), we get a list of references to lvalues"; my @test2 = \( $hash{a}, list(@expected), 'zzz' ); is scalar grep( { ref eq 'SCALAR' } @test2 ), 6, "With list(), we get a list of references to plain rvalues"; ${ $test2[0] }++; is $hash{a}, 4, "Indirect increment via reference to hash element"; ${$test2[2]} = 'bla'; TODO: { local $TODO = "Perl core devs be welcome to decide if they " . "implement list() that way or not"; is $expected[1], 'bla', "Values returned by and passed to list() are identical"; } done_testing; package Client::Module; sub valid_scalars_1 { return grep { defined $_ } # stub grep routine 'xxx', qw(foo bar baz), undef; # demo values } sub valid_scalars_2 { return ::list valid_scalars_1() } __END__