develooper Front page | perl.perl5.porters | Postings from November 2011

[perl #103212] Split to list assignment in scalar context

From:
Zsban Ambrus
Date:
November 8, 2011 14:37
Subject:
[perl #103212] Split to list assignment in scalar context
Message ID:
rt-3.6.HEAD-31297-1320791825-1374.103212-75-0@perl.org
# New Ticket Created by  Zsban Ambrus 
# Please include the string:  [perl #103212]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=103212 >


This is a bug report for perl from ambrus@math.bme.hu,
generated with the help of perlbug 1.39 running under perl 5.14.2.


-----------------------------------------------------------------
[Please describe your issue here]


This command gives an unexpected result:

$ perl -wE 'say scalar(($_x, $_y) = split "/", "one/two/three/four/five");'
3

One would naively think it should return 5, just like this command:

$ perl -wE 'say scalar((@_x) = split "/", "one/two/three/four/five");'
5

for the split returns a list of five strings and the list assignment returns
the number of scalars assigned.

The surprising behaviour of the first command is actually sort-of documented
in the perlfunc entry for split:

  When assigning to a list, if LIMIT is omitted, or zero, Perl supplies a
  LIMIT one larger than the number of variables in the list, to avoid
  unnecessary work.

So in the first command, split("/", $s) is silently changed to split("/",
$s, 3) by the optimizer because it's assigned to a list of scalars, which
made split return three strings only.  However, this documentation says this
is done only "to avoid unnecessary work", which I take as meaning this
shouldn't have an observable side effect.

I propose that you change split to use this implicit limit only when this
has no observable side effects, for example if the optimizer knows the list
assignment is always evaluated in void context.


This came up in the real world by the way, and I was utterly baffled by it
for a while: "http://www.perlmonks.com/?node_id=934401".

By the way, the bug still happens if you add an explicit limit of 0, eg.

$ perl -wE 'say scalar(($_x, $_y) = split "/", "one/two/three/four/five",
0);'
3

which is completely against what the docs say, as noted by core bug #3247
("https://rt.perl.org/rt3/Ticket/Display.html?id=3247"; that bug says it's
resolved, but it seems it's not).

Also, the bug is still present in perlblead as of a few weeks ago.

--
Ambrus


[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=core
    severity=low
---
Site configuration information for perl 5.14.2:

Configured by ambrus at Sat Oct  1 19:00:08 CEST 2011.

Summary of my perl5 (revision 5 version 14 subversion 2) configuration:

  Platform:
    osname=linux, osvers=2.6.37, archname=x86_64-linux
    uname='linux king 2.6.37 #6 smp sun mar 13 20:15:05 cet 2011
x86_64 gnulinux '
    config_args='-Dprefix=/usr/local/perl5.14
-Dman1dir=/usr/local/share/man/man1
-Dman3dir=/usr/local/share/man/man3
-Dsiteman1dir=/usr/local/share/man/man1
-Dsiteman3dir=/usr/local/share/man/man3 -d'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector
-I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.6.1', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib/../lib64 /usr/lib/../lib64 /lib
/usr/lib /lib64 /usr/lib64 /usr/local/lib64
    libs=-lnsl -ldl -lm -lcrypt -lutil -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=/lib/libc-2.11.2.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.11.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib
-fstack-protector'

Locally applied patches:


---
@INC for perl 5.14.2:
    /usr/local/perl5.14/lib/site_perl/5.14.2/x86_64-linux
    /usr/local/perl5.14/lib/site_perl/5.14.2
    /usr/local/perl5.14/lib/5.14.2/x86_64-linux
    /usr/local/perl5.14/lib/5.14.2
    /usr/local/perl5.14/lib/site_perl/5.14.1/x86_64-linux
    /usr/local/perl5.14/lib/site_perl/5.14.1
    /usr/local/perl5.14/lib/site_perl/5.14.0/x86_64-linux
    /usr/local/perl5.14/lib/site_perl/5.14.0
    /usr/local/perl5.14/lib/site_perl
    .

---
Environment for perl 5.14.2:
    HOME=/home/ambrus
    LANG (unset)
    LANGUAGE (unset)
    LC_CTYPE=hu_HU
    LD_LIBRARY_PATH=/home/ambrus/local/lib/
    LOGDIR (unset)
    PATH=/home/ambrus/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games
    PERL_BADLANG (unset)
    SHELL=/usr/local/bin/bash




nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About