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

bug or feature? foreach (sort @array) {y/a-z/A-Z/;} # @array modified! #8029

Closed
p5pRT opened this issue Jul 21, 2005 · 21 comments
Closed

bug or feature? foreach (sort @array) {y/a-z/A-Z/;} # @array modified! #8029

p5pRT opened this issue Jul 21, 2005 · 21 comments

Comments

@p5pRT
Copy link

p5pRT commented Jul 21, 2005

Migrated from rt.perl.org#36616 (status was 'rejected')

Searchable as RT36616$

@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2005

From ping@bioservrp.es.dupont.com

Created by ping@bioservrp.es.dupont.com

@​arr = ('one', 'two', 'three', 'four');

foreach (sort @​arr)
{
  print ' ';
  print;
  y/a-z/A-Z/;
}

foreach(@​arr)
{
  print ' ';
  print;
}

The above code prints out " four one three two ONE TWO THREE FOUR".
Is this correct behavior? Seems sort in the above foreach context
returns a list of elements that are aliases to elements of @​arr.

Perl Info

Flags:
    category=core
    severity=none

Site configuration information for perl v5.8.0:

Configured by root at Thu Jan 16 19:08:23 EST 2003.

Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration:
  Platform:
    osname=solaris, osvers=2.8, archname=sun4-solaris
    uname='sunos bioservrd.es.dupont.com 5.8 generic_108528-16 sun4u sparc sunw,sun-fire '
    config_args=''
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='gcc', ccflags ='-fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O',
    cppflags='-fno-strict-aliasing'
    ccversion='', gccversion='3.1', gccosandvers='solaris2.8'
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags =' -L/usr/local/lib '
    libpth=/usr/local/lib /usr/lib /usr/ccs/lib
    libs=-lsocket -lnsl -ldl -lm -lc
    perllibs=-lsocket -lnsl -ldl -lm -lc
    libc=/lib/libc.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' '
    cccdlflags='-fPIC', lddlflags='-G -L/usr/local/lib'

Locally applied patches:
    


@INC for perl v5.8.0:
    /app/local/perl/lib/5.8.0/sun4-solaris
    /app/local/perl/lib/5.8.0
    /app/local/perl/lib/site_perl/5.8.0/sun4-solaris
    /app/local/perl/lib/site_perl/5.8.0
    /app/local/perl/lib/site_perl
    .


Environment for perl v5.8.0:
    HOME=/home/ping
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH=/local/oracle/8.1.5/lib:/usr/openwin/lib:/usr/db/lib:/usr/lib:/usr/openwin/lib:/opt/SUNWspro/lib:/usr/local/lib:/app/local/lib:/usr/lib:/usr/openwin/lib:/opt/SUNWspro/lib:/app/local/lib:/app/local1/lib:/app/sfw/lib:/usr/lib/sparcv9:/app/local/lib/sparcv9
    LOGDIR (unset)
    PATH=/usr/openwin/bin/xview:/usr/openwin/bin:/app/workshop/SUNWspro/bin:/opt/SUNWspro/bin:/usr/ccs/bin:/usr/ucb:/usr/bin:/usr/local/progs:/usr/local/bin:/usr/local/gde:/usr/etc:/home/ping/bin:/home/ping/perl:/util/local/scripts:.:/usr/local/mysql/bin:/home/ping/bin/SUN4OS5:/home/ping/hz/bin/SUN4OS5:/home/ping/java/java/bin:/lsf/bin:/opt/sfw/bin:/opt/sfw/sbin:.:/local/oracle/8.1.5/bin:/etc/init.d/local:/opt/bin:/bin:/usr/ccs/bin
    PERL_BADLANG (unset)
    SHELL=/bin/tcsh


This communication is for use by the intended recipient and contains 
information that may be privileged, confidential or copyrighted under
applicable law.  If you are not the intended recipient, you are hereby
formally notified that any use, copying or distribution of this e-mail,
in whole or in part, is strictly prohibited.  Please notify the sender
by return e-mail and delete this e-mail from your system.  Unless
explicitly and conspicuously designated as "E-Contract Intended",
this e-mail does not constitute a contract offer, a contract amendment,
or an acceptance of a contract offer.  This e-mail does not constitute
a consent to the use of sender's contact information for direct marketing
purposes or for transfers of data to third parties.

 Francais Deutsch Italiano  Espanol  Portugues  Japanese  Chinese  Korean

            http://www.DuPont.com/corp/email_disclaimer.html



@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2005

From @petdance

Yes, this is correct. The loop variable is an alias.

@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2005

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

@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2005

@petdance - Status changed from 'open' to 'rejected'

@p5pRT p5pRT closed this as completed Jul 21, 2005
@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2005

From prev a.r.ferreira@gmail.com

The described behavior changes whether "sort @​arr" goes directly in
'for' or you assign it first to an array variable.

  @​arr = ('one', 'two', 'three', 'four');
  y/a-z/A-Z/ foreach sort @​arr;
  print "\na​: @​arr\n"

prints "a​: ONE TWO THREE FOUR" and

  @​arr = ('one', 'two', 'three', 'four');
  @​s = sort @​arr;
  y/a-z/A-Z/ foreach @​s;
  print "\na​: @​arr\n"

prints "a​: one two three four". This has to do with copy-on-assign?

That seems like a (subtle) feature. Otherwise, it is a very old bug​:
the same behavior with 5.8.6, 5.6.1, and 5.005_03.

@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2005

From ping@micro3.es.dupont.com

If it's a feature, then it's not documented at all. Larry's Perl books do not
mention it, the sort man page from perldoc does not mention it, and the manual
page from www.perl.org does not mention it. And this feature is against
intuition and I would consider it more a bug than a feature (what use it has?).
I think other people wouldn't expect @​array to be changed in the code above.
(New Perl programers may be surprised to know that foreach works on an alias,
but it's well documented (and warned) and such feature is at least useful under
some circumstances.) Conceptually, sort should return a true copy (sorted of
course) of its arguement and I think it is how people would understand it.
(How sort is implemented is a different matter. I guess sort is working on a
list of pointers to the elements of the original list and, in foreach context,
just returns a pointer to the list of pointers instead of making an anonymous
copy of the sort list.)

Thanks for your time.

From rt-a.r.ferreira=gmail.com@​perl.org Thu Jul 21 11​:03​:29 2005
Subject​: Re​: [perl #36616] bug or feature? foreach (sort @​array) {y/a-z/A-Z/;} # @​array modified!
From​: "Adriano Ferreira via RT" <perlbug-followup@​perl.org>
X-RT-Loop-Prevention​: perl
RT-Ticket​: perl #36616
Managed-by​: RT 3.0.11 (http​://www.bestpractical.com/rt/)
RT-Originator​: a.r.ferreira@​gmail.com
To​: ping@​bioservrp.es.dupont.com
X-RT-Original-Encoding​: utf-8
Date​: Thu, 21 Jul 2005 07​:34​:42 -0700
MIME-Version​: 1.0
Content-Transfer-Encoding​: 7bit

The described behavior changes whether "sort @​arr" goes directly in
'for' or you assign it first to an array variable.

@​arr = ('one', 'two', 'three', 'four');
y/a-z/A-Z/ foreach sort @​arr;
print "\na​: @​arr\n"

prints "a​: ONE TWO THREE FOUR" and

@​arr = ('one', 'two', 'three', 'four');
@​s = sort @​arr;
y/a-z/A-Z/ foreach @​s;
print "\na​: @​arr\n"

prints "a​: one two three four". This has to do with copy-on-assign?

That seems like a (subtle) feature. Otherwise, it is a very old bug​:
the same behavior with 5.8.6, 5.6.1, and 5.005_03.

This communication is for use by the intended recipient and contains
information that may be privileged, confidential or copyrighted under
applicable law. If you are not the intended recipient, you are hereby
formally notified that any use, copying or distribution of this e-mail,
in whole or in part, is strictly prohibited. Please notify the sender
by return e-mail and delete this e-mail from your system. Unless
explicitly and conspicuously designated as "E-Contract Intended",
this e-mail does not constitute a contract offer, a contract amendment,
or an acceptance of a contract offer. This e-mail does not constitute
a consent to the use of sender's contact information for direct marketing
purposes or for transfers of data to third parties.

Francais Deutsch Italiano Espanol Portugues Japanese Chinese Korean

  http​://www.DuPont.com/corp/email_disclaimer.html

@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2005

From ping@micro3.es.dupont.com

But shouldn't the alias be to the elements of the list returned by sort,
not to the elements of the original list? Should sort sort a copy of its
argument and return the sorted copy?

From rt-andy=petdance.com@​perl.org Thu Jul 21 10​:10​:59 2005
Subject​: [perl #36616] bug or feature? foreach (sort @​array) {y/a-z/A-Z/;} # @​array modified!
From​: "Andy Lester via RT" <perlbug-followup@​perl.org>
X-RT-Loop-Prevention​: perl
RT-Ticket​: perl #36616
Managed-by​: RT 3.0.11 (http​://www.bestpractical.com/rt/)
RT-Originator​: andy@​petdance.com
To​: ping@​bioservrp.es.dupont.com
X-RT-Original-Encoding​: utf-8
Date​: Thu, 21 Jul 2005 07​:08​:13 -0700
MIME-Version​: 1.0
Content-Transfer-Encoding​: 7bit

Yes, this is correct. The loop variable is an alias.

This communication is for use by the intended recipient and contains
information that may be privileged, confidential or copyrighted under
applicable law. If you are not the intended recipient, you are hereby
formally notified that any use, copying or distribution of this e-mail,
in whole or in part, is strictly prohibited. Please notify the sender
by return e-mail and delete this e-mail from your system. Unless
explicitly and conspicuously designated as "E-Contract Intended",
this e-mail does not constitute a contract offer, a contract amendment,
or an acceptance of a contract offer. This e-mail does not constitute
a consent to the use of sender's contact information for direct marketing
purposes or for transfers of data to third parties.

Francais Deutsch Italiano Espanol Portugues Japanese Chinese Korean

  http​://www.DuPont.com/corp/email_disclaimer.html

@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2005

From @schwern

On Thu, Jul 21, 2005 at 10​:20​:22AM -0400, Shiping Zhang wrote​:

But shouldn't the alias be to the elements of the list returned by sort,
not to the elements of the original list? Should sort sort a copy of its
argument and return the sorted copy?

That's what I'm thinking, that this is a sort/foreach optimization gone
wrong. foreach $_ works on aliases of the array its looping over but sort
does NOT sort in place. "foreach (sort @​a)" should not loop over aliases
to @​a any more than "foreach (map {$_} @​a)" should.

Its a bug.

--
Michael G Schwern schwern@​pobox.com http​://www.pobox.com/~schwern
ROCKS FALL! EVERYONE DIES!
  http​://www.somethingpositive.net/sp05032002.shtml

@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2005

From @iabyn

On Thu, Jul 21, 2005 at 01​:15​:39PM -0700, Michael G Schwern wrote​:

On Thu, Jul 21, 2005 at 10​:20​:22AM -0400, Shiping Zhang wrote​:

But shouldn't the alias be to the elements of the list returned by sort,
not to the elements of the original list? Should sort sort a copy of its
argument and return the sorted copy?

That's what I'm thinking, that this is a sort/foreach optimization gone
wrong. foreach $_ works on aliases of the array its looping over but sort
does NOT sort in place. "foreach (sort @​a)" should not loop over aliases
to @​a any more than "foreach (map {$_} @​a)" should.

I wouldn't expect map to maintain the alias, because map returns the
result of an expression; on the other hand, grep, like sort, returns the
original values, and like sort, it maintains the alias​:

  $ perl587 -we '@​a=qw(1 2 3); for (grep /\d/, @​a) { $_++ } print "@​a\n"'
  2 3 4
  $

I don't think its a bug so much as undocumented behaviour. "fixing" it
would involve doing a whole bunch of unneccessary copying in sort and
grep.

--
SCO - a train crash in slow motion

@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2005

From @gbarr

On Thu, July 21, 2005 3​:34 pm, Dave Mitchell said​:

On Thu, Jul 21, 2005 at 01​:15​:39PM -0700, Michael G Schwern wrote​:

On Thu, Jul 21, 2005 at 10​:20​:22AM -0400, Shiping Zhang wrote​:

But shouldn't the alias be to the elements of the list returned by
sort,
not to the elements of the original list? Should sort sort a copy of
its
argument and return the sorted copy?

That's what I'm thinking, that this is a sort/foreach optimization gone
wrong. foreach $_ works on aliases of the array its looping over but
sort
does NOT sort in place. "foreach (sort @​a)" should not loop over
aliases
to @​a any more than "foreach (map {$_} @​a)" should.

I wouldn't expect map to maintain the alias, because map returns the
result of an expression; on the other hand, grep, like sort, returns the
original values, and like sort, it maintains the alias​:

$ perl587 \-we '@&#8203;a=qw\(1 2 3\); for \(grep /\\d/\, @&#8203;a\) \{ $\_\+\+ \} print

"@​a\n"'
2 3 4
$

I don't think its a bug so much as undocumented behaviour. "fixing" it
would involve doing a whole bunch of unneccessary copying in sort and
grep.

And reverse and any XS sub that directly returns any of its
SV arguments (eg List​::Util​::shuffle), not to mention any sub
that returns a slice of @​_

Graham.

@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2005

From @iabyn

On Thu, Jul 21, 2005 at 04​:22​:19PM -0500, Graham Barr wrote​:

I don't think its a bug so much as undocumented behaviour. "fixing" it
would involve doing a whole bunch of unneccessary copying in sort and
grep.

And reverse and any XS sub that directly returns any of its
SV arguments (eg List​::Util​::shuffle), not to mention any sub
that returns a slice of @​_

Er, not the last one. subroutine returns make copies of the list

--
Monto Blanco... scorchio!

@p5pRT
Copy link
Author

p5pRT commented Jul 22, 2005

From @ysth

On Thu, Jul 21, 2005 at 04​:22​:19PM -0500, Graham Barr wrote​:

I don't think its a bug so much as undocumented behaviour. "fixing" it
would involve doing a whole bunch of unneccessary copying in sort and
grep.

And reverse and any XS sub that directly returns any of its
SV arguments (eg List​::Util​::shuffle), not to mention any sub
that returns a slice of @​_

And repeat​:

$ perl -we'$x = "f"; for (($x) x 2) { print "in​: $_\n"; $_ .= "o"; print "out​: $_\n" }'
in​: f
out​: fo
in​: fo
out​: foo

@p5pRT
Copy link
Author

p5pRT commented Jul 22, 2005

From nospam@webdragon.net

Shiping Zhang wrote​:

The described behavior changes whether "sort @​arr" goes directly in
'for' or you assign it first to an array variable.

@​arr = ('one', 'two', 'three', 'four');
y/a-z/A-Z/ foreach sort @​arr;
print "\na​: @​arr\n"

prints "a​: ONE TWO THREE FOUR" and

@​arr = ('one', 'two', 'three', 'four');
@​s = sort @​arr;
y/a-z/A-Z/ foreach @​s;
print "\na​: @​arr\n"

prints "a​: one two three four". This has to do with copy-on-assign?

That seems like a (subtle) feature. Otherwise, it is a very old bug​:
the same behavior with 5.8.6, 5.6.1, and 5.005_03.

If it's a feature, then it's not documented at all. Larry's Perl books do not
mention it, the sort man page from perldoc does not mention it, and the manual
page from www.perl.org does not mention it. And this feature is against
intuition and I would consider it more a bug than a feature (what use it has?).
I think other people wouldn't expect @​array to be changed in the code above.
(New Perl programers may be surprised to know that foreach works on an alias,
but it's well documented (and warned) and such feature is at least useful under
some circumstances.) Conceptually, sort should return a true copy (sorted of
course) of its arguement and I think it is how people would understand it.
(How sort is implemented is a different matter. I guess sort is working on a
list of pointers to the elements of the original list and, in foreach context,
just returns a pointer to the list of pointers instead of making an anonymous
copy of the sort list.)

it's documented under perldoc perltrap as a discontinuance between perl4
and perl5 so it's been around for quite a while.

it's also documented under perldoc perlsyn​:

"If any element of LIST is an lvalue, you can modify it by modifying VAR
inside the loop. Conversely, if any element of LIST is NOT an lvalue,
any attempt to modify that element will fail. In other words, the
"foreach" loop index variable is an implicit alias for each item in the
list that you're looping over."

it's ALSO mentioned in perlfaq4​: perldoc -q "strip blank space"

@p5pRT
Copy link
Author

p5pRT commented Jul 22, 2005

From ping@micro3.es.dupont.com

By "not documented', I was refering to what is supposed to be returned by sort.
To a Perl programer, should what's returned by sort be considered a 'true' copy
of a original list (albeit sorted) which can be worked on without affecting the original list under any circumstances? As far as I see it, in the code
of 'foreach (sort @​array){}', foreach is stepping through a sorted copy
returned by sort at the time sort has already finished and @​array forgotten.
So I wouldn't expect @​array to be changed. The current behavior is a bad
behavior to say the least. I would be very surprised if Larry would design
the code to behave in such a way. ;-)

From rt-nospam=webdragon.net@​perl.org Fri Jul 22 09​:07​:30 2005
Subject​: Re​: [perl #36616] bug or feature? foreach (sort @​array) {y/a-z/A-Z/;} # @​array modified!
From​: "Scott R. Godin via RT" <perlbug-followup@​perl.org>
X-RT-Loop-Prevention​: perl
RT-Ticket​: perl #36616
Managed-by​: RT 3.0.11 (http​://www.bestpractical.com/rt/)
RT-Originator​: nospam@​webdragon.net
To​: ping@​bioservrp.es.dupont.com
X-RT-Original-Encoding​: utf-8
Date​: Fri, 22 Jul 2005 06​:05​:23 -0700
MIME-Version​: 1.0
Content-Transfer-Encoding​: 7bit

Shiping Zhang wrote​:

The described behavior changes whether "sort @​arr" goes directly in
'for' or you assign it first to an array variable.

@​arr = ('one', 'two', 'three', 'four');
y/a-z/A-Z/ foreach sort @​arr;
print "\na​: @​arr\n"

prints "a​: ONE TWO THREE FOUR" and

@​arr = ('one', 'two', 'three', 'four');
@​s = sort @​arr;
y/a-z/A-Z/ foreach @​s;
print "\na​: @​arr\n"

prints "a​: one two three four". This has to do with copy-on-assign?

That seems like a (subtle) feature. Otherwise, it is a very old bug​:
the same behavior with 5.8.6, 5.6.1, and 5.005_03.

If it's a feature, then it's not documented at all. Larry's Perl books do not
mention it, the sort man page from perldoc does not mention it, and the manual
page from www.perl.org does not mention it. And this feature is against
intuition and I would consider it more a bug than a feature (what use it has?).
I think other people wouldn't expect @​array to be changed in the code above.
(New Perl programers may be surprised to know that foreach works on an alias,
but it's well documented (and warned) and such feature is at least useful under
some circumstances.) Conceptually, sort should return a true copy (sorted of
course) of its arguement and I think it is how people would understand it.
(How sort is implemented is a different matter. I guess sort is working on a
list of pointers to the elements of the original list and, in foreach context,
just returns a pointer to the list of pointers instead of making an anonymous
copy of the sort list.)

it's documented under perldoc perltrap as a discontinuance between perl4
and perl5 so it's been around for quite a while.

it's also documented under perldoc perlsyn​:

"If any element of LIST is an lvalue, you can modify it by modifying VAR
inside the loop. Conversely, if any element of LIST is NOT an lvalue,
any attempt to modify that element will fail. In other words, the
"foreach" loop index variable is an implicit alias for each item in the
list that you're looping over."

it's ALSO mentioned in perlfaq4​: perldoc -q "strip blank space"

This communication is for use by the intended recipient and contains
information that may be privileged, confidential or copyrighted under
applicable law. If you are not the intended recipient, you are hereby
formally notified that any use, copying or distribution of this e-mail,
in whole or in part, is strictly prohibited. Please notify the sender
by return e-mail and delete this e-mail from your system. Unless
explicitly and conspicuously designated as "E-Contract Intended",
this e-mail does not constitute a contract offer, a contract amendment,
or an acceptance of a contract offer. This e-mail does not constitute
a consent to the use of sender's contact information for direct marketing
purposes or for transfers of data to third parties.

Francais Deutsch Italiano Espanol Portugues Japanese Chinese Korean

  http​://www.DuPont.com/corp/email_disclaimer.html

@p5pRT
Copy link
Author

p5pRT commented Jul 22, 2005

From ping@micro3.es.dupont.com

From rt-davem=iabyn.com@​perl.org Thu Jul 21 20​:36​:57 2005
Subject​: Re​: [perl #36616] bug or feature? foreach (sort @​array) {y/a-z/A-Z/;} # @​array modified!
From​: "Dave Mitchell via RT" <perlbug-followup@​perl.org>
RT-Ticket​: perl #36616
Managed-by​: RT 3.0.11 (http​://www.bestpractical.com/rt/)
RT-Originator​: davem@​iabyn.com
To​: ping@​bioservrp.es.dupont.com
Date​: Thu, 21 Jul 2005 13​:34​:26 -0700

[...]

I don't think its a bug so much as undocumented behaviour. "fixing" it
would involve doing a whole bunch of unneccessary copying in sort and
grep.

I think you only need to do copying at the end of sort, just treat it
like foreach (my @​anonymous = sort @​old). After all, @​new = sort @​old is
what people usually do anyway (or at least such usage should be expected
to be common practice).

This communication is for use by the intended recipient and contains
information that may be privileged, confidential or copyrighted under
applicable law. If you are not the intended recipient, you are hereby
formally notified that any use, copying or distribution of this e-mail,
in whole or in part, is strictly prohibited. Please notify the sender
by return e-mail and delete this e-mail from your system. Unless
explicitly and conspicuously designated as "E-Contract Intended",
this e-mail does not constitute a contract offer, a contract amendment,
or an acceptance of a contract offer. This e-mail does not constitute
a consent to the use of sender's contact information for direct marketing
purposes or for transfers of data to third parties.

Francais Deutsch Italiano Espanol Portugues Japanese Chinese Korean

  http​://www.DuPont.com/corp/email_disclaimer.html

@p5pRT
Copy link
Author

p5pRT commented Jul 22, 2005

From nospam@webdragon.net

Shiping Zhang wrote​:

Shiping Zhang wrote​:

The described behavior changes whether "sort @​arr" goes directly in
'for' or you assign it first to an array variable.

@​arr = ('one', 'two', 'three', 'four');
y/a-z/A-Z/ foreach sort @​arr;
print "\na​: @​arr\n"

prints "a​: ONE TWO THREE FOUR" and

@​arr = ('one', 'two', 'three', 'four');
@​s = sort @​arr;
y/a-z/A-Z/ foreach @​s;
print "\na​: @​arr\n"

prints "a​: one two three four". This has to do with copy-on-assign?

That seems like a (subtle) feature. Otherwise, it is a very old bug​:
the same behavior with 5.8.6, 5.6.1, and 5.005_03.

If it's a feature, then it's not documented at all. Larry's Perl books do not
mention it, the sort man page from perldoc does not mention it, and the manual
page from www.perl.org does not mention it. And this feature is against
intuition and I would consider it more a bug than a feature (what use it has?).
I think other people wouldn't expect @​array to be changed in the code above.
(New Perl programers may be surprised to know that foreach works on an alias,
but it's well documented (and warned) and such feature is at least useful under
some circumstances.) Conceptually, sort should return a true copy (sorted of
course) of its arguement and I think it is how people would understand it.
(How sort is implemented is a different matter. I guess sort is working on a
list of pointers to the elements of the original list and, in foreach context,
just returns a pointer to the list of pointers instead of making an anonymous
copy of the sort list.)

it's documented under perldoc perltrap as a discontinuance between perl4
and perl5 so it's been around for quite a while.

it's also documented under perldoc perlsyn​:

"If any element of LIST is an lvalue, you can modify it by modifying VAR
inside the loop. Conversely, if any element of LIST is NOT an lvalue,
any attempt to modify that element will fail. In other words, the
"foreach" loop index variable is an implicit alias for each item in the
list that you're looping over."

it's ALSO mentioned in perlfaq4​: perldoc -q "strip blank space"

By "not documented', I was refering to what is supposed to be returned by
sort. To a Perl programer, should what's returned by sort be considered a
'true' copy of a original list (albeit sorted) which can be worked on without
affecting the original list under any circumstances? As far as I see it, in
the code of 'foreach (sort @​array){}', foreach is stepping through a sorted
copy returned by sort at the time sort has already finished and @​array
forgotten. So I wouldn't expect @​array to be changed. The current behavior is
a bad behavior to say the least. I would be very surprised if Larry would
design the code to behave in such a way. ;-)

I'm not so sure about that..

sort @​a is just @​a sorted. if I wanted a sorted copy of @​a I'd do it implicitly​:
@​b = sort @​a , as in foreach (my @​b = sort @​a) {}. As someone else pointed out,
sort is similar to grep in this respect.

When I first looked at this question, I thoroughly discounted sort as being
'part of the problem', and looked straight to the aliasing behaviour of foreach,
since you're merely receiving @​a back, just sorted first.

if I wanted a copy of @​a I'd ask for it. Perhaps this needs to be documented
better in the above three perldocs but I don't see it as a bug whatsoever. It
(foreach) is doing exactly what I'd have expected of it, myself, sorted/grepped
or not...

@p5pRT
Copy link
Author

p5pRT commented Jul 24, 2005

From @schwern

So it sounds like the resolution for this bug is to document that sort
uses aliases like grep does. I've stolen the wording from grep.

--
Michael G Schwern schwern@​pobox.com http​://www.pobox.com/~schwern
Reality is that which, when you stop believing in it, doesn't go away.
  -- Phillip K. Dick

@p5pRT
Copy link
Author

p5pRT commented Jul 24, 2005

From @schwern

sort.pod.patch
--- pod/perlfunc.pod	2005/07/24 02:57:16	1.2
+++ pod/perlfunc.pod	2005/07/24 02:58:42
@@ -4926,6 +4926,12 @@
 When C<use locale> is in effect, C<sort LIST> sorts LIST according to the
 current collation locale.  See L<perllocale>.
 
+sort returns aliases into the original list, much as a for loop's
+index variable aliases the list elements.  That is, modifying an
+element of a list returned by sort (for example, in a "foreach", "map"
+or "grep") actually modifies the element in the original list.  This
+is usually something to be avoided when writing clear code.
+
 Perl 5.6 and earlier used a quicksort algorithm to implement sort.
 That algorithm was not stable, and I<could> go quadratic.  (A I<stable> sort
 preserves the input order of elements that compare equal.  Although

@p5pRT
Copy link
Author

p5pRT commented Jul 25, 2005

From ping@micro3.es.dupont.com

I agree.

From rt-schwern=pobox.com@​perl.org Mon Jul 25 08​:08​:53 2005
Subject​: Re​: [perl #36616] bug or feature? foreach (sort @​array) {y/a-z/A-Z/;} # @​array modified!
From​: "Michael G Schwern via RT" <perlbug-followup@​perl.org>
X-RT-Loop-Prevention​: perl
RT-Ticket​: perl #36616
Managed-by​: RT 3.0.11 (http​://www.bestpractical.com/rt/)
RT-Originator​: schwern@​pobox.com
To​: ping@​bioservrp.es.dupont.com
X-RT-Original-Encoding​: utf-8
Date​: Sat, 23 Jul 2005 19​:59​:43 -0700
MIME-Version​: 1.0

This is a multi-part message in MIME format...

------------=_1122173983-30846-1
Content-Type​: text/plain; charset="utf-8"
Content-Transfer-Encoding​: 7bit

So it sounds like the resolution for this bug is to document that sort
uses aliases like grep does. I've stolen the wording from grep.

--
Michael G Schwern schwern@​pobox.com http​://www.pobox.com/~schwern
Reality is that which, when you stop believing in it, doesn't go away.
-- Phillip K. Dick

------------=_1122173983-30846-1
Content-Type​: text/plain; charset="us-ascii"; name="sort.pod.patch"
Content-Transfer-Encoding​: 7bit
Content-Disposition​: inline; filename="sort.pod.patch"

--- pod/perlfunc.pod 2005/07/24 02​:57​:16 1.2
+++ pod/perlfunc.pod 2005/07/24 02​:58​:42
@​@​ -4926,6 +4926,12 @​@​
When C<use locale> is in effect, C<sort LIST> sorts LIST according to the
current collation locale. See L<perllocale>.

+sort returns aliases into the original list, much as a for loop's
+index variable aliases the list elements. That is, modifying an
+element of a list returned by sort (for example, in a "foreach", "map"
+or "grep") actually modifies the element in the original list. This
+is usually something to be avoided when writing clear code.
+
Perl 5.6 and earlier used a quicksort algorithm to implement sort.
That algorithm was not stable, and I<could> go quadratic. (A I<stable> sort
preserves the input order of elements that compare equal. Although

------------=_1122173983-30846-1--

This communication is for use by the intended recipient and contains
information that may be privileged, confidential or copyrighted under
applicable law. If you are not the intended recipient, you are hereby
formally notified that any use, copying or distribution of this e-mail,
in whole or in part, is strictly prohibited. Please notify the sender
by return e-mail and delete this e-mail from your system. Unless
explicitly and conspicuously designated as "E-Contract Intended",
this e-mail does not constitute a contract offer, a contract amendment,
or an acceptance of a contract offer. This e-mail does not constitute
a consent to the use of sender's contact information for direct marketing
purposes or for transfers of data to third parties.

Francais Deutsch Italiano Espanol Portugues Japanese Chinese Korean

  http​://www.DuPont.com/corp/email_disclaimer.html

@p5pRT
Copy link
Author

p5pRT commented Jul 25, 2005

From ping@micro3.es.dupont.com

From rt-nospam=webdragon.net@​perl.org Fri Jul 22 18​:48​:32 2005
Subject​: Re​: [perl #36616] bug or feature? foreach (sort @​array) {y/a-z/A-Z/;} # @​array modified!
From​: "Scott R. Godin via RT" <perlbug-followup@​perl.org>
X-RT-Loop-Prevention​: perl
RT-Ticket​: perl #36616
Managed-by​: RT 3.0.11 (http​://www.bestpractical.com/rt/)
RT-Originator​: nospam@​webdragon.net
To​: ping@​bioservrp.es.dupont.com
Date​: Fri, 22 Jul 2005 15​:46​:36 -0700

By "not documented', I was refering to what is supposed to be returned by
sort. To a Perl programer, should what's returned by sort be considered a
'true' copy of a original list (albeit sorted) which can be worked on without
affecting the original list under any circumstances? As far as I see it, in
the code of 'foreach (sort @​array){}', foreach is stepping through a sorted
copy returned by sort at the time sort has already finished and @​array
forgotten. So I wouldn't expect @​array to be changed. The current behavior is
a bad behavior to say the least. I would be very surprised if Larry would
design the code to behave in such a way. ;-)

I'm not so sure about that..

sort @​a is just @​a sorted. if I wanted a sorted copy of @​a I'd do it implicitly​:
@​b = sort @​a , as in foreach (my @​b = sort @​a) {}. As someone else pointed out,
sort is similar to grep in this respect.

When I first looked at this question, I thoroughly discounted sort as being
'part of the problem', and looked straight to the aliasing behaviour of foreach,
since you're merely receiving @​a back, just sorted first.

But @​a itself is not sorted, so you can't say you are receiving @​a back.

if I wanted a copy of @​a I'd ask for it. Perhaps this needs to be documented
better in the above three perldocs but I don't see it as a bug whatsoever. It
(foreach) is doing exactly what I'd have expected of it, myself, sorted/grepped
or not...

The question here is not about the behavior of foreach, but that of
sort and its documentation. The "alias nature" of foreach and grep
is documentated and such nature makes some sense​: foreach lets you
step through each element and grep lets you target certain elements
of the list, so it's not completely out of logic to return aliases
to those elements so you can easily make change to each element or
the targeted elements.

Here are some words from http​://perldoc.perl.org/functions/grep.html​:
Similarly, grep returns aliases into the original list, much as a for
loop's index variable aliases the list elements. That is, modifying
an element of a list returned by grep (for example, in a foreach , map
or another grep) actually modifies the element in the original list.
But no such words about sort. Had I seen such words about sort, I wouldn't
have brought it up (though I would still had wondered why).

This communication is for use by the intended recipient and contains
information that may be privileged, confidential or copyrighted under
applicable law. If you are not the intended recipient, you are hereby
formally notified that any use, copying or distribution of this e-mail,
in whole or in part, is strictly prohibited. Please notify the sender
by return e-mail and delete this e-mail from your system. Unless
explicitly and conspicuously designated as "E-Contract Intended",
this e-mail does not constitute a contract offer, a contract amendment,
or an acceptance of a contract offer. This e-mail does not constitute
a consent to the use of sender's contact information for direct marketing
purposes or for transfers of data to third parties.

Francais Deutsch Italiano Espanol Portugues Japanese Chinese Korean

  http​://www.DuPont.com/corp/email_disclaimer.html

@p5pRT
Copy link
Author

p5pRT commented Aug 1, 2005

From @rgs

Michael G Schwern wrote​:

So it sounds like the resolution for this bug is to document that sort
uses aliases like grep does. I've stolen the wording from grep.

Thanks, applied as change #25258.

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

1 participant