Another way to shoot yourself in Perl

    Let's look at the code:

    use strict;
    use warnings;
    sub mysub($$)
        my ($a, $b) = @_;
        print "$a\n";
        print "$b\n";
    my $x = undef;
    mysub($x && $x->[0] =~ /abc/, $x = []);

    Can mysub as the first argument get something that in the boolean context is true?

    It would seem not, because for this $ x should be a reference to the array, and its first element should contain the substring 'abc'

    But it turned out that it could

    What is the matter?

    1. in Perl (as in many other languages) X && Y , if X is false, will return not just false (without executing Y ), but X itself (which should be false)
    2. All parameters in Perl are passed by reference, not by value.

    Thus, when the first argument is calculated
    $x && $x->[0] =~ /abc/

    $ x is undef i.e. false, therefore, instead of the first argument, $ x itself is passed
    when the second argument is calculated, $ x is assigned the value [] (a reference to an empty array), so when mysub code starts to run, both arguments
    contain a link to $ x (which is an empty array, which, in turn, is true)

    If it seems that the code does not seem very applicable in practice, then I can say that the bug was found in the real unit test code:

    ok( ($errors && ($errors->[0] =~ /My Exception/i)), "should catch exception $errors->[0]" );

    (in this case, another wonderful feature of the Autovivification pearl is triggered - if you turn to $ errors -> [0] then $ errors will be created
    if $ errors was undef before)

    Also popular now: