Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

s/// on a list

0 views
Skip to first unread message

Peter Scott

unread,
Oct 25, 2000, 3:00:00 AM10/25/00
to
Sometimes I feel like a complete idiot. This is one of those times.
Why does this:

$ perl -le '$x="a";(($y)=$x)=~s/a/b/;print $y'
a

not do the substitution the way this:

$ perl -le '$x="a";($y=$x)=~s/a/b/;print $y'
b

does? Okay, the former case supplies the binding variable in list
context, but why not operate on the first (or last) element of it?
The closest I can come to an explanation is the perlop text that

(The string specified with =~ must be scalar
variable, an array element, a hash element, or an assignment to one of
those, i.e., an lvalue.)

but I didn't find that really conclusive.

I know, "don't do that." But I had a program where instead of $x I
had a subroutine that returned what I wanted in list context but not
in scalar context...

--
Peter Scott

glauber

unread,
Oct 25, 2000, 3:00:00 AM10/25/00
to
In article <3mrJ5.9856$q9.2...@news1.gvcl1.bc.home.com>,
Pe...@psdt.com wrote:

[...]

> I know, "don't do that." But I had a program where instead of $x I
> had a subroutine that returned what I wanted in list context but not
> in scalar context...


To quote from one of my favourite passages in "perldoc perldata":

If you evaluate an array in scalar context, it returns the
length of the array. (Note that this is not true of lists,
which return the last value, like the C comma operator, nor
of built-in functions, which return whatever they feel like
returning.)

If you're not confused by this, you already know Perl and can start learning
Java now. :-)

glauber

--
Glauber Ribeiro
thegl...@my-deja.com http://www.myvehiclehistoryreport.com
"Opinions stated are my own and not representative of Experian"


Sent via Deja.com http://www.deja.com/
Before you buy.

Linc Madison

unread,
Oct 25, 2000, 3:00:00 AM10/25/00
to
In article <3mrJ5.9856$q9.2...@news1.gvcl1.bc.home.com>, Peter Scott
<pe...@psdt.com> wrote:

> Sometimes I feel like a complete idiot. This is one of those times.
> Why does this:
>
> $ perl -le '$x="a";(($y)=$x)=~s/a/b/;print $y'
> a
>
> not do the substitution the way this:
>
> $ perl -le '$x="a";($y=$x)=~s/a/b/;print $y'
> b
>
> does? Okay, the former case supplies the binding variable in list
> context, but why not operate on the first (or last) element of it?
> The closest I can come to an explanation is the perlop text that
>

> (The string specified with =~ must be a scalar


> variable, an array element, a hash element, or an assignment
> to one of those, i.e., an lvalue.)
>
> but I didn't find that really conclusive.

($y) is not a scalar variable, it's not an array element, it's not a
hash element, and it's not an assignment to one of those. It's a list.

If you still say that the explanation is not conclusive, tell us which
of those things you think ($y) is and why.

> I know, "don't do that." But I had a program where instead of $x I
> had a subroutine that returned what I wanted in list context but not
> in scalar context...

Well, it sounds like the analogous test program would have

($y = ($x)) # assign one-element list to scalar; result is scalar

rather than

(($y) = $x) # assign scalar to one-element list; result is list

Of course, if your return value is an array, rather than a list, then
$y = myfunc() will not give what you want.

Compare

($y = ($x)) # equivalent to $y = $x

@x = ($x);
($y = @x) # equivalent to $y = 1

You can also do something like

( $y = (myfunc())[0] ) =~ s/a/b/; # first element of list
( $y = (myfunc())[-1] ) =~ s/a/b/; # last element of list

If you are getting multiple values in the list, then you want to assign
those to @y and then do your substitution inside some sort of a "for"
loop.

However, it sounds like you're saying that your function returns a
single value, but in a list context.

If you can change the function itself, you should do something like

return wantarray ? @result : $result[0];

Compare these:

sub listfunc { return ("a"); }

sub arrayfunc { my @result = ("a"); return @result; }

sub flexfunc { my @res = ("a"); return wantarray ? @res : $res[0]; }

sub flexfunc2 { return wantarray ? ("a") : "a"; }

In particular, note that listfunc() and arrayfunc() do not behave
identically. Returning a list and returning an array have some subtle
differences.

Mark-Jason Dominus

unread,
Oct 25, 2000, 3:00:00 AM10/25/00
to

Peter Scott wrote:
> $ perl -le '$x="a";(($y)=$x)=~s/a/b/;print $y'
> Okay, the former case supplies the binding variable in list
> context, but why not operate on the first (or last) element of it?

This is all wrong. You say 'first element of it', implying that you
think there is a list here, but there isn't. The binding operator
always supplies a scalar context to its left operand, and so the left
operand always generates a scalar. There is no such thing as a list
in a scalar context, and there's no list here either. So it's not
meaningful to ask about the first or last element of a list, because
there is no list.

People always have this idea that when you write parentheses, like
($y) or (4,5,6), that somehow magically generates a list. That's
wrong. In

@a = (4,5,6);

it isn't the parentheses that generate the list; it's the comma
operator. That is what the comma operator does in a list context.
People think that in

$s = (4,5,6);

what is happening is that Perl is building the list (4,5,6), which is
then 'evaluated' in scalar context, and that a list in scalar context
turns into its last element. This is totally wrong. There is no such
thing as a list in scalar context, and it's meaningless to talk about
a list being 'evaluated', because languages evaluate *expressions*,
not *values*. A *list expression* can be evaluated, but there is no
such thing as a list expression either. There are comma expressions,
such as we have here, which, if they are in list context, build lists.
In a scalar context, however, a comma expression does not build a
list; instead, it returns its right-hand operand. "4,5,6" evaluates
to "5,6", which evaluates to 6, so the result is 6. But there
was never any list.

In your example:

(($y)=$x) =~ s/a/b/

You seem to think that the assignment ($y)=$x is going to yield a
list. In a list context, that is what it would do: It would yield a
list of $y. But this assignment is not in a list context; it is in a
scalar context, because it is the left operand of the =~ operator.
The left operand of the =~ operator provides a scalar context because
=~ is expecting a string, which is a scalar. ($y)=$x cannot possibly
produce a list, because it is in a scalar context and there is no such
thing as a list in a scalar context. =~ is expecting a scalar, so
($y)=$x will produce a scalar.

What scalar will it produce? One thing Perl does *not* do is
construct a list and then return the first element; nor does it
construct a list and then return the last element. It doesn't do this
for @a =~ s/a/b/ either. Perl never constructs a list in scalar
context. Instead, there is a special rule for the value of a list
assignment expression in a scalar context, just as there is a special
rule for the value of the array expression @a in a scalar context.

The rule for a list assignment expression is:

In scalar context, a list assignment expression evaluates to a
number, which is the number of items that were available
for assignment on the right.

For example, if you had had

($y) = (4,5,6)

in scalar context, this would have evaluated to 3, because there are 3
items available for assignment on the right. Instead, you have

($y) = $x

so there is 1 item available for assignment on the right. The value
of this expression in scalar context is 1, and the s/a/b/ is applied
to the string "1". You can see this by doing:

perl -le '$x = 'a'; (($y)=$x)=~ m/\d+/; print $&'

This prints "1". (print ($s = (($y) = $x)) will print the same.)

You might ask why a list assignment expression yields the number of
items available for assignment, rather than the number actually
assigned, or the last or the first of the items. One reason is so
that this will work:

while (($k, $v) = each %keys) { ... }

'each' is in list context, but the assignment itself is in scalar
context, since it is the controlling expression of 'while', which
expects a boolean. In list context, 'each' procudes either a
two-element list or an empty list, depending on whether or not the
hash has run out of pairs. If 'each' produces a two-element list, the
value of the assignment expression is 2, which is true, so the loop
continues; if 'each' produces an empty list, the value of the
assignment expression is 0, which is false, so the loop exits.

This situation also comes up in the following idiom:

my $number_of_matches = (() = ($string =~ m/pattern/g));

The =~ operator is in list context, and in list context =~ with m//g
generates a list of all matching substrings of $string. But the
assignment of this list to () is in scalar context, so the result is
the number of items available for assignment; that is, the total
number of matching substrings.

Any time you talk about a list being produced in a scalar context, you
are making a mistake.

[ Exception: I lied. An XS subroutine can produce a list in scalar context.]

Hugo van der Sanden

unread,
Oct 25, 2000, 3:00:00 AM10/25/00
to
Linc Madison wrote:
> In article <3mrJ5.9856$q9.2...@news1.gvcl1.bc.home.com>, Peter Scott
> <pe...@psdt.com> wrote:
> > Why does this:

> >
> > $ perl -le '$x="a";(($y)=$x)=~s/a/b/;print $y'
> > a
> >
> > not do the substitution [...]

> > The closest I can come to an explanation is the perlop text that
> >
> > (The string specified with =~ must be a scalar
> > variable, an array element, a hash element, or an assignment
> > to one of those, i.e., an lvalue.)
> >
> > but I didn't find that really conclusive.
>
> ($y) is not a scalar variable, it's not an array element, it's not a
> hash element, and it's not an assignment to one of those. It's a list.

Since ($y) is not an acceptable argument to s///, I think perl should
have given an error.

Running with -Dr shows that the substitution tried to act on "1", which
probably ought to be marked readonly. However fixing that aspect would
not give us a particularly useful error message in this case, so the
issue of supplying an invalid argument still applies. I'll file a bug
report.

Hugo

Randal L. Schwartz

unread,
Oct 25, 2000, 3:00:00 AM10/25/00
to
>>>>> "Hugo" == Hugo van der Sanden <h...@crypt0.demon.co.uk> writes:

Hugo> Since ($y) is not an acceptable argument to s///, I think perl should
Hugo> have given an error.

Huh?

It's perfectly fine. It's a parenthesized scalar. Parens here are
meaningless.

But see MJD's fine explanation elsewhere in this thread as well.

print "Just another Perl hacker,"

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<mer...@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!

Ilmari Karonen

unread,
Oct 26, 2000, 10:13:38 AM10/26/00
to
In article <200010251951...@plover.com>, Mark-Jason Dominus wrote:
>
>[ Exception: I lied. An XS subroutine can produce a list in scalar context.]

Okay, now you got me curious: What does that evaluate to? The length?

--
Ilmari Karonen - http://www.sci.fi/~iltzu/
Please ignore Godzilla | "By promoting postconditions to
and its pseudonyms - | preconditions, algorithms become
do not feed the troll. | remarkably simple." -- Abigail

Jaime Metcher

unread,
Oct 26, 2000, 3:34:40 AM10/26/00
to

Mark-Jason Dominus wrote:
> [An excellent reply, which all we list-challenged types should read]

$y = 'I wonder if this will match some pattern';
($x) = $y =~ /some (pattern)/;
$z = $y =~ /some (pattern)/;
print "$x, $z\n";

prints pattern, 1

From perlop:
"If the /g option is not used, m// in list context returns a list consisting of
the subexpressions matched by the parentheses in the pattern".

So ($x) is supplying a list context. This seems to imply that parentheses are
indeed special with regard to list context and are not merely for denoting
precedence. Or is this just a special case for single element lists, given that
($x) is the same as ($x,)?

Jaime Metcher

Linc Madison

unread,
Oct 26, 2000, 4:47:13 AM10/26/00
to
In article <m14s20t...@halfdome.holdit.com>, Randal L. Schwartz
<mer...@stonehenge.com> wrote:

> >>>>> "Hugo" == Hugo van der Sanden <h...@crypt0.demon.co.uk> writes:
>
> Hugo> Since ($y) is not an acceptable argument to s///, I think perl should
> Hugo> have given an error.
>
> Huh?
>
> It's perfectly fine. It's a parenthesized scalar. Parens here are
> meaningless.

No, they're clearly NOT meaningless. Look at the circumstances that
started this thread:

----------
#! perl -w

my $x = 'a';
my $y;

( ($y) = $x ) =~ s/a/b/;
print "$y\n";

( $y = $x ) =~ s/a/b/;
print "$y\n\n";
----------

If the parentheses were meaningless, the two print statements would
give the same value for $y.

The bottom line is that ( $y = $x ) resolves to $y (after the
assignment of the value of $x to $y); the parentheses cause the
assignment to be in a list context instead of a scalar context.

( ($y) = $x ) resolves to 1 when it is interpreted in the scalar
context of the =~ operator.

In other words, the parentheses in ($y) DO magically create a list in
the code above, without a comma. If ($y) were not a list, then the =
would be in a scalar context and ( ($y) = $x ) would be the same as
($y=$x) when taken in the scalar context created by the =~

Also, in the case of

$s = (4,5,6);

the (4,5,6) *IS* a list. See page 47 of the camel book. The list
literal (4,5,6) interpreted in a scalar context becomes the scalar
value 6.

Mark-Jason Dominus

unread,
Oct 26, 2000, 1:32:23 PM10/26/00
to

> So ($x) is supplying a list context. This seems to imply that
> parentheses are indeed special with regard to list context and are
> not merely for denoting precedence.

There's one, and only one place where the parentheses do something
other than control operator precedence, and that is on the *left* side
of an assignment. In that case, they tell Perl that the thing on the
*right* should be evaluated in a list context instead of in a scalar
context.

But the parentheses still don't construct a list value, even on the
left side of an equals sign, because the expression on the left side
of an equals sign is never evaluated. Parentheses on the left don't
change the context of the left side, or the context of the assignment
itself; they only affect the context of the right side.

In your example

($x) = $y =~ /some (pattern)/;

Here "$y =~ /.../" returned a list of the matched backreference
groups, because it's in list context.

$z = $y =~ /some (pattern)/;

Here "$y =~ /.../" returned a boolean value indicating a successful
match, because it's in scalar context. This is analagous to

if ($y =~ /.../) { ... }

[Disclaimer: I lied; the parentheses make a difference in one other
case: On the left-hand side of the x operator. ]

John Porter

unread,
Oct 26, 2000, 10:40:22 AM10/26/00
to
Hugo van der Sanden wrote:
>
> Since ($y) is not an acceptable argument to s///, I think perl should
> have given an error.

But you misunderstand: ($y) was NOT the argument to s/// here!


> I'll file a bug report.

Please don't.
Where would that leave people who actually use that feature?

--
John Porter

Michael Balenger

unread,
Oct 26, 2000, 7:19:46 PM10/26/00
to

Mark-Jason Dominus <m...@plover.com> wrote in message
news:200010251951...@plover.com...

[ lots of useful stuff on differences between lists and arrays ]

Always been a bit foggy to me - I actually got corrected a few times in
recent postings.

Thanks for removing some of the smoke and mirrors.


--
================================================================
Mike Balenger
MBal...@att.net migrating toward MichaelRu...@att.net)
(732)809-3613 cell

All mammals learn by playing.

Michael Balenger

unread,
Oct 26, 2000, 7:54:58 PM10/26/00
to

Mark-Jason Dominus <m...@plover.com> wrote in message
news:200010251951...@plover.com...

> while (($k, $v) = each %keys) { ... }


>
> 'each' is in list context, but the assignment itself is in scalar
> context, since it is the controlling expression of 'while', which
> expects a boolean. In list context, 'each' procudes either a
> two-element list or an empty list, depending on whether or not the
> hash has run out of pairs. If 'each' produces a two-element list, the
> value of the assignment expression is 2, which is true, so the loop
> continues; if 'each' produces an empty list, the value of the
> assignment expression is 0, which is false, so the loop exits.

I had a problem wrapping this around my brain, so I consulted my Perl
CD. (See quoted section below.) It took me a while to grok

"list assignment in a scalar context",

but I think that's the key to understanding this. I saw it from a
slightly different perspective. Perhaps this may help others.

The assignment operator has two effects:

1) A return value. Specifically in this case, it's scalar --
repeatedly 2 until finally 0.

2) A mutator side-effect. Change the scalars in the list of
the LHS with values from the RHS.

================================================================

"2.5.17 - Assignment operators" from "Programming Perl"

List assignment may be done only with the plain assignment
operator, =.

In a list context, list assignment returns the list of new values
just as scalar assignment does.

In a scalar context, list assignment returns the number of values
that were available on the right side of the assignment, as we
mentioned earlier in "List Values and Arrays".

This makes it useful for testing functions that return a null list
when they're "unsuccessful", as in:

while (($key, $value) = each %gloss) { ... }

================================================================


I now think that my previous understanding of this is WRONG:

=begin WRONG_THINKING

1) Perform assignment in a list context. Because the LHS is a list
of scalars, some special DWIM magic happens. The scalars on the LHS
are treated as l-values, and a 1-to-1 algorithm DWIM's them from the
RHS.

2) Evaluate the array in scalar context. This will either return 2
or 0. (I think this was my WRONG assumption. It's not an
*array*, it's a *list*! The list evaluated in a scalar context
would have returned the last element. That would have left the
loop up to the vagaries of the $v! Boo, hiss. That prevents the
loop from operating with values of "0", "", and undef - some of
my most meaningful values.)

=end WRONG_THINKING

=begin REMEDY-IAL_THINKING

So, it's not the "($k, $v)" part that's supplying the scalar
(boolean?) value to the while. It's the "=" operator that's doing it.
Specifically "list assignment in a scalar context".

=end REMEDY-IAL_THINKING

"List assignment in a scalar context."

"List assignment in a scalar context."

"List assignment in a scalar context."

Like any newly learned concept, I have to keep repeating it to myself
to make sure I still have it. And some times I don't.

Thanks, all for the thread.

Hugo van der Sanden

unread,
Oct 26, 2000, 8:23:43 PM10/26/00
to
John Porter wrote:
>
> Hugo van der Sanden wrote:
> >
> > Since ($y) is not an acceptable argument to s///, I think perl should
> > have given an error.
>
> But you misunderstand: ($y) was NOT the argument to s/// here!

Then what was?

Compare these two invocations:
perl -Dr -wle '($y = "x") =~ s/x/y/'
perl -Dr -wle '(($y) = "x") =~ s/x/y/'

> > I'll file a bug report.
>
> Please don't.
> Where would that leave people who actually use that feature?

Please show me how you use this, with a list as the LHS of a
substitution. I haven't yet seen an example.

Hugo

Ilya Zakharevich

unread,
Oct 26, 2000, 7:15:27 PM10/26/00
to
[A complimentary Cc of this posting was sent to Mark-Jason Dominus
<m...@plover.com>],

who wrote in article <2000102617322...@plover.com>:
>
> > So ($x) is supplying a list context. This seems to imply that
> > parentheses are indeed special with regard to list context and are
> > not merely for denoting precedence.
>
> There's one, and only one place where the parentheses do something
> other than control operator precedence, and that is on the *left* side
> of an assignment.

Once I made an excursion into perly.y and toke.c, and IIRC my count
was 3, not one. My recollection is that powers that be decided that
documenting this is not desirable, so I (of course) cannot recollect
these other two cases now...

Ilya

Mark-Jason Dominus

unread,
Oct 26, 2000, 2:05:17 PM10/26/00
to

> The bottom line is that ( $y = $x ) resolves to $y (after the
> assignment of the value of $x to $y); the parentheses cause the
> assignment to be in a list context instead of a scalar context.

No, that's not right either. The assignment is in a scalar context in
both examples:

( $y = $x) =~ s///;
(($y) = $x) =~ s///;

The *assignment* is in a scalar context, because the assignment is on
the left side of =~. But in the two examples, it's a different kind
of assignment. in the first example, it's a scalar assignment, and in
the second example, it's a list assignment.

In a scalar context, a scalar assignment produces the value that was
assigned; in this case $x. But a list assignment produces the number
of values that were available, in this case 1.

> In other words, the parentheses in ($y) DO magically create a list in
> the code above, without a comma.

No, there's no list.

> If ($y) were not a list, then the = would be in a scalar context

'Context' is called 'context' for a good reason. You cannot tell, by
looking at an expression, what context it is in, just like you cannot
tell the context of a person just by looking at a photograph of their
face. You need the background scenery to know the context. An
expression can be in any context. You have to look at the parts of
the larger expression that it is embedded in to know the context it is
in.

Nothing in the assignment expression itself can affect what context it
is in. Only the context in which it is used can affect the context.

As I explained in an earlier article, the parentheses change the
assignment from a scalar assignment expression to a list assignment
expression. These two kinds of expressions have different behaviors
when used in scalar context, as they are here.

> Also, in the case of
>
> $s = (4,5,6);
>
> the (4,5,6) *IS* a list.

No, it is a comma expression. The Camel book (2 ed) calls this
expression a 'list literal', which means the same thing, but is
confusing, because it is not the same as a list value.

> The list literal (4,5,6) interpreted in a scalar context becomes the
> scalar value 6.

People frequently have a confusion about the difference between what
they write in the program code and the meaning that the program
attaches to what they have written. What they write is the syntax,
and the meaning attached is the semantics.

This confusion causes a lot of problems. For example, they write this
program:

$number = <STDIN>;
print $number + 1, "\n";

Then they run the program and type in 007 and they complain when the
result is 8 instead of 010. They show up in the newsgroups pointing
at the Camel book, which says that 007 is an octal constant, and
asking why Perl did not do the right thing and increment 007 to 010.
But the answer is that 007 is only an octal constant whan it is a
'literal', which means when it appears literally in the source code.

Or similarly, they ask how to tell whether a number in Perl is in
octal or decimal format. This question doesn't make any sense,
because internally, all Perl numbers are stored in your computer's
internal format, which is neither octal nor decimal. But people get
the idea that because there are two representations for numbers in the
source code (octal and decimal) there are also two internal
representations inside of Perl.

The confusion in this thread seems to be about source code
vs. internal representations, because the word 'list' is being used in
two ways. You and the camel book are using it to mean 'list literal',
which is a part of the source code that starts with a parenthesis
character, continues with a sequence of items separated by commas, and
ends with a close parentheses character. But I was using 'list' only
to mean a list *value*, which is an internal data structure that Perl
uses to represent a list.

When I said "There is no such thing as a list in a scalar context" I
was speaking of list *values*. Of course you can write a literal list
expression in a scalar context; you can write anything you want. But
it still will not produce a list value. When you call that expression
a "list literal" you suggest to people that it is going to produce a
list value, just as a string literal produces a string, but in this
case that is mistaken. The "list literal" will not produce a list
value unless it is in list context. That is why I call it a "comma
expression" instead.

The parentheses in Perl never create a list value. They do two
things:

* They change the way expressions are parsed. (Operator precedence)

* On the left side of an = operator, they put the *right* side into
list context, and they change the operator from a scalar assignment
operator to a list assignment operator.

In

($y) = (1,2,3)

the left set of parentheses puts the right side into a list context,
so that the comma operators there construct a list of three values.

The parentheses on the left certainly *don't* create a list, as you
said, because the expression on the left side of an equals sign is
never evaluated at all!

Mark-Jason Dominus

unread,
Oct 27, 2000, 3:46:21 AM10/27/00
to

> Once I made an excursion into perly.y and toke.c, and IIRC my count
> was 3, not one.

One of these is the left-hand operand of the 'x' operator, which I did
mention somewhere else in this thread. But if there is a third one, I
am not sure I know what it is. Perhaps you could consider
(expr)[3,2,9] as a third exception?

Jaime Metcher

unread,
Oct 26, 2000, 9:25:41 PM10/26/00
to
Thanks for that excellent explanation. So is Randal's post in this thread a
little...I won't say wrong, but perhaps off-the-cuff.

Jaime Metcher

Hugo van der Sanden

unread,
Oct 25, 2000, 9:13:11 PM10/25/00
to
Randal L. Schwartz wrote:
>
> >>>>> "Hugo" == Hugo van der Sanden <h...@crypt0.demon.co.uk> writes:
>
> Hugo> Since ($y) is not an acceptable argument to s///, I think perl should
> Hugo> have given an error.
>
> Huh?
>
> It's perfectly fine. It's a parenthesized scalar. Parens here are
> meaningless.

They're hardly meaningless - the meaning is quite different to what it
would have been without the parens.

> But see MJD's fine explanation elsewhere in this thread as well.

I agree that he gave a fine explanation of perl's current behaviour in
this case. I don't believe that this behaviour is useful, and I'd like
to help define and implement more useful behaviour for perl in this
case.

I believe (and have seen some agreement) that the '1' should be
readonly. Unfortunately that would still give us only a 'Modification of
a read-only value attempted at ...' error message, which still isn't
particularly informative. Perhaps the optimiser needs a scalarlvalue()
coercion so that we could give more helpful error messages in cases such
as these.

Hugo

Randal L. Schwartz

unread,
Oct 27, 2000, 12:45:26 PM10/27/00
to
>>>>> "Jaime" == Jaime Metcher <met...@spider.herston.uq.edu.au> writes:

Jaime> Thanks for that excellent explanation. So is Randal's post in
Jaime> this thread a little...I won't say wrong, but perhaps
Jaime> off-the-cuff.

It's plain wrong... I didn't read enough of the context to understand
that it was one of the few places where parens DO matter. I'm sorry.

Peter Scott

unread,
Oct 27, 2000, 1:41:50 PM10/27/00
to
In article <39F8CB0F...@crypt0.demon.co.uk>,

Hugo van der Sanden <h...@crypt0.demon.co.uk> writes:
>John Porter wrote:
>>
>> Hugo van der Sanden wrote:
>> >
>> > Since ($y) is not an acceptable argument to s///, I think perl should
>> > have given an error.
>>
>> But you misunderstand: ($y) was NOT the argument to s/// here!
>
>Then what was?

The scalar value 1, the result of the list assignment in scalar context.

Doing a s/// on a literal list operates on the last element (per perldata):

$ perl -Mstrict -wle 'my $x = "abc"; ($x) =~ s/b/z/; print $x'
azc
$ perl -Mstrict -wle 'my $x = "abc"; my $y = "dbe"; ($x,$y) =~ s/b/z/; print "$x $y"'
Useless use of private variable in void context at -e line 1.
abc dze

(I've been reading the thread most carefully!)

>Compare these two invocations:
> perl -Dr -wle '($y = "x") =~ s/x/y/'
> perl -Dr -wle '(($y) = "x") =~ s/x/y/'
>
>> > I'll file a bug report.
>>
>> Please don't.
>> Where would that leave people who actually use that feature?

The bug is that there is no warning at the attempt to perform a substitution on
the read-only 1 resulting from the list assignment. I'm trying to learn to read
the output of -Dt; I *think* that what I'm seeing from

$ perl -Drt -wle '(($y) = "x") =~ s/1/y/'

means that it's actually modifying that 1, wherever it is:

[...]
(-e:1) aassign
(-e:1) const(PV("y"\0))
(-e:1) subst
[...]
Setting an EVAL scope, savestack=3
0 <> <1> | 1: EXACT <1>
1 <1> <> | 3: END
Match successful!

--
Peter Scott

John Porter

unread,
Oct 27, 2000, 2:30:35 PM10/27/00
to
Hugo van der Sanden wrote:
>
> I don't believe that this behaviour is useful, and I'd like
> to help define and implement more useful behaviour for perl in this
> case.
>
> I believe (and have seen some agreement) that the '1' should be
> readonly.
> Perhaps the optimiser needs a scalarlvalue()
> coercion so that we could give more helpful error messages in cases such
> as these.

I think you're making way too big a deal out of this.
Has this feature actually hurt you somehow?

--
John Porter

By pressing down a special key It plays a little melody

John Porter

unread,
Oct 27, 2000, 2:33:08 PM10/27/00
to
Peter Scott wrote:
>
> The bug is that there is no warning at the attempt to perform a substitution on
> the read-only 1 resulting from the list assignment.

Just because some people don't know every little thing about perl,
it does not follow that perl should be changed.

--
John Porter

John Porter

unread,
Oct 27, 2000, 11:36:34 AM10/27/00
to
Hugo van der Sanden wrote:
> >
> > But you misunderstand: ($y) was NOT the argument to s/// here!
>
> Then what was?

The result of the list-assignment-in-scalar-context, i.e. the number 1.

--
John Porter

Hugo van der Sanden

unread,
Oct 27, 2000, 11:36:31 PM10/27/00
to
John Porter wrote:
> Hugo van der Sanden wrote:
> > I don't believe that this behaviour is useful, and I'd like
> > to help define and implement more useful behaviour for perl in this
> > case.
> >
> > I believe (and have seen some agreement) that the '1' should be
> > readonly.
> > Perhaps the optimiser needs a scalarlvalue() coercion so that we
> > could give more helpful error messages in cases such as these.
>
> I think you're making way too big a deal out of this.

How so?

> Has this feature actually hurt you somehow?

No, it hasn't. Has this bug actually helped you somehow?

If I become aware of a bug, I want to see it fixed regardless of whether
it directly affects me. The only question is whether this behaviour
should be classified as buggy, and if so which particular aspect(s) of
it are buggy.

It seems clear to me in the context of the rest of perl that if a
temporary list supplies its count to a scalar context, that count should
be a readonly value. I have seen no one yet offer an argument against
that.

It is also arguable that a list that will supply its count as the LHS of
a substitution should be treated as a separate error, so that we can
give a more informative error message than 'Modification of a read-only
value attempted at ...'. The only argument I've seen against this so far
concentrates on m// and its relationship with s///. The issue remains
debatable.

Is there some aspect of this you disagree with? If so, please explain
why.

Hugo

Ilya Zakharevich

unread,
Oct 30, 2000, 2:32:27 PM10/30/00
to
[A complimentary Cc of this posting was sent to Peter Scott
<Pe...@psdt.com>],
who wrote in article <y7jK5.11342$q9.3...@news1.gvcl1.bc.home.com>:

> >> But you misunderstand: ($y) was NOT the argument to s/// here!
> >
> >Then what was?
>
> The scalar value 1, the result of the list assignment in scalar context.

> The bug is that there is no warning at the attempt to perform a substitution on


> the read-only 1 resulting from the list assignment.

As you see, this value is not a tiny bit more read-only than

my ($x, $y) = (2, 3);
($x + $y) =~ s/\d/$&$&/;

Why should it be?

Ilya

Ren Maddox

unread,
Oct 30, 2000, 3:45:19 PM10/30/00
to
il...@math.ohio-state.edu (Ilya Zakharevich) writes:

Eh?

perl <<'__END__'


my ($x, $y) = (2, 3);
($x + $y) =~ s/\d/$&$&/;

__END__
Can't modify addition (+) in substitution (s///) at - line 2, near "s/\d/$&$&/;"
Execution of - aborted due to compilation errors.


Ilya,

I read and re-read your post several times without determining what it
is you are alluding to. Are you saying that it isn't a bug? Or that
it is? Or are you just giving an example of similar code that
currently produces an error as evidence for why this code should
produce an error?

Since it's been omitted from the citations, here is some code that
seems like it should produce an error but doesn't:

perl <<'__END__'
(my($x, $y) = (2, 3)) =~ s/\d/$&$&/;
__END__

--
Ren Maddox
r...@tivoli.com

Joe Smith

unread,
Nov 11, 2000, 3:00:00 AM11/11/00
to
In article <mv3K5.10891$xJ4.3...@bgtnsc06-news.ops.worldnet.att.net>,

Michael Balenger <MBal...@worldnet.att.net> wrote:
>=begin REMEDY-IAL_THINKING
>
>So, it's not the "($k, $v)" part that's supplying the scalar
>(boolean?) value to the while. It's the "=" operator that's doing it.
>Specifically "list assignment in a scalar context".
>
>=end REMEDY-IAL_THINKING

No, the scalar context comes from the while() expression, not the equal sign.

LABEL while (EXPR) BLOCK

"The _while_ statement repeatedly executes the block as long
as the EXPR is true."

The process of evaluating whether EXPR is true is what provides scalar
context.

The correct thing to remember is that
list in scalar context == number of elements in list
regardless of the presence or absence of any assignment.

-Joe
--
See http://www.inwap.com/ for PDP-10 and "ReBoot" pages.

Randal L. Schwartz

unread,
Nov 11, 2000, 3:00:00 AM11/11/00
to
>>>>> "Joe" == Joe Smith <in...@best.com> writes:

Joe> The correct thing to remember is that
Joe> list in scalar context == number of elements in list
Joe> regardless of the presence or absence of any assignment.

I don't think this is the right thing to remember at all.
First, you can't have a "list in a scalar context".

You can have @a in a scalar context, which doesn't yield a list, but
rather the number of items currently in the @a array.

You can have (5, 7, 9) in a scalar context, which doesn't yield a
list, but rather evaluates 5, then 7, then 9, sequentially returning 9.

You can have getpwuid in a scalar context, which doesn't yield a list,
but rather returns the username associated with a specified user id.

You can have keys() in a scalar context, which doesn't yield a list,
but rather quickly returns the number of keys, without ever visiting
them all to see what's there or even allocating memory to build a
list.

You can have reverse() in a scalar context, which doesn't yield a
list, but rather returns a string-reverse of the concatenation of its
arguments.

Are you getting the idea?

THERE IS NEVER A LIST IN A SCALAR CONTEXT.

NEVER.

Get it?

How many more times must we say this to kill this meme?

<sigh>

Joe Smith

unread,
Nov 12, 2000, 3:00:00 AM11/12/00
to
In article <m11ywit...@halfdome.holdit.com>,

Randal L. Schwartz <mer...@stonehenge.com> wrote:
>>>>>> "Joe" == Joe Smith <in...@best.com> writes:
>
>Joe> The correct thing to remember is that
>Joe> list in scalar context == number of elements in list
>Joe> regardless of the presence or absence of any assignment.
>
>I don't think this is the right thing to remember at all.
>First, you can't have a "list in a scalar context".

OK, it looks like we need some better nomenclature to describe
the situation being described.

>You can have @a in a scalar context, which doesn't yield a list, but
>rather the number of items currently in the @a array.

And '@a' can refer to an array by name, a reference to an array,
or a slice of an array. OK so far.

>You can have (5, 7, 9) in a scalar context, which doesn't yield a
>list, but rather evaluates 5, then 7, then 9, sequentially returning 9.

A bunch of scalar literals or scalar expressions separated by the
comma operator. Got it.

What I'm looking for are the proper words to describe this:

print scalar(($a,$b) = (111,222));

The thing on the left hand side '($a,$b)' is not an array.
Maybe it is described in "perldoc perldata" ... yes!

List assignment in a scalar context returns the number of
elements produced by the expression on the right side of the
assignment:

>Are you getting the idea?
>
> THERE IS NEVER A LIST IN A SCALAR CONTEXT.
>
> NEVER.
>
>Get it?
>
>How many more times must we say this to kill this meme?

OK, OK. You can have a list assignment in scalar context, but there is
no such thing as a list in scalar context. Adding that one word,
"assignment", negates my quoted sentence above. My bad. I should have
quit while I was ahead.

Linc Madison

unread,
Nov 12, 2000, 3:00:00 AM11/12/00
to
> > THERE IS NEVER A LIST IN A SCALAR CONTEXT. NEVER.
>
> OK, OK. You can have a list assignment in scalar context, but ...

Returning to the original point of this thread, it is a BUG in the Perl
language that the code

( ($x) = $y ) =~ s/foo/bar/;

does not generate a fatal error.

The expression to the left of the =~ is not an lvalue in the scalar
context of the substitution, but an lvalue is required for the
substitution.

Therefore, the code MUST fail with an error that you are attempting a
substitution on something that is not an lvalue, since it is an illegal
operation. At the very least, it must generate a warning under "-w" or
"use strict", since it cannot possibly be what you intended.

There has been some discussion that this is actually a "feature" rather
than a "bug," but there is no possible practical use, now or ever, for
this particular "feature," because

( ($x) = $y ) =~ s/foo/bar/;

is exactly syntactically equivalent to

($x) = $y;
my $void = 1;
$void =~ s/foo/bar/; # possible side effects*
undef $void;

If the substitution has no side effects, then you can use only the
first line. If the substitution does have side effects, they should be
put out in the open, rather than hiding in a useless void substitution.

End of discussion.
_____
* The literal substitution s/foo/bar/ has no side effects, but it is
possible to construct a substitution that does.

0 new messages