Should x < $foo < y read from $foo once or twice? Perl debates
source link: https://github.com/Perl/perl5/issues/17692
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Description
The perlop docs describe the current behavior, so this doesn't contradict anything.
A chained comparison in 5.31.10 appears to evaluate the middle condition twice for a tied scalar but doesn't warn about it. Since a programmer might not realize they are using a tied variable, they might see odd behavior.
Steps to Reproduce
use v5.31.10; package UnstableScalar { use parent qw(Tie::Scalar); sub TIESCALAR { bless {}, $_[0] } sub FETCH { my $value = int rand 10; say "Fetching scalar with $value"; return $value; } } tie my $unstable, 'UnstableScalar'; if( 5 < $unstable < 9 ) { say "Found a value between 5 and 9"; }
The comparison short circuits just fine, but if the first comparison is true, the tied scalar is evaluated again (so things such as Tie::Cycle
will unexpectedly progress or skip values):
$ perl5.31.10 ~/Desktop/test.pl Fetching scalar with 2 $ perl5.31.10 ~/Desktop/test.pl Fetching scalar with 0 $ perl5.31.10 ~/Desktop/test.pl Fetching scalar with 9 Fetching scalar with 2 Found a value between 5 and 9 $ perl5.31.10 ~/Desktop/test.pl Fetching scalar with 6 Fetching scalar with 9
Expected behavior
I expect that the scalar would only call FETCH
once and reuse the result in the second comparison. perlop
says this may happen, but perhaps a warning would be useful here. Ideally, tied variables would be evaluated once.
Is there a chance that the internals could recognize this and use the tied object instead of the scalar itself? This works as expected:
if( 5 < tied($unstable)->FETCH < 9 ) { say "Found a value between 5 and 9"; }
Perl configuration
Summary of my perl5 (revision 5 version 31 subversion 10) configuration: Platform: osname=darwin osvers=19.3.0 archname=darwin-2level uname='darwin otter.local 19.3.0 darwin kernel version 19.3.0: thu jan 9 20:58:23 pst 2020; root:xnu-6153.81.5~1release_x86_64 x86_64 ' config_args='-des -Dprefix=/usr/local/perls/perl-5.31.10 -Dusedevel' hint=recommended useposix=true d_sigaction=define useithreads=undef usemultiplicity=undef use64bitint=define use64bitall=define uselongdouble=undef usemymalloc=n default_inc_excludes_dot=define bincompat5005=undef Compiler: cc='cc' ccflags ='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.15 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -DPERL_USE_SAFE_PUTENV' optimize='-O3' cppflags='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.15 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include' ccversion='' gccversion='4.2.1 Compatible Apple LLVM 11.0.0 (clang-1100.0.33.17)' 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 =' -mmacosx-version-min=10.15 -fstack-protector-strong -L/usr/local/lib' libpth=/usr/local/lib /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.0/lib /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib /usr/lib libs=-lpthread -ldbm -ldl -lm -lutil -lc perllibs=-lpthread -ldl -lm -lutil -lc libc= so=dylib useshrplib=false libperl=libperl.a gnulibc_version='' Dynamic Linking: dlsrc=dl_dlopen.xs dlext=bundle d_dlsymun=undef ccdlflags=' ' cccdlflags=' ' lddlflags=' -mmacosx-version-min=10.15 -bundle -undefined dynamic_lookup -L/usr/local/lib -fstack-protector-strong' Characteristics of this binary (from libperl): Compile-time options: HAS_TIMES PERLIO_LAYERS PERL_COPY_ON_WRITE PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP PERL_OP_PARENT PERL_PRESERVE_IVUV PERL_USE_DEVEL PERL_USE_SAFE_PUTENV USE_64_BIT_ALL USE_64_BIT_INT USE_LARGE_FILES USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE USE_LOCALE_NUMERIC USE_LOCALE_TIME USE_PERLIO USE_PERL_ATOF Built under darwin Compiled at Mar 27 2020 01:45:56 %ENV: PERL="/Users/brian/bin/perls/perl-latest" PERL5_PATH="/Users/brian/bin/perls" PERL6_PATH="/Users/brian/bin/perl6s:/Applications/Rakudo/bin:/Applications/Rakudo/share/perl6/site/bin" PERLDOTCOM_AUTHOR="brian d foy" @INC: /usr/local/perls/perl-5.31.10/lib/site_perl/5.31.10/darwin-2level /usr/local/perls/perl-5.31.10/lib/site_perl/5.31.10 /usr/local/perls/perl-5.31.10/lib/5.31.10/darwin-2level /usr/local/perls/perl-5.31.10/lib/5.31.10
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK