Еще Один Способ Выстрелить Себе В Ногу В Perl

Давайте посмотрим на код:

  
  
  
   

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

Может ли mysub принять в качестве первого аргумента что-то истинное в логическом контексте? Казалось бы, нет, ведь для этого $x должна быть ссылкой на массив, а его первый элемент должен содержать подстроку abc. Но оказалось, что это можно

$perl poc.pl ARRAY(0xdb6d48) ARRAY(0xdb6d48)

В чем дело?
  1. в Perl (как и во многих других языках) Икс && Да , если Икс - false, вернет не просто false (без выполнения Да ), и вернет его сам Икс (что должно быть ложным)
  2. Все параметры в Perl передаются по ссылке, а не по значению.

Таким образом, когда вычисляется первый аргумент

$x && $x->[0] =~ /abc/

$x имеет значение undef, то есть ложь, поэтому вместо первого аргумента передается сам $x, когда оценивается второй аргумент, $x присваивается значение [] (ссылка на пустой массив), поэтому, когда код mysub начинает выполняться, оба аргумента содержит ссылку на $x (который представляет собой пустой массив, что, в свою очередь, верно) Если кажется, что на практике код выглядит не очень применимо, то могу сказать, что ошибка была найдена в реальном коде юнит-теста:

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

(в то же время еще одна замечательная особенность работ Перла Автовивификация - если вы обращаетесь к $errors-> [0], то будут созданы $errors, если $errors раньше был undef) Теги: #perl #ошибки кода #perl #программирование
Вместе с данным постом часто просматривают: