Skip to content

Chained comparison evaluates tied scalar twice #17692

@briandfoy

Description

@briandfoy

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions