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

'x' forces scalar context on array variables #9526

Closed
p5pRT opened this issue Oct 13, 2008 · 18 comments
Closed

'x' forces scalar context on array variables #9526

p5pRT opened this issue Oct 13, 2008 · 18 comments

Comments

@p5pRT
Copy link

p5pRT commented Oct 13, 2008

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

Searchable as RT59884$

@p5pRT
Copy link
Author

p5pRT commented Oct 13, 2008

From jschneid@redhat.com

Created by jschneid@redhat.com

The 'x' operator forces scalar context on the left operand, unless
that operand is enclosed in parens, even if the left operand is an
array variable.

For example, the following code fragment prints the string "22", rather
than the expected four lines of alternating words​:

@​foo = qw(foo bar);
print "$_\n" foreach @​foo x 2;

The alternative​:

print "$_\n" foreach qw(foo bar) x 2;

does print the alternating lines.

"perldoc perlop" is not clear on the expected behavior - quoting​:

  In scalar context or if the left operand is not enclosed in parentheses,
  it returns a string consisting of the left operand repeated the number of
  times specified by the right operand. In list context, if the left operand
  is enclosed in parentheses or is a list formed by "qw/STRING/", it repeats
  the list.

It could be read that the behavior is the documented behavior, but it
certainly looks like wrong behavior. It also violates the principal of
least surprise. Why should the "x" operator force a particular context
on an operand that already has a perfectly good context of its own?

In the event this is not fixed, I suggest the passage above be amended to​:

  The "x" operator will evaluate its left operand in scalar context,
  unless the left operand is enclosed in parentheses, or is a list formed
  by "qw/STRING/", where it will be evaluated in list context. In scalar
  context, it returns a string consisting of the left operand repeated
  the number of times specified by the right operand. In list context,
  it repeats the list.

Perl Info

Flags:
    category=core
    severity=wishlist

This perlbug was built using Perl v5.8.8 in the Red Hat build system.
It is being executed now by Perl v5.8.8 - Tue Oct 23 12:21:05 EDT 2007.

Site configuration information for perl v5.8.8:

Configured by Red Hat, Inc. at Tue Oct 23 12:21:05 EDT 2007.

Summary of my perl5 (revision 5 version 8 subversion 8) configuration:
  Platform:
    osname=linux, osvers=2.6.9-55.0.9.elsmp, archname=i386-linux-thread-multi
    uname='linux hs20-bc1-6.build.redhat.com 2.6.9-55.0.9.elsmp #1 smp tue sep 25 02:16:15 edt 2007 i686 i686 i386 gnulinux '
    config_args='-des -Doptimize=-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -Dversion=5.8.8 -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=n -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r_proto -Ud_sethostent_r_proto -Ud_endprotoent_r_proto -Ud_setprotoent_r_proto -Ud_endservent_r_proto -Ud_setservent_r_proto -Dinc_version_list=5.8.7 5.8.6 5.8.5 -Dscriptdir=/usr/bin'
    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 -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
    optimize='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include -I/usr/include/gdbm'
    ccversion='', gccversion='4.1.1 20070105 (Red Hat 4.1.1-52)', 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=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
    perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=/lib/libc-2.5.so, so=so, useshrplib=true, libperl=libperl.so
    gnulibc_version='2.5'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -L/usr/local/lib'

Locally applied patches:
    


@INC for perl v5.8.8:
    /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.7/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.6/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.8
    /usr/lib/perl5/site_perl/5.8.7
    /usr/lib/perl5/site_perl/5.8.6
    /usr/lib/perl5/site_perl/5.8.5
    /usr/lib/perl5/site_perl
    /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.7/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.6/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.5/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.8
    /usr/lib/perl5/vendor_perl/5.8.7
    /usr/lib/perl5/vendor_perl/5.8.6
    /usr/lib/perl5/vendor_perl/5.8.5
    /usr/lib/perl5/vendor_perl
    /usr/lib/perl5/5.8.8/i386-linux-thread-multi
    /usr/lib/perl5/5.8.8
    .


Environment for perl v5.8.8:
    HOME=/home/jschneid
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/lib/qt-3.3/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/sbin:/home/jschneid/bin
    PERL_BADLANG (unset)
    SHELL=/bin/bash


@p5pRT
Copy link
Author

p5pRT commented Oct 14, 2008

From @schwern

James Schneider (via RT) wrote​:

The 'x' operator forces scalar context on the left operand, unless
that operand is enclosed in parens, even if the left operand is an
array variable.

For example, the following code fragment prints the string "22", rather
than the expected four lines of alternating words​:

@​foo = qw(foo bar);
print "$_\n" foreach @​foo x 2;

The alternative​:

print "$_\n" foreach qw(foo bar) x 2;

does print the alternating lines.

I think what you're seeing in the second example is a quirk of Perl's
interpretation of "enclosed in parentheses" because I believe once compiled
qw(foo bar) and ('foo', 'bar') are equivalent.

"perldoc perlop" is not clear on the expected behavior - quoting​:

In scalar context or if the left operand is not enclosed in parentheses,
it returns a string consisting of the left operand repeated the number of
times specified by the right operand. In list context, if the left operand
is enclosed in parentheses or is a list formed by "qw/STRING/", it repeats
the list.

It could be read that the behavior is the documented behavior, but it
certainly looks like wrong behavior. It also violates the principal of
least surprise. Why should the "x" operator force a particular context
on an operand that already has a perfectly good context of its own?

Because operands don't have context, only operators. That's sort of like
asking, in English class, "what context does the word 'right' have"? Words
are used in context, but they do not have an inherent context.

For example, print evaluates its arguments in list context. When you write
C<< print $foo >>, $foo is still being used by print in list context. It just
so happens to make no difference.

I suppose one could look at 'x' as being two different operators with the same
name. The 'list repeat operator' and the 'scalar repeat operator'. Just like
'@​list = qw(1 2 3)' is really using the 'list assignment operator' and
'$scalar = qw(1 2 3)' is using the 'scalar assignment operator' at which point
my statement that operands don't have context starts to break down.

You're right that C<< @​foo x 4 >> is confusing just as C<< reverse $foo >> is.
This is why the "everything is an object" approach makes more sense. C<<
@​foo.repeat(4) >> and C<< $foo.reverse >> can DWIM better in those cases where
the type of the variable, not the context in which its used, is more important.

In conclusion, the 'x' operator probably should just DWIM according to the
context in which its used just like every other operator.

  $string = @​foo x 4; # $string = join '', map { scalar @​foo } 1..4;
  @​list = @​foo x 4; # @​list = map { @​foo } 1..4;

And if you want to force an operand into scalar context, you do it
explicitly.

  @​list = scalar @​foo x 4; # @​list = map { scalar @​foo } 1..4;

But it's too late now. :(

In the event this is not fixed, I suggest the passage above be amended to​:

The "x" operator will evaluate its left operand in scalar context,
unless the left operand is enclosed in parentheses, or is a list formed
by "qw/STRING/", where it will be evaluated in list context. In scalar
context, it returns a string consisting of the left operand repeated
the number of times specified by the right operand. In list context,
it repeats the list.

Something like that, yes. I'd use the "white lie" approach, start with a
simple statement that isn't entirely true and refine, to allow a series of
simpler statements.


Binary "x" is the repetition operator. It repeats the left operand,
as a scalar, the number of times specified by the right operand.

  $line = '-' x 80; # a string of 80 dashes

If the left operand is enclosed in parenthesis (including a
qw/STRING/), and the "x" operator is used in list context, it repeats
the list.

  @​dashes = ('-') x 80; # a list of 80 dashes
  $line = ('-') x 80; # a string of 80 dashes

If the right operand is zero or negative, it returns an empty string
or empty list, depending on the context.


--
<Schwern> What we learned was if you get confused, grab someone and swing
  them around a few times
  -- Life's lessons from square dancing

@p5pRT
Copy link
Author

p5pRT commented Oct 14, 2008

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

@p5pRT
Copy link
Author

p5pRT commented Oct 14, 2008

From @ikegami

On Tue, Oct 14, 2008 at 11​:40 AM, Michael G Schwern <schwern@​pobox.com>wrote​:

If the left operand is enclosed in parenthesis (including a
qw/STRING/), and the "x" operator is used in list context, it repeats
the list.

Including qw/STRING/ enclosed in parenthesis?

If the left operand is enclosed in parenthesis or if it's a qw/STRING/,
and if the "x" operator is used in list context, it repeats the list.

@p5pRT
Copy link
Author

p5pRT commented Oct 14, 2008

From @schwern

Eric Brine wrote​:

On Tue, Oct 14, 2008 at 11​:40 AM, Michael G Schwern <schwern@​pobox.com
<mailto​:schwern@​pobox.com>> wrote​:

If the left operand is enclosed in parenthesis \(including a
qw/STRING/\)\, and the "x" operator is used in list context\, it repeats
the list\.

Including qw/STRING/ enclosed in parenthesis?

Ahh, I see the ambiguity. I want to make it clear that qw/STRING/ isn't a
special case in the "x" operator, but a special parsing case.


If the left operand is enclosed in parenthesis (qw/STRING/ is considered to be
enclosed in parenthesis), and the "x" operator is used in list context, it
repeats the list.


Speaking of weird exceptions...

$ perl -wle '@​foo = ("a".."b"); $x = @​foo x 2; print $x'
22

$ perl -wle '@​foo = ("a".."b"); $x = (@​foo) x 2; print $x'
22

$ perl -wle '$x = ("a".."b") x 2; print $x'
Argument "a" isn't numeric in range (or flip) at -e line 1.
Use of uninitialized value in range (or flip) at -e line 1.
Argument "b" isn't numeric in range (or flop) at -e line 1.
Use of uninitialized value in range (or flop) at -e line 1.
1E01E0

$ perl -wle '$x = (("a".."b") x 2); print $x'
Argument "a" isn't numeric in range (or flip) at -e line 1.
Use of uninitialized value in range (or flip) at -e line 1.
Argument "b" isn't numeric in range (or flop) at -e line 1.
Use of uninitialized value in range (or flop) at -e line 1.
1E01E0

Which seems to be a special case of..

$ perl -wle 'print scalar (1..2)'
Use of uninitialized value in range (or flip) at -e line 1.

And I'm not going to pretend I understand scalar flip/fop.

--
54. "Napalm sticks to kids" is *not* a motivational phrase.
  -- The 213 Things Skippy Is No Longer Allowed To Do In The U.S. Army
  http​://skippyslist.com/list/

@p5pRT
Copy link
Author

p5pRT commented Oct 14, 2008

From perl@nevcal.com

On approximately 10/14/2008 9​:15 AM, came the following characters from
the keyboard of Michael G Schwern​:

Eric Brine wrote​:

On Tue, Oct 14, 2008 at 11​:40 AM, Michael G Schwern <schwern@​pobox.com
<mailto​:schwern@​pobox.com>> wrote​:

If the left operand is enclosed in parenthesis \(including a
qw/STRING/\)\, and the "x" operator is used in list context\, it repeats
the list\.

Including qw/STRING/ enclosed in parenthesis?

Ahh, I see the ambiguity. I want to make it clear that qw/STRING/ isn't a
special case in the "x" operator, but a special parsing case.

-------------------------------------------------------
If the left operand is enclosed in parenthesis (qw/STRING/ is considered to be
enclosed in parenthesis), and the "x" operator is used in list context, it
repeats the list.
--------------------------------------------------------

Except for your weird exceptions below, I was about to suggest saying
"If the left operand is a list" (which covers the () syntax, the qw//
syntax, and excludes the @​foo syntax). Maybe the wording still would
cover these weird exceptions appropriately.

But the weird exceptions do point out that the wording "if the left
operand is enclosed in parenthesis" is incorrect wording.

It is certainly true that not everything in Perl that is enclosed in
parentheses is a list; suggesting that in this documentation would be
misleading. Further explaining what parenthesized items are and are not
lists, and what non-parenthesized items are and are not lists, should be
redundant with other parts of the Perl documentation that explain the
individual syntax elements.

The Perl user does need to understand the differences between arrays,
lists, and expressions, and how the context of an operator affects the
interpretation of syntax.

'x' does seem to be somewhat unique in that its own context affects the
context of its operands... can anyone give other examples of that?

Speaking of weird exceptions...

$ perl -wle '@​foo = ("a".."b"); $x = @​foo x 2; print $x'
22

$ perl -wle '@​foo = ("a".."b"); $x = (@​foo) x 2; print $x'
22

$ perl -wle '$x = ("a".."b") x 2; print $x'
Argument "a" isn't numeric in range (or flip) at -e line 1.
Use of uninitialized value in range (or flip) at -e line 1.
Argument "b" isn't numeric in range (or flop) at -e line 1.
Use of uninitialized value in range (or flop) at -e line 1.
1E01E0

$ perl -wle '$x = (("a".."b") x 2); print $x'
Argument "a" isn't numeric in range (or flip) at -e line 1.
Use of uninitialized value in range (or flip) at -e line 1.
Argument "b" isn't numeric in range (or flop) at -e line 1.
Use of uninitialized value in range (or flop) at -e line 1.
1E01E0

Which seems to be a special case of..

$ perl -wle 'print scalar (1..2)'
Use of uninitialized value in range (or flip) at -e line 1.

And I'm not going to pretend I understand scalar flip/fop.

--
Glenn -- http​://nevcal.com/

A protocol is complete when there is nothing left to remove.
-- Stuart Cheshire, Apple Computer, regarding Zero Configuration Networking

@p5pRT
Copy link
Author

p5pRT commented Oct 14, 2008

From @schwern

Glenn Linderman wrote​:

'x' does seem to be somewhat unique in that its own context affects the
context of its operands... can anyone give other examples of that?

Hmm, good point. I can't think of any offhand.

--
44. I am not the atheist chaplain.
  -- The 213 Things Skippy Is No Longer Allowed To Do In The U.S. Army
  http​://skippyslist.com/list/

@p5pRT
Copy link
Author

p5pRT commented Oct 14, 2008

From blgl@hagernas.com

In article <48F4CD2B.6050205@​NevCal.com>, perl@​NevCal.com (Glenn Linderman)
wrote​:

'x' does seem to be somewhat unique in that its own context affects the
context of its operands... can anyone give other examples of that?

Unary​: +
Binary​: && || // and or (right operand)
Ternary​: ?​: (second and third operands)

/Bo Lindbergh

@p5pRT
Copy link
Author

p5pRT commented Oct 14, 2008

From Eirik-Berg.Hanssen@allverden.no

Bo Lindbergh <blgl@​hagernas.com> writes​:

In article <48F4CD2B.6050205@​NevCal.com>, perl@​NevCal.com (Glenn Linderman)
wrote​:

'x' does seem to be somewhat unique in that its own context affects the
context of its operands... can anyone give other examples of that?

Unary​: +
Binary​: && || // and or (right operand)
Ternary​: ?​: (second and third operands)

  Also, comma. If comma in list context is considered an operator?

sub w { $w=wantarray; push @​w, $w }
@​x = (w, w); # list, list
$x = (w, w); # void, scalar
use Data​::Dumper;
print Dumper(\@​w);

__END__

$VAR1 = [
  1,
  1,
  undef,
  ''
  ];

Eirik
--
The basic facts are that the rate of decrease of the population growth
rate has been falling for decades, at an ever increasing rate.
  --jsnead@​netcom.com (John R. Snead)

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2013

From @jkeenan

On Mon Oct 13 14​:11​:35 2008, jschneid@​redhat.com wrote​:

This is a bug report for perl from jschneid@​redhat.com,

generated with the help of perlbug 1.35 running under perl v5.8.8.

-----------------------------------------------------------------
[Please enter your report here]

The 'x' operator forces scalar context on the left operand, unless
that operand is enclosed in parens, even if the left operand is an
array variable.

For example, the following code fragment prints the string "22",
rather
than the expected four lines of alternating words​:

@​foo = qw(foo bar);
print "$_\n" foreach @​foo x 2;

The alternative​:

print "$_\n" foreach qw(foo bar) x 2;

does print the alternating lines.

"perldoc perlop" is not clear on the expected behavior - quoting​:

In scalar context or if the left operand is not enclosed in
parentheses,
it returns a string consisting of the left operand repeated the
number of
times specified by the right operand. In list context, if the left
operand
is enclosed in parentheses or is a list formed by "qw/STRING/", it
repeats
the list.

It could be read that the behavior is the documented behavior, but it
certainly looks like wrong behavior. It also violates the principal
of
least surprise. Why should the "x" operator force a particular
context
on an operand that already has a perfectly good context of its own?

In the event this is not fixed, I suggest the passage above be amended
to​:

The "x" operator will evaluate its left operand in scalar context,
unless the left operand is enclosed in parentheses, or is a list
formed
by "qw/STRING/", where it will be evaluated in list context. In
scalar
context, it returns a string consisting of the left operand repeated
the number of times specified by the right operand. In list
context,
it repeats the list.

I reviewed this older ticket this evening. The OP was concerned about
two different instances of the 'x' binary repetition operator. In the
first case, everything DWIMs​:

#####
$ perl -E '@​foo = qw(foo bar);say $_ for (@​foo) x 2;'
foo
bar
foo
bar
#####

Drop the parentheses around the '@​foo' and you get the second case​:

#####
$ perl -E '@​foo = qw(foo bar);say $_ for @​foo x 2;'
22
#####

... which the OP felt violated the principle of least surprise, even if
it technically satisfied the documentation for the 'x' operator in
'perlop'. In blead, that documentation reads​:

#####
Binary "x" is the repetition operator. In scalar context or if the left
operand is not enclosed in parentheses, it returns a string consisting
of the left operand repeated the number of times specified by the right
operand. In list context, if the left operand is enclosed in
parentheses or is a list formed by C<qw/STRING/>, it repeats the list.
If the right operand is zero or negative, it returns an empty string
or an empty list, depending on the context.
#####

I am attaching a patch in the same spirit as a revision suggested by the
original poster. Please review.

Thank you very much.
Jim Keenan

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2013

From @jkeenan

0001-Clarify-case-of-x-operator-with-left-operand-lacking.patch
From bbd88daf10e3c66a615601e34a020bd10361b08c Mon Sep 17 00:00:00 2001
From: James E Keenan <jkeenan@cpan.org>
Date: Mon, 18 Feb 2013 21:51:19 -0500
Subject: [PATCH] Clarify case of "x" operator with left operand lacking parens.

Modification of documentation change suggested by James Schneider.

For: RT #59884.
---
 pod/perlop.pod |   33 +++++++++++++++++++--------------
 1 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/pod/perlop.pod b/pod/perlop.pod
index 40402be..c1b1944 100644
--- a/pod/perlop.pod
+++ b/pod/perlop.pod
@@ -297,22 +297,27 @@ operator is not as well defined for negative operands, but it will
 execute faster.
 X<%> X<remainder> X<modulo> X<mod>
 
-Binary "x" is the repetition operator.  In scalar context or if the left
-operand is not enclosed in parentheses, it returns a string consisting
-of the left operand repeated the number of times specified by the right
-operand.  In list context, if the left operand is enclosed in
-parentheses or is a list formed by C<qw/STRING/>, it repeats the list.
-If the right operand is zero or negative, it returns an empty string
-or an empty list, depending on the context.
+Binary "x" is the repetition operator.  It will evaluate its left
+operand in scalar context unless (a) the left operand is enclosed in
+parentheses or (b) is a list formed by C<qw/STRING/> -- in which case it
+will evaluate its left operand in list context.  In scalar context, it
+returns a string consisting of the left operand repeated the number of
+times specified by the right operand. In list context, it repeats the
+list.
 X<x>
 
-    print '-' x 80;		# print row of dashes
-
-    print "\t" x ($tab/8), ' ' x ($tab%8);	# tab over
-
-    @ones = (1) x 80;		# a list of 80 1's
-    @ones = (5) x @ones;	# set all elements to 5
-
+    print '-' x 80;                 # print row of dashes
+    print "\t" x ($tab/8),
+      ' ' x ($tab%8);               # tab over
+    
+    @terms = ('foo', 'bar');
+    print "$_\n" for @terms x 2;    # prints "22\n"; lack of parens
+                                    # on left operand causes @terms
+                                    # to be evaluated in scalar context
+
+    @ones = (1) x 80;               # a list of 80 1's
+    @ones = (5) x @ones;            # set all elements to 5
+    @terms = qw/foo bar/ x 2;       # ('foo', 'bar', 'foo', 'bar')
 
 =head2 Additive Operators
 X<operator, additive>
-- 
1.6.3.2

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2013

From @tamias

On Mon, Feb 18, 2013 at 06​:55​:34PM -0800, James E Keenan via RT wrote​:

-Binary "x" is the repetition operator. In scalar context or if the left
-operand is not enclosed in parentheses, it returns a string consisting
-of the left operand repeated the number of times specified by the right
-operand. In list context, if the left operand is enclosed in
-parentheses or is a list formed by C<qw/STRING/>, it repeats the list.
-If the right operand is zero or negative, it returns an empty string
-or an empty list, depending on the context.
+Binary "x" is the repetition operator. It will evaluate its left
+operand in scalar context unless (a) the left operand is enclosed in
+parentheses or (b) is a list formed by C<qw/STRING/> -- in which case it
+will evaluate its left operand in list context. In scalar context, it
+returns a string consisting of the left operand repeated the number of
+times specified by the right operand. In list context, it repeats the
+list.

The original text is precise and correct, while the proposed text conflates
the context of the operator with the context of the left operand.

If the 'x' operator is in scalar context, then the left operand is
evaluated in scalar context and the result is a string.

If the 'x' operator is in list context *and* the left operand is enclosed
in parentheses or is a qw// list, then the left operand is evaluated in
list context and the result is a list.

Ronald

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2013

From tchrist@perl.com

"James E Keenan via RT" <perlbug-followup@​perl.org> wrote
  on Mon, 18 Feb 2013 18​:55​:34 PST​:

I reviewed this older ticket this evening. The OP was concerned about
two different instances of the 'x' binary repetition operator. In the
first case, everything DWIMs​:

#####
$ perl -E '@​foo = qw(foo bar);say $_ for (@​foo) x 2;'
foo
bar
foo
bar
#####

Drop the parentheses around the '@​foo' and you get the second case​:

#####
$ perl -E '@​foo = qw(foo bar);say $_ for @​foo x 2;'
22
#####

... which the OP felt violated the principle of least surprise, even if
it technically satisfied the documentation for the 'x' operator in
'perlop'. In blead, that documentation reads​:

#####
Binary "x" is the repetition operator. In scalar context or if the left
operand is not enclosed in parentheses, it returns a string consisting
of the left operand repeated the number of times specified by the right
operand. In list context, if the left operand is enclosed in
parentheses or is a list formed by C<qw/STRING/>, it repeats the list.
If the right operand is zero or negative, it returns an empty string
or an empty list, depending on the context.
#####

I am attaching a patch in the same spirit as a revision suggested by the
original poster. Please review.

The doc patch looks good. Thanks.

I agree with the original submitter that this is all somewhat bizarre, but
it exists for historical reasons. The weirdness was originally introduced
so as not to break existing code. It persists now, rather more than twenty
years later, for the same reason, but this time the amount of code out
there is surely many orders of magnitude greater.

I doubt if we had it to do over again, we would do it this way.

--tom

@p5pRT
Copy link
Author

p5pRT commented Mar 13, 2013

From @jkeenan

On Mon Feb 18 19​:43​:03 2013, tom christiansen wrote​:

"James E Keenan via RT" <perlbug-followup@​perl.org> wrote
on Mon, 18 Feb 2013 18​:55​:34 PST​:

I reviewed this older ticket this evening. The OP was concerned about
two different instances of the 'x' binary repetition operator. In the
first case, everything DWIMs​:

#####
$ perl -E '@​foo = qw(foo bar);say $_ for (@​foo) x 2;'
foo
bar
foo
bar
#####

Drop the parentheses around the '@​foo' and you get the second case​:

#####
$ perl -E '@​foo = qw(foo bar);say $_ for @​foo x 2;'
22
#####

... which the OP felt violated the principle of least surprise, even if
it technically satisfied the documentation for the 'x' operator in
'perlop'. In blead, that documentation reads​:

#####
Binary "x" is the repetition operator. In scalar context or if the left
operand is not enclosed in parentheses, it returns a string consisting
of the left operand repeated the number of times specified by the right
operand. In list context, if the left operand is enclosed in
parentheses or is a list formed by C<qw/STRING/>, it repeats the list.
If the right operand is zero or negative, it returns an empty string
or an empty list, depending on the context.
#####

I am attaching a patch in the same spirit as a revision suggested by the
original poster. Please review.

The doc patch looks good. Thanks.

We had one vote for the patch (tomc) and one against (ronald). Hence, I
held off on applying it. Anyone else want to sound off?

Thank you very much.
Jim Keenan

@p5pRT
Copy link
Author

p5pRT commented Mar 13, 2013

From @bulk88

On Tue Mar 12 18​:21​:40 2013, jkeenan wrote​:

On Mon Feb 18 19​:43​:03 2013, tom christiansen wrote​:

"James E Keenan via RT" <perlbug-followup@​perl.org> wrote
on Mon, 18 Feb 2013 18​:55​:34 PST​:

I reviewed this older ticket this evening. The OP was concerned about
two different instances of the 'x' binary repetition operator. In the
first case, everything DWIMs​:

#####
$ perl -E '@​foo = qw(foo bar);say $_ for (@​foo) x 2;'
foo
bar
foo
bar
#####

Drop the parentheses around the '@​foo' and you get the second case​:

#####
$ perl -E '@​foo = qw(foo bar);say $_ for @​foo x 2;'
22
#####

... which the OP felt violated the principle of least surprise,
even if
it technically satisfied the documentation for the 'x' operator in
'perlop'. In blead, that documentation reads​:

#####
Binary "x" is the repetition operator. In scalar context or if
the left
operand is not enclosed in parentheses, it returns a string consisting
of the left operand repeated the number of times specified by the
right
operand. In list context, if the left operand is enclosed in
parentheses or is a list formed by C<qw/STRING/>, it repeats the list.
If the right operand is zero or negative, it returns an empty string
or an empty list, depending on the context.
#####

I am attaching a patch in the same spirit as a revision suggested
by the
original poster. Please review.

The doc patch looks good. Thanks.

We had one vote for the patch (tomc) and one against (ronald). Hence, I
held off on applying it. Anyone else want to sound off?

Thank you very much.
Jim Keenan

I like the current blead wording more.
--
bulk88 ~ bulk88 at hotmail.com

@p5pRT
Copy link
Author

p5pRT commented Mar 13, 2013

From @rjbs

* James E Keenan via RT <perlbug-followup@​perl.org> [2013-03-12T21​:21​:40]

We had one vote for the patch (tomc) and one against (ronald). Hence, I
held off on applying it. Anyone else want to sound off?

I agree with Ronald's criticism.

--
rjbs

@p5pRT
Copy link
Author

p5pRT commented Mar 22, 2013

From @jkeenan

On Wed Mar 13 06​:23​:09 2013, perl.p5p@​rjbs.manxome.org wrote​:

* James E Keenan via RT <perlbug-followup@​perl.org> [2013-03-12T21​:21​:40]

We had one vote for the patch (tomc) and one against (ronald). Hence, I
held off on applying it. Anyone else want to sound off?

I agree with Ronald's criticism.

Marking as rejected. Thank you very much.

Jim Keenan

@p5pRT
Copy link
Author

p5pRT commented Mar 22, 2013

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

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