-
Notifications
You must be signed in to change notification settings - Fork 589
Description
Module: builtin
Description
One of the great things about ref() is that it always returns a
string, meaning that it's easy to use---even under 'warnings'---without
having to perform other tests on the argument or result first. Even
ref(undef) returns a defined value.
Contrast builtin::reftype(), which returns undef for non-references.
This makes it harder to use in code that may operate on mixed scalars
and references (tree walks, etc).
This also renders the advice in the UNIVERSAL(3) pod incorrect,
where it says:
Previous versions of this documentation suggested using "isa"
as a function to determine the type of a reference:
$yes = UNIVERSAL::isa($h, "HASH");
$yes = UNIVERSAL::isa("Foo", "Bar");
The problem is that this code would never call an overridden
"isa" method in any class. Instead, use "reftype" from
Scalar::Util for the first case:
use Scalar::Util 'reftype';
$yes = reftype( $h ) eq "HASH";
This works without warnings when $h isn't a reference:
$yes = UNIVERSAL::isa($h, "HASH");
This doesn't:
$yes = reftype( $h ) eq "HASH";
You have to use one of these instead:
$yes = ref($h) ne '' && reftype( $h ) eq "HASH";
$yes = defined reftype( $h ) && reftype( $h ) eq "HASH";
$yes = (reftype( $h ) // '') eq "HASH";
$yes = do { my $t = reftype( $h ); defined $t && $t eq "HASH" };
Having ref() return '' for non-references may be unexpected, but
it has great UX. reftype() should follow that.
Steps to Reproduce
use v5.40;
my($scalar, $undef) = ( 'foo' );
these are good
if (ref($scalar) eq 'HASH') { say "process hash"; }
if (ref($undef) eq 'ARRAY') { say "process array"; }
these warn
if (reftype($scalar) eq 'HASH') { say "process hash"; }
if (reftype($undef) eq 'ARRAY') { say "process array"; }
say "scalar = $scalar";
Expected behavior
Script should output "scalar = foo", but instead emits warnings to get this:
Use of uninitialized value $scalar in string eq at - line 10.
Use of uninitialized value $undef in string eq at - line 11.
scalar = foo
(side note: that first error is misleading/confusing to claim that
$scalar is uninitialized when it clearly contains 'foo')
Perl configuration
Site configuration information for perl 5.40.1:
Configured by root at Thu Jan 1 0:00:00 UTC 1970.
Summary of my perl5 (revision 5 version 40 subversion 1) configuration:
Platform:
osname=openbsd
osvers=7.6
archname=amd64-openbsd
uname='openbsd'
config_args='-dse -Dopenbsd_distribution=defined -Dmksymlinks'
hint=recommended
useposix=true
d_sigaction=define
useithreads=undef
usemultiplicity=undef
use64bitint=define
use64bitall=define
uselongdouble=undef
usemymalloc=n
default_inc_excludes_dot=define
Compiler:
cc='cc'
ccflags ='-DNO_LOCALE_NUMERIC -DNO_LOCALE_COLLATE -DNO_LOCALE_NUMERIC -DNO_LOCALE_COLLATE -DNO_LOCALE_MONETARY -DNO_
LOCALE_TIME -DNO_LOCALE_MESSAGES -DLIBC_HANDLES_MISMATCHED_CTYPE -fno-strict-aliasing -fno-delete-null-pointer-checks -p
ipe -fstack-protector-strong -I/usr/local/include'
optimize='-O2'
cppflags='-DBIG_TIME -DNO_LOCALE_NUMERIC -DNO_LOCALE_COLLATE -DNO_LOCALE_NUMERIC -DNO_LOCALE_COLLATE -DNO_LOCALE_MON
ETARY -DNO_LOCALE_TIME -DNO_LOCALE_MESSAGES -DLIBC_HANDLES_MISMATCHED_CTYPE -fno-strict-aliasing -fno-delete-null-pointe
r-checks -pipe -fstack-protector-strong -I/usr/local/include'
ccversion=''
gccversion='OpenBSD Clang 16.0.6'
gccosandvers=''
intsize=4
longsize=8
ptrsize=8
doublesize=8
byteorder=12345678
doublekind=3
d_longlong=define
longlongsize=8
d_longdbl=define
longdblsize=16
longdblkind=3
ivtype='long'
ivsize=8
nvtype='double'
nvsize=8
Off_t='off_t'
lseeksize=8
alignbytes=8
prototype=define
Linker and Libraries:
ld='cc'
ldflags ='-Wl,-E -fstack-protector-strong -L/usr/local/lib'
libpth=/usr/lib /usr/lib/clang/16/lib
libs=-lm -lc
perllibs=-lm -lc
libc=/usr/lib/libc.so.100.3
so=so
useshrplib=true
libperl=libperl.so.25.0
gnulibc_version=''
Dynamic Linking:
dlsrc=dl_dlopen.xs
dlext=so
d_dlsymun=undef
ccdlflags='-Wl,-R/usr/libdata/perl5/amd64-openbsd/CORE'
cccdlflags='-DPIC -fpic '
lddlflags='-shared -fpic -fstack-protector-strong -L/usr/local/lib'
---
@INC for perl 5.40.1:
/usr/local/libdata/perl5/site_perl/amd64-openbsd
/usr/local/libdata/perl5/site_perl
/usr/libdata/perl5/amd64-openbsd
/usr/libdata/perl5
---
Environment for perl 5.40.1:
HOME=/home/users/guenther
LANG (unset)
LANGUAGE (unset)
LC_CTYPE=C.UTF-8
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/home/users/guenther/bin:/bin:/usr/bin:/usr/local/bin:/usr/local/sbin:/sbin:/usr/sbin:/usr/X11R6/bin:/usr/games
PERL_BADLANG (unset)
SHELL=/bin/ksh