using wildcards with -e

T

Tad McClellan

Clenna Lumina said:
I understand that it is undefined behavior, but what I'm trying to
determine is what useful purpose could that possibly serve?


None, other than to indicate that it has been called incorrectly.

Why doesn't
it just return the count?


Why don't you just call map() when you want the count?
 
C

Clenna Lumina

Tad said:
None, other than to indicate that it has been called incorrectly.

True. It just seems like unexpected behavior given that it returns a
list, and lists in scalar context normally return the amount of items.
Why don't you just call map() when you want the count?

Yes one could do that. I can understand why it would not be of high
importance, as sort in scalar context would seem like a waste when you
think about it, but that doesn't mean that there will never me never
were any situations where returning the count could have a use.

For instance, I could imagine some really crazy/obfuscated code that
uses the body of a sort function to do some unorthodox type processing.
I mean, I've seen crazier things done in Perl :)
 
M

Michele Dondi

I understand that it is undefined behavior, but what I'm trying to
determine is what useful purpose could that possibly serve? Why doesn't
it just return the count?

Yep, actually it may, if not for anything else, for consistency. But
that would amount to sort() a list to get the count of the sorted
list, which is the same of the unsorted one. So you would be doing
something "very unnecessary" (unless the sort subroutine has some
side-effect, but even then...) and perhaps that's the logic behind the
undefined behaviour.
(Note to self, update perldoc.)

I didn't know that you were a maintainer.


Michele
 
M

Michele Dondi

think about it, but that doesn't mean that there will never me never
were any situations where returning the count could have a use.

Give one such example, then!
For instance, I could imagine some really crazy/obfuscated code that
uses the body of a sort function to do some unorthodox type processing.
I mean, I've seen crazier things done in Perl :)

Well, that Perl is apt at obfu doesn't mean by any means that
capabilities in this sense are a design goal. They're all side-effects
of something thought to be useful in "regular" code.


Michele
 
P

Paul Lalli

True. It just seems like unexpected behavior given that it
returns a list, and lists in scalar context normally return
the amount of items.

You keep saying that. It's really just not true. An array in scalar
context returns the size. SOME functions, as you've found, return the
size of a list of items when called in scalar context. A "list in
scalar context" NEVER returns its size.

sub foo { 1 }
sub bar { 10 }
my $a = (foo(), bar());
my $b = ('a', 'b', 'c', 'd');
my @stuff = (10..15);
my $c = @stuff[0..2];
my %h = (one => 'a', two => 'b', three => 'c');
my $d = @h{'two', 'one'};
print for $a, $b, $c, $d;

In this example, $a, $b, $c, and $d are 10, 'd', 12, and 'a',
respectively.

Please see also:
perldoq -q list
Found in /software/perl-5.8.5-0/pkg/lib/5.8.5/pod/perlfaq4.pod
What is the difference between a list and an array?

Paul Lalli
 
T

Tad McClellan

It just seems like unexpected behavior given that it returns a
list,


It does NOT return a list when called in scalar context.

It is impossible to return a list from a scalar context, because
There Is No Such Thing As A List In Scalar Context.

From perlfunc.pod:

You can't get a list
like C<(1,2,3)> into being in scalar context, because the compiler knows
the context at compile time. It would generate the scalar comma operator
there, not the list construction version of the comma. That means it
was never a list to start with.

and lists in scalar context normally return the amount of items.
^^^^^^^^^^^^^^^^^^^^^^^

No they don't.

Lists do not even exist in a scalar context.

Some _functions_ (not lists) normally return the amount of items
when called in scalar context, but many more return something
other than the count of items, eg:


perldoc -f each
perldoc -f localtime
perldoc -f readpipe (backticks)
perldoc -f reverse

From perlfunc.pod:

Remember the following important rule: There is B<no rule> that relates
the behavior of an expression in list context to its behavior in scalar
context, or vice versa. It might do two totally different things.
Each operator and function decides which sort of value it would be most
appropriate to return in scalar context. Some operators return the
length of the list that would have been returned in list context. Some
operators return the first value in the list. Some operators return the
last value in the list. Some operators return a count of successful
operations. In general, they do what you want, unless you want
consistency.

Yes one could do that. I can understand why it would not be of high
importance, as sort in scalar context would seem like a waste when you
think about it,


Larry thought about it.

How can he indicate that it "seems like a waste"?

By returning undef whenever you do it maybe?

Wadda guy, that Larry!

but that doesn't mean that there will never me never
were any situations where returning the count could have a use.


Then you call map() instead of sort().
 
C

Clenna Lumina

Paul said:
You keep saying that. It's really just not true. An array in scalar
context returns the size. SOME functions, as you've found, return the
size of a list of items when called in scalar context.

True, but see my next point.
A "list in scalar context" NEVER returns its size.

$ perl -le 'print scalar(()=(22,33,44,77,88))'
5

Then why does this return the size? Isn't the " ()= " part forcing
list context? Without that, you get the last value in the set.
sub foo { 1 }
sub bar { 10 }
my $a = (foo(), bar());
my $b = ('a', 'b', 'c', 'd');
my @stuff = (10..15);
my $c = @stuff[0..2];
my %h = (one => 'a', two => 'b', three => 'c');
my $d = @h{'two', 'one'};
print for $a, $b, $c, $d;

In this example, $a, $b, $c, and $d are 10, 'd', 12, and 'a',
respectively.

Well, isn't () acting as a different operator until list context is
forced (see above) ?

Please see also:
perldoq -q list
Found in /software/perl-5.8.5-0/pkg/lib/5.8.5/pod/perlfaq4.pod
What is the difference between a list and an array?

Yes I realize they are not the same, and what you outlined is a big
difference, though the behavior seems clear when list context is
properly forced?
 
C

Clenna Lumina

Tad said:
It does NOT return a list when called in scalar context.
True.

It is impossible to return a list from a scalar context, because
There Is No Such Thing As A List In Scalar Context.

From perlfunc.pod:

You can't get a list
like C<(1,2,3)> into being in scalar context, because the compiler
knows the context at compile time. It would generate the scalar
comma operator there, not the list construction version of the
comma. That means it was never a list to start with.

Thats sort of what I was beginning to suspect myself:

$ perl -le 'print scalar(()=(22,33,44,77,88))'
5

$ perl -le 'print scalar((22,33,44,77,88))'
88

With out the " ()= " it's nto a list, but as that doc snippet says, a
product of the comma operator. So I would be correct to say " ()= "
forces list context?
^^^^^^^^^^^^^^^^^^^^^^^

No they don't.

Lists do not even exist in a scalar context.

Ok I said it wrong, but I also recognize I generally conveyed that all
wrong. I was really wondering about having more consistant behavior
amoung the built in list-returning functions, but I can undertand why
some of thme return the eay they do.
Some _functions_ (not lists) normally return the amount of items
when called in scalar context, but many more return something
other than the count of items, eg:


perldoc -f each
perldoc -f localtime
perldoc -f readpipe (backticks)
perldoc -f reverse

From perlfunc.pod:
[...]

Point taken.
 
C

Clenna Lumina

Michele said:
Yep, actually it may, if not for anything else, for consistency. But
that would amount to sort() a list to get the count of the sorted
list, which is the same of the unsorted one. So you would be doing
something "very unnecessary" (unless the sort subroutine has some
side-effect, but even then...) and perhaps that's the logic behind the
undefined behaviour.


I didn't know that you were a maintainer.

I was referring to my local copy of it. I have updated to 5.8 and am
seeing the same docs as some of you have quoted throughout this thread.
I'm glad this was caught, as the new version is so much better.
 
P

Paul Lalli

True, but see my next point.


$ perl -le 'print scalar(()=(22,33,44,77,88))'
5

Then why does this return the size? Isn't the " ()= " part
forcing list context? Without that, you get the last value in
the set.

I don't know what point you're trying to make. A "list in scalar
context" does not exist. Rather, the comma operator is being used in
scalar context in my example, and the comma operator returns its right-
hand operand.

In your example, you are evaluating a LIST ASSIGNMENT OPERATION in
scalar context. A list assignment, in scalar context, returns the
size of the right-hand list. That is simply one additional example of
things that return sizes when evaluated in scalar context. It is not
the same thing as saying a "list returns its size in scalar context".

It is not "the ()= part" that returns the size. The assignment of the
right-hand list to an empty list evaluates the right-hand list in list
context. Of course, this is completely irrelevant, because we're not
doing anything with the result of this assignment - it's being
discarded by assigning to an empty list. But then that entire
expression, "()=(1,2,3,4)", is evaluated in scalar context. THAT
EXPRESSION is what returns the size of its right-hand list in scalar
context.

A list-assignment operation is just one more example of an expression
which when evaluated in scalar context returns the size of a list.
You've also found the examples of grep and map which do the same
thing. This does not change the fact that there are also examples
that do something differently which you've also found or been shown -
sort, slices, reverse, etc.

This, of course, is all documented in `perldoc perlop`:
Unlike in C, the scalar assignment operator produces a valid
lvalue. Modifying an assignment is equivalent to doing the
assignment and then modifying the variable that was assigned
to. This is useful for modifying a copy of something, like
this:
($tmp = $global) =~ tr [A-Z] [a-z];

Likewise,

($a += 2) *= 3;

is equivalent to

$a += 2;
$a *= 3;

Similarly, a list assignment in list context produces the
list of lvalues assigned to, and a list assignment in scalar
context returns the number of elements produced by the
expression on the right hand side of the assignment.

sub foo { 1 }
sub bar { 10 }
my $a = (foo(), bar());
my $b = ('a', 'b', 'c', 'd');
my @stuff = (10..15);
my $c = @stuff[0..2];
my %h = (one => 'a', two => 'b', three => 'c');
my $d = @h{'two', 'one'};
print for $a, $b, $c, $d;
In this example, $a, $b, $c, and $d are 10, 'd', 12, and 'a',
respectively.

Well, isn't () acting as a different operator until list
context is forced (see above) ?

Parentheses are not operators. I haven't a clue what you mean by this
question, or how it applies to anything else. They are used for
precedence, so that:
my $x = 1, 2, 3, 4;
means
my $x = (1, 2, 3, 4);
rather than
(my $x = 1), 2, 3, 4;

Yes I realize they are not the same, and what you outlined is a
big difference, though the behavior seems clear when list
context is properly forced?

Again, I don't know what point you're trying to make. This entire
discussion is about what happens when an expression that returns a
list in list context is used in scalar context. No where has there
been any debate about what those expressions do in a list context.
The whole point is that THERE IS NO CORRELATION between what an
expression does in one context versus another. The behavior is always
clear. It just doesn't necessarily correlate in any way between what
it does in the "other" context.

Paul Lalli
 
C

Clenna Lumina

Paul said:
True, but see my next point.


$ perl -le 'print scalar(()=(22,33,44,77,88))'
5

Then why does this return the size? Isn't the " ()= " part
forcing list context? Without that, you get the last value in
the set.
[...]
It is not "the ()= part" that returns the size. The assignment of the
right-hand list to an empty list evaluates the right-hand list in list
context. Of course, this is completely irrelevant, because we're not
doing anything with the result of this assignment - it's being
discarded by assigning to an empty list. But then that entire
expression, "()=(1,2,3,4)", is evaluated in scalar context. THAT
EXPRESSION is what returns the size of its right-hand list in scalar
context.

I understand what you are saying, but when it comes down to it, and from
your own words, a list is being returned from the expression,
"()=(1,2,3,4)", after which it is evaluated in scalar context.

Is this correct?

After being evaluated in scalar context, you are left with the size.
A list-assignment operation is just one more example of an expression
which when evaluated in scalar context returns the size of a list.

Ok, but I'm a little confused now after reading Tad's post which seems
to say otherwise:

Tad said:
Lists do not even exist in a scalar context.

Some _functions_ (not lists) normally return the amount of items
when called in scalar context, but many more return something
other than the count of items, eg:

It seems to me that lists do naturally return their size when evaluated
in scalar context, as evidenced by using " ()= " on a raw list. So why
do functions like sort not follow this (assuming I'm not horribly
mistaken) ? Maybe some clarification could be in order here, please?
You've also found the examples of grep and map which do the same
thing. This does not change the fact that there are also examples
that do something differently which you've also found or been shown -
sort, slices, reverse, etc.

This, of course, is all documented in `perldoc perlop`:
Unlike in C, the scalar assignment operator produces a valid
lvalue.

Indeed. Running a sample test in c (gcc) gives "invalid lvalue in
assignment" (boo!)
Modifying an assignment is equivalent to doing the assignment
and then modifying the variable that was assigned to.
This is useful for modifying a copy of something, like
this:
($tmp = $global) =~ tr [A-Z] [a-z];

Yes, I've used many such constructs.
Likewise,

($a += 2) *= 3;

is equivalent to

$a += 2;
$a *= 3;

This is one of the many things I love about Perl. It's just a highly
evolved language with a familiar general syntax if you have a c/c++
background as I have.
 
M

Michele Dondi

True, but see my next point.

Quite funnily one minute ago, on my logout from perlmonk.org, I got
the following:

: Remember though that
: THERE IS NO GENERAL RULE FOR CONVERTING A LIST INTO A SCALAR.
: -- Larry Wall in the perl man page
: Connection to perlmonk.org closed.


Michele
 
M

Michele Dondi

Ok I said it wrong, but I also recognize I generally conveyed that all
wrong. I was really wondering about having more consistant behavior
amoung the built in list-returning functions, but I can undertand why
some of thme return the eay they do.

Forget about consistency in Perl. Think about the magic instead. Well,
at least till Perl 6. Which won't trash the magic away, anyway.


Michele
 
C

Clenna Lumina

Michele said:
Quite funnily one minute ago, on my logout from perlmonk.org, I got
the following:

Well if it came from Larry Wall, I think that pretty much defines that
then.
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
Tad McClellan
It is impossible to return a list from a scalar context, because
There Is No Such Thing As A List In Scalar Context.

You are confused. There is absolutely no problem in creating a list
in scalar context. However, the behaviour in this case is
"undefined": very few people know what happens in this situation, and
those who know want it to be changed (the current behaviour is just an
oversight - no developer realized what was happened until people
started to depend on this broken behaviour...).
From perlfunc.pod:

You can't get a list
like C<(1,2,3)> into being in scalar context, because the compiler knows
the context at compile time. It would generate the scalar comma operator
there, not the list construction version of the comma. That means it
was never a list to start with.

Irrelevant. This is about comma operators, not about lists.

Hope this helps,
Ilya

P.S. Yesterday, I checked the C-based modules shipped with 5.8.8, and
only 2 of them (HiRes and POSIX) try to do something intelligent
with returning lists in scalar context.

All the rest (of those returning lists from XSUBs) just ignore
the context - thus trigger the mentioned above "undefined" behaviour.

Of course, I investigated this "not just for fun" - one of MY
modules was doing the same, so MY script using this module was
not actually doing what I expected it do.
 
M

Michele Dondi

^^^^
^^^^


It seems to me that lists do naturally return their size when evaluated

It seems to you but it is not so. It has been carefully explained to
you why raw lists do not even exist in scalar context. It was
instructive and actually I'm marking this thread for future reference.
in scalar context, as evidenced by using " ()= " on a raw list. So why

Using " ()= " evidences only shows that one particular thing called
"list assignment" returns the length of the list being assigned.

cantor:~ [22:49:37]$ perl -le 'print scalar((undef,undef)=1..5)'
5
do functions like sort not follow this (assuming I'm not horribly
mistaken) ? Maybe some clarification could be in order here, please?

Because the behaviour is *not* factorized: had Perl aimed at blind
consistency, perhaps it would have had functions that always return a
list and lists coerced in scalar context would always evaluate to
their lengths. Instead the driving principle has always been that of
DWIM, and most often it has succeeded IMHO. Since sort() in scalar
context can hardly mean anything but possibly for some awkward side
effect, it has been chosen to have an undefined behaviour.


Michele
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was NOT [per weedlist] sent to
Michele Dondi
Because the behaviour is *not* factorized: had Perl aimed at blind
consistency, perhaps it would have had functions that always return a
list and lists coerced in scalar context would always evaluate to
their lengths. Instead the driving principle has always been that of
DWIM, and most often it has succeeded IMHO.

I'm afraid I must call this BS. ;-) ;-( The driving principle was
"graduate growth", and a lot of shortcomings just WERE NOT NOTICED
quick enough - and when ramifications were noticed, it was too late to
change things due to backward compatibility.

Hope this helps,
Ilya
 
P

Paul Lalli

Paul Lalli wrote:

I understand what you are saying,

No, you really really don't.
but when it comes down to it, and from
your own words, a list is being returned from the expression,
"()=(1,2,3,4)", after which it is evaluated in scalar context.

Is this correct?

No. Not correct. Incorrect.

One last time, then I'm done with this thread. It's been explained to
you multiple times, and you're simply arguing that we're wrong at this
point.

The expression "()=(1,2,3,4)" is a list assignment. It is assigning
one list to another. Just like the expression "($a, $b) = (4, 5)" is
a list assignment. Just like "my ($b) = @_" is a list assignment.
The fact that the = operator is being used with a list on the left
side results in the expression on the right side ("(1,2,3,4)", "(4,
5)", or "@_", respectively) being evaluated in a list context.

THE ENTIRE EXPRESSION is then evaluated in a scalar context. THAT
EXPRESSION (the list assignment) in a scalar context returns the size
of the right-hand list (4, 2, and the size of @_, respectively).
After being evaluated in scalar context, you are left with
the size.

No. NO LIST is ever evaluated in a list context.
Ok, but I'm a little confused now after reading Tad's post which
seems to say otherwise:



It seems to me that lists do naturally return their size when
evaluated in scalar context, as evidenced by using " ()= "
on a raw list.

NOTHING either Tad nor I ever said says that. Rather we very
specifically are telling you that your scenario does not exist. THERE
IS NO SUCH THING as a "list being evaluated in scalar context".

Once again, the "() =" does not force the right-hand list to return
its size. It is not the list that's returning its size. It is the
list assignment expression. The entire thing. "() =" imposes list
context on the right-hand list, but this is meaningless because
nothing is being done with the values of that assignment. It is the
entire list assignment expression that, when evaluated in scalar
context, happens to return the size of the right-hand list. The
expression "()=(10,11,12)" returns 3 in scalar context. The
expression "($a, $b, $c)=()" returns 0 in scalar context. The
expression "($a, $b, $c)=foo()" returns whatever the size of the list
foo() returns is in scalar context.
So why
do functions like sort not follow this (assuming I'm not horribly
mistaken) ?

Regrettably, you are horribly mistaken.
Maybe some clarification could be in order here, please?

Because there is no reason to make sort return anything in particular
in scalar context. Why would there be? What on earth would be the
point of sorting a list but not doing anything with the sorted
results? It makes sense for grep to return the size of its resultant
list, if I simply want to know how many items the grep condition holds
for. It makes sense for map to return the size of its resultant list,
if I simply want to know how many items resulted from the
transformation (which is not necessarily the same number as the
original list). There is NO CAUSE to call sort in scalar context, and
therefore the results are undefined.

#How many of @items are greater than two?
my $x = grep { $_ > 2 } @items;

#How many items are produced by repeating each element
#two or three times, depending on even vs odd?
my $x = map { ($_) x ($_ % 2 ? 2 : 3) } @stuff

#What question is answered by this:
my $x = sort @items;
#that would not be answered by:
my $x = @items;
#?

Paul Lalli
 
M

Michele Dondi

I'm afraid I must call this BS. ;-) ;-( The driving principle was
"graduate growth", and a lot of shortcomings just WERE NOT NOTICED
quick enough - and when ramifications were noticed, it was too late to
change things due to backward compatibility.

Well, you're far more knowledgeable than me so I just can't blindily
dismiss your remark as false, but couldn't truth be somewhat in the
middle?


Michele
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was NOT [per weedlist] sent to
Michele Dondi
Well, you're far more knowledgeable than me so I just can't blindily
dismiss your remark as false, but couldn't truth be somewhat in the
middle?

Of course it could. However, in this particular case, it is not. :)

Yours,
Ilya
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top