When a Perl operator returns only true or false, it returns one of two statically-allocated scalars called &PL_sv_yes and &PL_sv_no. It's more efficient to return these than to allocate a new scalar every time.
There's a third statically-allocated scalar: &PL_sv_undef. It's used by Perl when it needs to return undef.
$ perl -MDevel::Peek -e'Dump(undef)'
SV = NULL(0x0) at 0x2186148
REFCNT = 2147483639
FLAGS = (READONLY,PROTECT)
This scalar is undefined because it has no OK flags. But notice the artificially high REFCNT that prevents it from being deallocated. This tells us that Perl returned &PL_sv_undef. I shall call this "the undef", in contrast to other undefined scalars which I'll call "an undef".
An array element that has never been allocated (e.g. because nothing was ever assigned to it, or because delete was used on it) returns the undef.
$ perl -MDevel::Peek -e'Dump($a[0])'
SV = NULL(0x0) at 0x1116148
REFCNT = 2147483639
FLAGS = (READONLY,PROTECT)
Otherwise, the array element itself is returned, which might be an undef.
$ perl -MDevel::Peek -e'$a[0]=undef; Dump($a[0])'
SV = NULL(0x0) at 0xc93f90
REFCNT = 1
FLAGS = ()
The feature is meant to be triggered when you literally use undef in the code. But what it actually does is check for the undef.
use feature qw( say );
my @a;
{ say open(my $fh, '<', $a[0]) ? 1 : 0; } # 1
$a[1] = undef;
{ say open(my $fh, '<', $a[0]) ? 1 : 0; } # 1
$a[0] = undef;
{ say open(my $fh, '<', $a[0]) ? 1 : 0; } # 0
delete($a[0]);
{ say open(my $fh, '<', $a[0]) ? 1 : 0; } # 1
As you've discovered, this is an imperfect proxy.
|