Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assignments inside lists misbehave #7483

Open
p5pRT opened this issue Aug 31, 2004 · 6 comments
Open

Assignments inside lists misbehave #7483

p5pRT opened this issue Aug 31, 2004 · 6 comments

Comments

@p5pRT
Copy link

p5pRT commented Aug 31, 2004

Migrated from rt.perl.org#31403 (status was 'open')

Searchable as RT31403$

@p5pRT
Copy link
Author

p5pRT commented Aug 31, 2004

From jerabek@math.cas.cz

Created by jerabek@math.cas.cz

When a variable followed by an assignment to the same variable are
both interpolated in a list, the result is bogus.

Specifically, the original length of an array is preserved, but the
slots are filled using the new value of the variable, repeated if the
new value is shorter.

(I hope the examples are more clear than the description.)

[]% perl -e '@​a = (1, 2, 3, 4, 5); @​b = (@​a, (@​a = (8, 9))); print "@​b\n"'
8 9 8 9 8 8 9
[
]% perl -e '$a = 1; @​b = ($a, ($a += 2)); print "@​b\n"'
3 3

Notice that this affects in particular the common "reverse comma"
idiom ($a, ...)[0].

Cheers,
Emil Jerabek

Perl Info

Flags:
    category=core
    severity=medium

Site configuration information for perl v5.8.3:

Configured by bhcompile at Tue Mar 23 20:55:12 EST 2004.

Summary of my perl5 (revision 5.0 version 8 subversion 3) configuration:
  Platform:
    osname=linux, osvers=2.4.21-9.elsmp, archname=i386-linux-thread-multi
    uname='linux bugs.devel.redhat.com 2.4.21-9.elsmp #1 smp thu jan 8 17:08:56 est 2004 i686 i686 i386 gnulinux '
    config_args='-des -Doptimize=-O2 -g -pipe -march=i386 -mcpu=i686 -Dversion=5.8.3 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dinc_version_list=5.8.2 5.8.1 5.8.0'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
    optimize='-O2 -g -pipe -march=i386 -mcpu=i686',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -I/usr/include/gdbm'
    ccversion='', gccversion='3.3.2 20031218 (Red Hat Linux 3.3.2-5)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libperl.so
    gnulibc_version='2.3.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.3/i386-linux-thread-multi/CORE'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    


@INC for perl v5.8.3:
    /usr/lib/perl5/5.8.3/i386-linux-thread-multi
    /usr/lib/perl5/5.8.3
    /usr/lib/perl5/site_perl/5.8.3/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.2/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.1/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.3
    /usr/lib/perl5/site_perl/5.8.2
    /usr/lib/perl5/site_perl/5.8.1
    /usr/lib/perl5/site_perl/5.8.0
    /usr/lib/perl5/site_perl
    /usr/lib/perl5/vendor_perl/5.8.3/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.2/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.1/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.3
    /usr/lib/perl5/vendor_perl/5.8.2
    /usr/lib/perl5/vendor_perl/5.8.1
    /usr/lib/perl5/vendor_perl/5.8.0
    /usr/lib/perl5/vendor_perl
    .


Environment for perl v5.8.3:
    HOME=/home/emil
    LANG=cs_CZ.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/kerberos/bin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/home/emil/bin:/usr/java/j2re1.4.2_03/bin
    PERL_BADLANG (unset)
    SHELL=/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Sep 1, 2004

From @iabyn

On Tue, Aug 31, 2004 at 01​:02​:16PM -0000, jerabek @​ math. cas. cz wrote​:

When a variable followed by an assignment to the same variable are
both interpolated in a list, the result is bogus.

Specifically, the original length of an array is preserved, but the
slots are filled using the new value of the variable, repeated if the
new value is shorter.

(I hope the examples are more clear than the description.)

[]% perl -e '@​a = (1, 2, 3, 4, 5); @​b = (@​a, (@​a = (8, 9))); print "@​b\n"'
8 9 8 9 8 8 9
[
]% perl -e '$a = 1; @​b = ($a, ($a += 2)); print "@​b\n"'
3 3

Thanks for the report. This one can be chalked up to the "for efficiency,
Perl does not reference count items pushed on the stack" problem, which
introduces a class of jolly bugs which are essentially unfixable in Perl
5 :-(

The 3,4,5 elements of @​a are pushed on the stack, and then get freed
by the assignnent to @​a. The freed items then get reused elswhere while
still on the stack, then get assigned to @​b.

Notice that this affects in particular the common "reverse comma"
idiom ($a, ...)[0].

I'm not sure what you mean there.

The problem should only occur if an item is freed while still on the stack,
eg by an assignment within a list.

Dave.

--
To collect all the latest movies, simply place an unprotected ftp server
on the Internet, and wait for the disk to fill....

@p5pRT
Copy link
Author

p5pRT commented Sep 1, 2004

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Sep 1, 2004

From @ysth

On Wed, Sep 01, 2004 at 09​:44​:56PM +0100, Dave Mitchell <davem@​iabyn.com> wrote​:

On Tue, Aug 31, 2004 at 01​:02​:16PM -0000, jerabek @​ math. cas. cz wrote​:

When a variable followed by an assignment to the same variable are
both interpolated in a list, the result is bogus.

Specifically, the original length of an array is preserved, but the
slots are filled using the new value of the variable, repeated if the
new value is shorter.

(I hope the examples are more clear than the description.)

[~]% perl -e '@​a = (1, 2, 3, 4, 5); @​b = (@​a, (@​a = (8, 9))); print "@​b\n"'
8 9 8 9 8 8 9

Unfixable bug, as Dave says.

[~]% perl -e '$a = 1; @​b = ($a, ($a += 2)); print "@​b\n"'
3 3

Correct behaviour. If you want to make a list of the initial numeric
value of $a followed by $a incremented by 2, say ($a+0, ($a += 2)).

A variable is an lvalue, even in a list. Since the += happens before
the assignment to @​b, at the time of the assignment, the value of the
first element in the list has changed to 3.

Thanks for the report. This one can be chalked up to the "for efficiency,
Perl does not reference count items pushed on the stack" problem, which
introduces a class of jolly bugs which are essentially unfixable in Perl
5 :-(

I've often wondered if it would actually *increase* efficiency to
start refcounting the stack. We go to an awful lot of work to avoid
doing so.

The 3,4,5 elements of @​a are pushed on the stack, and then get freed
by the assignnent to @​a. The freed items then get reused elswhere while
still on the stack, then get assigned to @​b.

Notice that this affects in particular the common "reverse comma"
idiom ($a, ...)[0].

I'm not sure what you mean there.

He's referring to the second case, which isn't a bug.

@p5pRT
Copy link
Author

p5pRT commented Sep 1, 2004

From @iabyn

On Wed, Sep 01, 2004 at 03​:06​:10PM -0700, Yitzchak Scott-Thoennes wrote​:

I've often wondered if it would actually *increase* efficiency to
start refcounting the stack. We go to an awful lot of work to avoid
doing so.

yes, such as adding half the stuff we push onto the tmps stack too,
just so we are sure they get freed at the end.

If it was just a case of changing the various PP macros, I'd consider
trying it. But I think in practice it would break a whole bunch of
XS code.

--
A walk of a thousand miles begins with a single step...
then continues for another 1,999,999 or so.

@p5pRT
Copy link
Author

p5pRT commented Sep 2, 2004

From @hvds

Dave Mitchell <davem@​iabyn.com> wrote​:
:On Wed, Sep 01, 2004 at 03​:06​:10PM -0700, Yitzchak Scott-Thoennes wrote​:
:> I've often wondered if it would actually *increase* efficiency to
:> start refcounting the stack. We go to an awful lot of work to avoid
:> doing so.
:
:yes, such as adding half the stuff we push onto the tmps stack too,
:just so we are sure they get freed at the end.
:
:If it was just a case of changing the various PP macros, I'd consider
:trying it. But I think in practice it would break a whole bunch of
:XS code.

If we've done things right, it should in principle be possible to leave
a legacy interface to allow old XS code to continue working and support
a new way of doing things with a new set of macros. Have we done things
as right as that?

I'd be quite interested to see what sort of improvements we might be
able to get with this approach, but unless a compatibility mode is
possible without throwing away all the theoretical advantages it seems
like a lot of work to get a small amount of extra data - I suspect
it would be difficult to remove the old macros even after an extensive
deprecation cycle.

Hugo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants