Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.85k stars 527 forks source link

qw and x operators doesn't mix #7919

Closed p5pRT closed 18 years ago

p5pRT commented 19 years ago

Migrated from rt.perl.org#35885 (status was 'resolved')

Searchable as RT35885$

p5pRT commented 19 years ago

From @salva

Created by @salva

for instance

  $ perl -e 'print qw|foo bar| x 3'   Number found where operator expected at -e line 1\, near "x 3"   (Do you need to predeclare x?)   syntax error at -e line 1\, near "qw|foo bar| x "   Execution of -e aborted due to compilation errors.

while

  $ perl -e '$\,="-"; print ((qw|foo bar|) x 3)'   foo-bar-foo-bar-foo-bar

produces the desired behaviour

Cheers

  - Salvador.

Perl Info ``` Flags: category=core severity=wishlist Site configuration information for perl v5.8.4: Configured by Debian Project at Tue Mar 8 20:31:23 EST 2005. Summary of my perl5 (revision 5 version 8 subversion 4) configuration: Platform: osname=linux, osvers=2.4.27-ti1211, archname=i386-linux-thread-multi uname='linux kosh 2.4.27-ti1211 #1 sun sep 19 18:17:45 est 2004 i686 gnulinux ' config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i386-linux -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.4 -Dsitearch=/usr/local/lib/perl/5.8.4 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.4 -Dd_dosuid -des' 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='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2', cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include' ccversion='', gccversion='3.3.5 (Debian 1:3.3.5-9)', 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='cc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt perllibs=-ldl -lm -lpthread -lc -lcrypt libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libperl.so.5.8.4 gnulibc_version='2.3.2' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' Locally applied patches: @INC for perl v5.8.4: /etc/perl /usr/local/lib/perl/5.8.4 /usr/local/share/perl/5.8.4 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.8 /usr/share/perl/5.8 /usr/local/lib/site_perl . Environment for perl v5.8.4: HOME=/home/salva LANG (unset) LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=~/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games PERL_BADLANG (unset) SHELL=/bin/bash ```
p5pRT commented 19 years ago

From @salva

Created by @salva

for instance​:

  $ perl -e '@​foo = qw(foo bar) x 3'   Number found where operator expected at -e line 1\, near "x 3"   (Do you need to predeclare x?)   syntax error at -e line 1\, near "qw(foo bar) x "   Execution of -e aborted due to compilation errors.

I would expect 'qw(foo bar) x 3' to behave as '(qw(foo bar)) x 3'

Cheers\,

  - Salvador.

Perl Info ``` Flags: category=core severity=wishlist Site configuration information for perl v5.8.4: Configured by Debian Project at Tue Mar 8 20:31:23 EST 2005. Summary of my perl5 (revision 5 version 8 subversion 4) configuration: Platform: osname=linux, osvers=2.4.27-ti1211, archname=i386-linux-thread-multi uname='linux kosh 2.4.27-ti1211 #1 sun sep 19 18:17:45 est 2004 i686 gnulinux ' config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i386-linux -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.4 -Dsitearch=/usr/local/lib/perl/5.8.4 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.4 -Dd_dosuid -des' 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='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2', cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include' ccversion='', gccversion='3.3.5 (Debian 1:3.3.5-9)', 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='cc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt perllibs=-ldl -lm -lpthread -lc -lcrypt libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libperl.so.5.8.4 gnulibc_version='2.3.2' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' Locally applied patches: @INC for perl v5.8.4: /etc/perl /usr/local/lib/perl/5.8.4 /usr/local/share/perl/5.8.4 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.8 /usr/share/perl/5.8 /usr/local/lib/site_perl . Environment for perl v5.8.4: HOME=/home/salva LANG (unset) LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=~/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games PERL_BADLANG (unset) SHELL=/bin/bash __________________________________ Yahoo! Mail Mobile Take Yahoo! Mail with you! Check email on your mobile phone. http://mobile.yahoo.com/learn/mail ```
p5pRT commented 19 years ago

From @ysth

On Thu\, May 19\, 2005 at 04​:12​:45PM -0000\, Salvador Fandiño wrote​:

for instance​:

$ perl -e '@​foo = qw(foo bar) x 3' Number found where operator expected at -e line 1\, near "x 3" (Do you need to predeclare x?) syntax error at -e line 1\, near "qw(foo bar) x " Execution of -e aborted due to compilation errors.

I would expect 'qw(foo bar) x 3' to behave as '(qw(foo bar)) x 3'

perlop says​:

  In list context\, if the left operand is enclosed in   parentheses\, it repeats the list.

I would rather not add qw to that as an additional special case; instead qw(foo bar) x 3 should behave as scalar(qw(foo bar)) x 3\, generating a single string "barbarbar" (and a warning "Useless use of a constant in void context").

To get qw/foo bar foo bar foo bar/\, just enclose the qw// in parentheses​: (qw/foo bar/ x 3).

p5pRT commented 19 years ago

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

p5pRT commented 19 years ago

From @salva

--- Yitzchak Scott-Thoennes via RT \perlbug\-followup@​perl\.org wrote​:

To get qw/foo bar foo bar foo bar/\, just enclose the qw// in parentheses​: (qw/foo bar/ x 3).

that doesn't work either\, did you meant...

  (qw/foo bar/) x 3

?

cheers\,

  - Salvador

 
__________________________________ Yahoo! Mail Mobile Take Yahoo! Mail with you! Check email on your mobile phone. http​://mobile.yahoo.com/learn/mail

p5pRT commented 19 years ago

From @ysth

On Thu\, May 19\, 2005 at 11​:13​:44PM -0700\, Salvador Fandiño wrote​:

--- Yitzchak Scott-Thoennes wrote​:

To get qw/foo bar foo bar foo bar/\, just enclose the qw// in parentheses​: (qw/foo bar/ x 3).

that doesn't work either\, did you meant...

(qw/foo bar/) x 3

Oops. Yes.

p5pRT commented 19 years ago

From @rgs

Yitzchak Scott-Thoennes wrote​:

On Thu\, May 19\, 2005 at 04​:12​:45PM -0000\, Salvador Fandiño wrote​:

for instance​:

$ perl -e '@​foo = qw(foo bar) x 3' Number found where operator expected at -e line 1\, near "x 3" (Do you need to predeclare x?) syntax error at -e line 1\, near "qw(foo bar) x " Execution of -e aborted due to compilation errors.

I would expect 'qw(foo bar) x 3' to behave as '(qw(foo bar)) x 3'

perlop says​:

In list context\, if the left operand is enclosed in parentheses\, it repeats the list.

I would rather not add qw to that as an additional special case; instead qw(foo bar) x 3 should behave as scalar(qw(foo bar)) x 3\, generating a single string "barbarbar" (and a warning "Useless use of a constant in void context").

There's indeed a bug\, since the tokenizer doesn't set its state after parsing qw/..../. Fixed by this nit :

--- toke.c (revision 4822) +++ toke.c (working copy) @​@​ -4956\,6 +4956\,7 @​@​   s = scan_str(s\,FALSE\,FALSE);   if (!s)   missingterm((char*)0); + PL_expect = XOPERATOR;   force_next(')');   if (SvCUR(PL_lex_stuff)) {   OP *words = Nullop; End

But... technically I agree with Yitzchak on the exegesis of perlop\, qw() has a strong "list" feeling. Moreover\, perl 6 seems to agree :

$ ./pugs -e 'say for qw(foo bar) xx 2' foo bar foo bar

(asking on #perl6 confirms this.) And Perl 5 hasn't a strong history of not introducing special parsing cases. So I'll think I'll made it work like this :

$ bleadperl -le 'print for qw(foo bar) x 2' foo bar foo bar

p5pRT commented 19 years ago

From @ysth

On Fri\, May 20\, 2005 at 11​:07​:25AM +0200\, Rafael Garcia-Suarez wrote​:

Yitzchak Scott-Thoennes wrote​:

On Thu\, May 19\, 2005 at 04​:12​:45PM -0000\, Salvador Fandi??o wrote​:

for instance​:

$ perl -e '@​foo = qw(foo bar) x 3' Number found where operator expected at -e line 1\, near "x 3" (Do you need to predeclare x?) syntax error at -e line 1\, near "qw(foo bar) x " Execution of -e aborted due to compilation errors.

I would expect 'qw(foo bar) x 3' to behave as '(qw(foo bar)) x 3'

perlop says​:

In list context\, if the left operand is enclosed in parentheses\, it repeats the list.

I would rather not add qw to that as an additional special case; instead qw(foo bar) x 3 should behave as scalar(qw(foo bar)) x 3\, generating a single string "barbarbar" (and a warning "Useless use of a constant in void context").

There's indeed a bug\, since the tokenizer doesn't set its state after parsing qw/..../. Fixed by this nit :

--- toke.c (revision 4822) +++ toke.c (working copy) @​@​ -4956\,6 +4956\,7 @​@​ s = scan_str(s\,FALSE\,FALSE); if (!s) missingterm((char*)0); + PL_expect = XOPERATOR; force_next(')'); if (SvCUR(PL_lex_stuff)) { OP *words = Nullop; End

But... technically I agree with Yitzchak on the exegesis of perlop\, qw() has a strong "list" feeling. Moreover\, perl 6 seems to agree :

$ ./pugs -e 'say for qw(foo bar) xx 2' foo bar foo bar

(asking on #perl6 confirms this.) And Perl 5 hasn't a strong history of not introducing special parsing cases. So I'll think I'll made it work like this :

$ bleadperl -le 'print for qw(foo bar) x 2' foo bar foo bar

That's the opposite of what I was trying to say. I think of ()x and x as being two separate operators\, that happen to behave the same in scalar context. I don't think the list form should apply if there aren't explict parens around the left operand.

p5pRT commented 19 years ago

From @rgs

Yitzchak Scott-Thoennes wrote​:

$ bleadperl -le 'print for qw(foo bar) x 2' foo bar foo bar

That's the opposite of what I was trying to say.

Yes\, I'm quite aware of this :) A "nonetheless" is missing in my previous mail.

I think of ()x and x as being two separate operators\, that happen to behave the same in scalar context. I don't think the list form should apply if there aren't explict parens around the left operand.

Yes... but from a DWIM point of view I think that people are used to assume () around qw lists; or to see qw just as another form of lists. And (qw(foo bar)) is just clutter\, since qw(foo bar) x 3 is not going to be used usefully.

Perl 6 works around this difficulty by having separate x and xx operators.

p5pRT commented 19 years ago

From @ysth

On Fri\, May 20\, 2005 at 11​:07​:25AM +0200\, Rafael Garcia-Suarez wrote​:

qw() has a strong "list" feeling. Moreover\, perl 6 seems to agree :

$ ./pugs -e 'say for qw(foo bar) xx 2' foo bar foo bar

Is p6's xx supposed to have both roles of p5's x?

It sure seems to work differently; I'm told that this​:

./pugs -e 'sub foo { ("foo"\,"bar") } say for foo() xx 2'

produces foo bar foo bar

also\, while for perl5\, we have​:

$ ./perl -le'sub foo { ("foo"\,"bar") } print for foo() x 2' barbar

p5pRT commented 19 years ago

From @demerphq

On 5/20/05\, Rafael Garcia-Suarez \rgarciasuarez@​mandriva\.com wrote​:

Yitzchak Scott-Thoennes wrote​:

$ bleadperl -le 'print for qw(foo bar) x 2' foo bar foo bar

That's the opposite of what I was trying to say.

Yes\, I'm quite aware of this :) A "nonetheless" is missing in my previous mail.

I think of ()x and x as being two separate operators\, that happen to behave the same in scalar context. I don't think the list form should apply if there aren't explict parens around the left operand.

Yes... but from a DWIM point of view I think that people are used to assume () around qw lists; or to see qw just as another form of lists. And (qw(foo bar)) is just clutter\, since qw(foo bar) x 3 is not going to be used usefully.

theres precedence for this interpretation as well​:

D​:\dev>perl -wle "use strict; for my $x qw(foo bar baz) { print $x }" foo bar baz

-- perl -Mre=debug -e "/just|another|perl|hacker/"

p5pRT commented 19 years ago

From @rgs

Yitzchak Scott-Thoennes wrote​:

On Fri\, May 20\, 2005 at 11​:07​:25AM +0200\, Rafael Garcia-Suarez wrote​:

qw() has a strong "list" feeling. Moreover\, perl 6 seems to agree :

$ ./pugs -e 'say for qw(foo bar) xx 2' foo bar foo bar

Is p6's xx supposed to have both roles of p5's x?

No; as Synopsis 03 says :

  x splits into two operators​: x (which concatenates repetitions of a   string to produce a single string)\, and xx (which creates a list of   repetitions of a list or scalar).

It sure seems to work differently; I'm told that this​:

./pugs -e 'sub foo { ("foo"\,"bar") } say for foo() xx 2'

produces foo bar foo bar

also\, while for perl5\, we have​:

$ ./perl -le'sub foo { ("foo"\,"bar") } print for foo() x 2' barbar

I don't see the point... My point was that qw() forces immediate list context on x; not that it forces list context on function return. (i.e. that qw(foo bar) is more like ("foo"\,"bar") than like "foo"\,"bar".)

p5pRT commented 18 years ago

From @rgs

Rafael Garcia-Suarez wrote​:

There's indeed a bug\, since the tokenizer doesn't set its state after parsing qw/..../. Fixed by this nit :

--- toke.c (revision 4822) +++ toke.c (working copy) @​@​ -4956\,6 +4956\,7 @​@​ s = scan_str(s\,FALSE\,FALSE); if (!s) missingterm((char*)0); + PL_expect = XOPERATOR; force_next(')'); if (SvCUR(PL_lex_stuff)) { OP *words = Nullop; End

I applied this as change 24560 to bleadperl\, with a regression test that says :

is( (join '\,'\, (qw(a b c) x 3))\, 'a\,b\,c\,a\,b\,c\,a\,b\,c'\, 'x on qw produces list' );

-- The universe (which others call the Library) is composed of an indefinite and perhaps infinite number of hexagonal galleries.   -- Borges

p5pRT commented 18 years ago

@rgs - Status changed from 'open' to 'resolved'

p5pRT commented 18 years ago

From @ysth

On Tue\, May 24\, 2005 at 01​:51​:52PM +0200\, Rafael Garcia-Suarez wrote​:

Rafael Garcia-Suarez wrote​:

There's indeed a bug\, since the tokenizer doesn't set its state after parsing qw/..../. Fixed by this nit :

--- toke.c (revision 4822) +++ toke.c (working copy) @​@​ -4956\,6 +4956\,7 @​@​ s = scan_str(s\,FALSE\,FALSE); if (!s) missingterm((char*)0); + PL_expect = XOPERATOR; force_next(')'); if (SvCUR(PL_lex_stuff)) { OP *words = Nullop; End

I applied this as change 24560 to bleadperl\, with a regression test that says :

is( (join '\,'\, (qw(a b c) x 3))\, 'a\,b\,c\,a\,b\,c\,a\,b\,c'\, 'x on qw produces list' );

Inline Patch ```diff --- perl/pod/perlop.pod.orig 2005-05-10 08:07:42.000000000 -0700 +++ perl/pod/perlop.pod 2005-05-24 08:50:05.524456000 -0700 @@ -250,9 +250,9 @@ 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, 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. +parentheses or is a list formed by C, 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. print '-' x 80; # print row of dashes End of Patch. ```
p5pRT commented 18 years ago

From @rgs

Yitzchak Scott-Thoennes wrote​:

I applied this as change 24560 to bleadperl\, with a regression test that says :

is( (join '\,'\, (qw(a b c) x 3))\, 'a\,b\,c\,a\,b\,c\,a\,b\,c'\, 'x on qw produces list' );

--- perl/pod/perlop.pod.orig 2005-05-10 08​:07​:42.000000000 -0700 +++ perl/pod/perlop.pod 2005-05-24 08​:50​:05.524456000 -0700 @​@​ -250\,9 +250\,9 @​@​ 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\, 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. +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.

Right; thanks\, applied as change #24567.