Perl / perl5

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

"chomp @a = <STDIN>" not an error? #5589

Closed p5pRT closed 19 years ago

p5pRT commented 22 years ago

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

Searchable as RT9734$

p5pRT commented 22 years ago

From @RandalSchwartz

OK\, I'm puzzled.

  chomp $a = \;

rightfully aborts as a syntax error. But

  chomp @​a = \;

doesn't\, and does something odd (nothing is in @​a\, and \ is read in scalar context). Shouldn't this be a syntax error?

Even in nearly-bleed-perl\, it deparses as​:

  merlyn% perl -MO=Deparse\,-p -e 'chomp @​a = \'   (chomp(@​a) = \);   -e syntax OK   merlyn%

which still looks like bad syntax to me.

(Found by one of my students\, who didn't know better. :)

-- Randal L. Schwartz - Stonehenge Consulting Services\, Inc. - +1 503 777 0095 \merlyn@&#8203;stonehenge\.com \<URL​:http​://www.stonehenge.com/merlyn/> Perl/Unix/security consulting\, Technical writing\, Comedy\, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!

p5pRT commented 22 years ago

From @lizmat

At 01​:38 PM 6/19/02 -0700\, Randal L. Schwartz wrote​:

OK\, I'm puzzled.

chomp $a = \;

rightfully aborts as a syntax error. But

chomp @​a = \;

doesn't\, and does something odd (nothing is in @​a\, and \ is read in scalar context). Shouldn't this be a syntax error?

Even in nearly-bleed-perl\, it deparses as​:

merlyn% perl \-MO=Deparse\,\-p \-e 'chomp @&#8203;a = \<STDIN>'
\(chomp\(@&#8203;a\) = \<STDIN>\);
\-e syntax OK
merlyn%

which still looks like bad syntax to me.

(Found by one of my students\, who didn't know better. :)

According to perlfunc​:

========================================================================= Any function in the list below may be used either with or without parentheses around its arguments.

and chomp _does_ occur in that list. And from the docco of chomp()​:

========================================================================= You can actually chomp anything that's an lvalue\, including an assignment​:   chomp($cwd = `pwd`);   chomp($answer = \); If you chomp a list\, each element is chomped\, and the total number of characters removed is returned.

which would lead me to conclude that either both should be legal\, or the documentation should be changed.

Liz

p5pRT commented 22 years ago

From [Unknown Contact. See original ticket]

----- Original Message ----- From​: "Elizabeth Mattijsen" \liz@&#8203;dijkmat\.nl To​: "Randal L. Schwartz" \merlyn@&#8203;stonehenge\.com; \perl5\-porters@&#8203;perl\.org Sent​: Sunday\, June 23\, 2002 5​:43 PM Subject​: Re​: [ID 20020623.015] "chomp @​a = \" not an error?

At 01​:38 PM 6/19/02 -0700\, Randal L. Schwartz wrote​:

You can actually chomp anything that's an lvalue\, including an assignment​: chomp($cwd = `pwd`); chomp($answer = \); If you chomp a list\, each element is chomped\, and the total number of characters removed is returned.

which would lead me to conclude that either both should be legal\, or the documentation should be changed.

Yes\, but chomp binds tighter than assignment\, as the Deparse output indicates\, so you're trying to assign to the non-lvalue return of chomp. Thus the parentheses in the example.

Benjamin Holzman

p5pRT commented 22 years ago

From @RandalSchwartz

"You" == \bholzman@&#8203;earthlink\.net writes​:

At 01​:38 PM 6/19/02 -0700\, Randal L. Schwartz wrote​:

You can actually chomp anything that's an lvalue\, including an assignment​: chomp($cwd = `pwd`); chomp($answer = \); If you chomp a list\, each element is chomped\, and the total number of characters removed is returned.

which would lead me to conclude that either both should be legal\, or the documentation should be changed.

You> Yes\, but chomp binds tighter than assignment\, as the Deparse output You> indicates\, so you're trying to assign to the non-lvalue return of chomp. You> Thus the parentheses in the example.

Right\, so

  chomp $foo = \

is clearly illegal\, because it wants to be parsed as​:

  (chomp $foo) = \

My ponderance is why

  chomp @​foo = \

is not also parsed identically\, as the illegal​:

  (chomp @​foo) = \

The relative precedence of chomp() and "=" doesn't change\, so the parsing is wrong. Or something. I just don't get it.

-- Randal L. Schwartz - Stonehenge Consulting Services\, Inc. - +1 503 777 0095 \merlyn@&#8203;stonehenge\.com \<URL​:http​://www.stonehenge.com/merlyn/> Perl/Unix/security consulting\, Technical writing\, Comedy\, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!

p5pRT commented 22 years ago

From [Unknown Contact. See original ticket]

----- Original Message ----- From​: "Randal L. Schwartz" \merlyn@&#8203;stonehenge\.com To​: \bholzman@&#8203;earthlink\.net Cc​: \perl5\-porters@&#8203;perl\.org; "Elizabeth Mattijsen" \liz@&#8203;dijkmat\.nl Sent​: Monday\, June 24\, 2002 7​:48 PM Subject​: Re​: [ID 20020623.015] "chomp @​a = \" not an error?

Right\, so

    chomp $foo = \<BAR>

is clearly illegal\, because it wants to be parsed as​:

    \(chomp $foo\) = \<BAR>

My ponderance is why

    chomp @&#8203;foo = \<BAR>

is not also parsed identically\, as the illegal​:

    \(chomp @&#8203;foo\) = \<BAR>

The relative precedence of chomp() and "=" doesn't change\, so the parsing is wrong. Or something. I just don't get it.

Oh yeah\, I totally agree that it should be a syntax error.

p5pRT commented 22 years ago

From @pjscott

At 04​:48 PM 6/24/02 -0700\, Randal L. Schwartz wrote​:

Right\, so

    chomp $foo = \<BAR>

is clearly illegal\, because it wants to be parsed as​:

    \(chomp $foo\) = \<BAR>

My ponderance is why

    chomp @&#8203;foo = \<BAR>

is not also parsed identically\, as the illegal​:

    \(chomp @&#8203;foo\) = \<BAR>

The relative precedence of chomp() and "=" doesn't change\, so the parsing is wrong. Or something. I just don't get it.

Perl parses scalar chomps and list chomps as different operators (the former is called schomp).

% perl -e 'chomp($a) = 42' Can't modify scalar chomp in scalar assignment at -e line 1\, at EOF Execution of -e aborted due to compilation errors. % perl -e 'chomp(@​a) = 42' %

I spent a fair bit of time digging around op.c\, toke.c and opcode.pl trying to figure out what schomp does that chomp doesn't (or vice versa). All I can tell is that during the OP_SASSIGN\, there's no case statement in Perl_mod() in op.c for OP_SCHOMP\, so it ends up in the default block\, which triggers the error. But there is a case statement for OP_CHOMP\, and that ends up getting called and has no objection.

Maybe adding something like

@​@​ -1613\,6 +1613\,8 @​@​   case OP_NEXTSTATE​:   case OP_DBSTATE​:   case OP_CHOMP​: + if (type == OP_SASSIGN) + goto nomod;   PL_modcount = RETURN_UNLIMITED_NUMBER;   break;   case OP_RV2SV​:

? But this seems kludgey.

-- Peter Scott Pacific Systems Design Technologies

p5pRT commented 22 years ago

From @tamias

On Tue\, Jun 25\, 2002 at 11​:44​:29AM +0200\, Elizabeth Mattijsen wrote​:

--- perlfunc.pod.original Fri Jun 21 19​:38​:36 2002 +++ perlfunc.pod Tue Jun 25 11​:43​:19 2002 @​@​ -621\,7 +621\,7 @​@​

=item chomp VARIABLE

-=item chomp( LIST ) +=item chomp( LIST ) # note parentheses here

=item chomp

@​@​ -644\,30 +644\,39 @​@​ }

If VARIABLE is a hash\, it chomps the hash's values\, but not its keys. +If VARIABLE is an array\, each element is chomped. In both cases the total +number of characters removed is returned.

You can actually chomp anything that's an lvalue\, including an assignment​:

 chomp\($cwd = \`pwd\`\);
 chomp\($answer = \<STDIN>\);

-If you chomp a list\, each element is chomped\, and the total number of -characters removed is returned.

Should we still explicitly document the behavior when chomping a list\, as distinct from chomping an array?

+Note that parentheses are necessary when you're chomping anything that is +not a simple variable. This is because the chomp() has a higher precedence +than the assignment\, so that the "chomp $cwd = `pwd`;" is interpreted as +"(chomp $cwd) = `pwd`;"\, rather than as "chomp ($cwd = `pwd`)" which you +might expect.

The second sentence refers to "the assignment"\, which is a bit odd after the new first sentence\, which no longer specifically mentions an assignment. How about​:

  Note that parentheses are necessary when you're chomping anything that is   not a simple variable. This is because chomp() has the highest precedence.   For example\, C\<chomp $cwd = `pwd`> is interpreted as C\<(chomp $cwd) =   `pwd`> rather than C\<chomp($cwd = `pwd`> as you might expect.

I don't know if "the highest precedence" is the right way to say it though...

=item chop VARIABLE

-=item chop( LIST ) +=item chop( LIST ) # note parentheses here

=item chop

Chops off the last character of a string and returns the character chopped. It is much more efficient than C\<s/.$//s> because it neither scans nor copies the string. If VARIABLE is omitted\, chops C\<$_>. + If VARIABLE is a hash\, it chops the hash's values\, but not its keys. +If VARIABLE is an array\, each element is chopped. In all cases the value of +the last C\ is returned.

You can actually chop anything that's an lvalue\, including an assignment. - -If you chop a list\, each element is chopped. Only the value of the -last C\ is returned. +But note that parentheses are necessary when you're chopping anything that +is not a simple variable. This is because the chop() has a higher precedence +than the assignment\, so that the "chop $a\,$b;" is interpreted as +"(chop $a)\,$b;" rather than as "chop ($a\,$b)" which you might expect.

Note that C\ returns the last character. To return all but the last character\, use C\<substr($string\, 0\, -1)>.

Similar comments for this part as well. :)

Ronald

p5pRT commented 22 years ago

From @lizmat

At 04​:48 PM 6/24/02 -0700\, Randal L. Schwartz wrote​:

which would lead me to conclude that either both should be legal\, or the documentation should be changed. You> Yes\, but chomp binds tighter than assignment\, as the Deparse output You> indicates\, so you're trying to assign to the non-lvalue return of chomp. You> Thus the parentheses in the example.

In any case\, the documentation of chop() and chomp() may need clarification. Document patch is included.

Liz

p5pRT commented 22 years ago

From @lizmat

perlfunc.patch ```diff --- perlfunc.pod.original Fri Jun 21 19:38:36 2002 +++ perlfunc.pod Tue Jun 25 10:26:41 2002 @@ -650,6 +650,11 @@ chomp($cwd = `pwd`); chomp($answer = ); +Note that parentheses are necessary when you're chomping a left-value. This +is because the chomp() has a higher precedence than the assignment, so that +the "chomp $cwd = `pwd`;" is interpreted as "(chomp $cwd) = `pwd`;", rather +than as "chomp ($cwd = `pwd`)" which you might expect. + If you chomp a list, each element is chomped, and the total number of characters removed is returned. @@ -665,6 +670,10 @@ If VARIABLE is a hash, it chops the hash's values, but not its keys. You can actually chop anything that's an lvalue, including an assignment. +But note that parentheses are necessary when you're chopping a left-value. +This is because the chop() has a higher precedence than the assignment, so that +the "chop $line = ;" is interpreted as "(chop $line) = ;" rather +than as "chop ($line = )" which you might expect. If you chop a list, each element is chopped. Only the value of the last C is returned. ```
p5pRT commented 22 years ago

From @lizmat

At 10​:59 AM 6/25/02 -0400\, Ronald J Kimball wrote​:

On Tue\, Jun 25\, 2002 at 11​:44​:29AM +0200\, Elizabeth Mattijsen wrote​:

-If you chomp a list\, each element is chomped\, and the total number of -characters removed is returned. Should we still explicitly document the behavior when chomping a list\, as distinct from chomping an array?

In my book an array is a variable such as @​list\, something that can be used as a left value. An array can be interpreted as a list in list context. A list is any range of values\, such as (1\,2\,3)\, qw(a b c) or 1..20.

Are these definitions wrong?

+Note that parentheses are necessary when you're chomping anything that is +not a simple variable. This is because the chomp() has a higher precedence +than the assignment\, so that the "chomp $cwd = `pwd`;" is interpreted as +"(chomp $cwd) = `pwd`;"\, rather than as "chomp ($cwd = `pwd`)" which you +might expect.

The second sentence refers to "the assignment"\, which is a bit odd after the new first sentence\, which no longer specifically mentions an assignment. How about​:

Note that parentheses are necessary when you're chomping anything that is not a simple variable. This is because chomp() has the highest precedence. For example\, C\<chomp $cwd = `pwd`> is interpreted as C\<(chomp $cwd) = `pwd`> rather than C\<chomp($cwd = `pwd`> as you might expect.

I don't know if "the highest precedence" is the right way to say it though...

Let's not confuse users in that respect. Third version of doc patch included.

Liz

p5pRT commented 22 years ago

From @lizmat

perlfunc3.patch ```diff --- perlfunc.pod.original Fri Jun 21 19:38:36 2002 +++ perlfunc.pod Tue Jun 25 17:17:46 2002 @@ -621,7 +621,7 @@ =item chomp VARIABLE -=item chomp( LIST ) +=item chomp( LIST ) # note parentheses here =item chomp @@ -644,30 +644,37 @@ } If VARIABLE is a hash, it chomps the hash's values, but not its keys. +If VARIABLE is an array, each element is chomped. In both cases the total +number of characters removed is returned. You can actually chomp anything that's an lvalue, including an assignment: chomp($cwd = `pwd`); chomp($answer = ); -If you chomp a list, each element is chomped, and the total number of -characters removed is returned. +Note that parentheses are necessary when you're chomping anything that is +not a simple variable. This is because "chomp $cwd = `pwd`;" is interpreted as +"(chomp $cwd) = `pwd`;", rather than as "chomp( $cwd = `pwd` )" which you +might expect. =item chop VARIABLE -=item chop( LIST ) +=item chop( LIST ) # note parentheses here =item chop Chops off the last character of a string and returns the character chopped. It is much more efficient than C because it neither scans nor copies the string. If VARIABLE is omitted, chops C<$_>. + If VARIABLE is a hash, it chops the hash's values, but not its keys. +If VARIABLE is an array, each element is chopped. In all cases the value of +the last C is returned. You can actually chop anything that's an lvalue, including an assignment. - -If you chop a list, each element is chopped. Only the value of the -last C is returned. +But note that parentheses are necessary when you're chopping anything that +is not a simple variable. This is because "chop $a,$b;" is interpreted as +"(chop $a),$b;" rather than as "chop( $a,$b )" which you might expect. Note that C returns the last character. To return all but the last character, use C. ```
p5pRT commented 22 years ago

From @lizmat

At 11​:38 AM 6/25/02 -0400\, Ronald J Kimball wrote​:

For code snippets in POD\, C\<> is better than "". That way you'll get the appropriate formatting in whatever renderer (text\, html\, *roff\, etc.) is being used.

I've looked at the pod2html output\, but I find the C\<> syntax handler not necessarily clearer than using quotes. I guess I could create seperate lines for them\, making it _really_ clear that it is a code example.

If the C\<> syntax is customary\, I'll supply yet another patch with those changes...

Liz

p5pRT commented 22 years ago

From @tamias

On Tue\, Jun 25\, 2002 at 05​:19​:33PM +0200\, Elizabeth Mattijsen wrote​:

At 10​:59 AM 6/25/02 -0400\, Ronald J Kimball wrote​:

On Tue\, Jun 25\, 2002 at 11​:44​:29AM +0200\, Elizabeth Mattijsen wrote​:

-If you chomp a list\, each element is chomped\, and the total number of -characters removed is returned. Should we still explicitly document the behavior when chomping a list\, as distinct from chomping an array?

In my book an array is a variable such as @​list\, something that can be used as a left value. An array can be interpreted as a list in list context. A list is any range of values\, such as (1\,2\,3)\, qw(a b c) or 1..20.

Are these definitions wrong?

An array can be a list\, but a list isn't necessarily an array. I'm just wondering if the documentation should still make it explicit what happens when you chomp a list that isn't an array\, such as chomp($x\, $y).

The second sentence refers to "the assignment"\, which is a bit odd after the new first sentence\, which no longer specifically mentions an assignment. How about​:

Note that parentheses are necessary when you're chomping anything that is not a simple variable. This is because chomp() has the highest precedence. For example\, C\<chomp $cwd = `pwd`> is interpreted as C\<(chomp $cwd) = `pwd`> rather than C\<chomp($cwd = `pwd`> as you might expect.

I don't know if "the highest precedence" is the right way to say it though...

Let's not confuse users in that respect. Third version of doc patch included.

Fair enough.

+Note that parentheses are necessary when you're chomping anything that is +not a simple variable. This is because "chomp $cwd = `pwd`;" is interpreted as +"(chomp $cwd) = `pwd`;"\, rather than as "chomp( $cwd = `pwd` )" which you +might expect.

For code snippets in POD\, C\<> is better than "". That way you'll get the appropriate formatting in whatever renderer (text\, html\, *roff\, etc.) is being used.

Ronald

p5pRT commented 22 years ago

From @rgarcia

On 2002.06.25 10​:28 Elizabeth Mattijsen wrote​:

In any case\, the documentation of chop() and chomp() may need clarification. Document patch is included.

Liz --- perlfunc.pod.original Fri Jun 21 19​:38​:36 2002 +++ perlfunc.pod Tue Jun 25 10​:26​:41 2002 @​@​ -650\,6 +650\,11 @​@​ chomp($cwd = `pwd`); chomp($answer = \);

+Note that parentheses are necessary when you're chomping a left-value. This +is because the chomp() has a higher precedence than the assignment\, so that +the "chomp $cwd = `pwd`;" is interpreted as "(chomp $cwd) = `pwd`;"\, rather +than as "chomp ($cwd = `pwd`)" which you might expect.

In fact\, parentheses are always needed\, because the parsing of chom?p is peculiar. For example\, "chomp $x\, $y" really means "chomp($x)\,$y". It doesn't behave as a real list operator (unlike kill()\, for example\, whose equivalent perl prototype is "(@​)").

That's what the header in perlfunc tries to say :

=item chomp VARIABLE

=item chomp( LIST )

=item chomp

p5pRT commented 22 years ago

From @lizmat

At 11​:26 AM 6/25/02 +0200\, Rafael Garcia-Suarez wrote​:

On 2002.06.25 10​:28 Elizabeth Mattijsen wrote​:

In any case\, the documentation of chop() and chomp() may need clarification. Document patch is included. In fact\, parentheses are always needed\, because the parsing of chom?p is peculiar. For example\, "chomp $x\, $y" really means "chomp($x)\,$y". It doesn't behave as a real list operator (unlike kill()\, for example\, whose equivalent perl prototype is "(@​)").

That's what the header in perlfunc tries to say :

=item chomp VARIABLE

=item chomp( LIST )

=item chomp

Because parentheses are sometimes used in documentation and sometimes not\, that pointer was _completely_ missed by me. Second version of document patch included. Hopefully the emphasis will now not be missed by users... ;-)

Liz

p5pRT commented 22 years ago

From @lizmat

perlfunc2.patch ```diff --- perlfunc.pod.original Fri Jun 21 19:38:36 2002 +++ perlfunc.pod Tue Jun 25 11:43:19 2002 @@ -621,7 +621,7 @@ =item chomp VARIABLE -=item chomp( LIST ) +=item chomp( LIST ) # note parentheses here =item chomp @@ -644,30 +644,39 @@ } If VARIABLE is a hash, it chomps the hash's values, but not its keys. +If VARIABLE is an array, each element is chomped. In both cases the total +number of characters removed is returned. You can actually chomp anything that's an lvalue, including an assignment: chomp($cwd = `pwd`); chomp($answer = ); -If you chomp a list, each element is chomped, and the total number of -characters removed is returned. +Note that parentheses are necessary when you're chomping anything that is +not a simple variable. This is because the chomp() has a higher precedence +than the assignment, so that the "chomp $cwd = `pwd`;" is interpreted as +"(chomp $cwd) = `pwd`;", rather than as "chomp ($cwd = `pwd`)" which you +might expect. =item chop VARIABLE -=item chop( LIST ) +=item chop( LIST ) # note parentheses here =item chop Chops off the last character of a string and returns the character chopped. It is much more efficient than C because it neither scans nor copies the string. If VARIABLE is omitted, chops C<$_>. + If VARIABLE is a hash, it chops the hash's values, but not its keys. +If VARIABLE is an array, each element is chopped. In all cases the value of +the last C is returned. You can actually chop anything that's an lvalue, including an assignment. - -If you chop a list, each element is chopped. Only the value of the -last C is returned. +But note that parentheses are necessary when you're chopping anything that +is not a simple variable. This is because the chop() has a higher precedence +than the assignment, so that the "chop $a,$b;" is interpreted as +"(chop $a),$b;" rather than as "chop ($a,$b)" which you might expect. Note that C returns the last character. To return all but the last character, use C. ```
p5pRT commented 19 years ago

From @smpeters

[RT_System - Wed Jun 26 00​:16​:06 2002]​:

At 11​:26 AM 6/25/02 +0200\, Rafael Garcia-Suarez wrote​:

On 2002.06.25 10​:28 Elizabeth Mattijsen wrote​:

In any case\, the documentation of chop() and chomp() may need clarification. Document patch is included. In fact\, parentheses are always needed\, because the parsing of chom?p is peculiar. For example\, "chomp $x\, $y" really means "chomp($x)\,$y". It doesn't behave as a real list operator (unlike kill()\, for example\, whose equivalent perl prototype is "(@​)").

That's what the header in perlfunc tries to say :

=item chomp VARIABLE

=item chomp( LIST )

=item chomp

Because parentheses are sometimes used in documentation and sometimes not\, that pointer was _completely_ missed by me. Second version of document patch included. Hopefully the emphasis will now not be missed by users... ;-)

Liz

This documentation fix went into Perl as change #17367.

p5pRT commented 19 years ago

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