28

Should x < $foo < y read from $foo once or twice? Perl debates

 3 years ago
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

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK