using wildcards with -e

A

anno4000

[...]
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.

Ah... good idea. I'll make the round over Hash::Util::FieldHash. At
least one internal function could use a revision in this light.

Anno
 
C

Clenna Lumina

Paul said:
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.

No, I never said any of you were wrong. I'm just trying to make sense of
one thing, which still is not quite clear (see below) and I really do
apologize if it seems like I'm asking the same thing over. I guess maybe
it feels like my question is being miss-interpreted in a way.
The expression "()=(1,2,3,4)" is a list assignment. It is assigning
one list to another. [...]

THE ENTIRE EXPRESSION is then evaluated in a scalar context.

Yes. But to clarify, everything /inside/ the C< scalar(...) > is
processed/evaluated before C said:
THAT EXPRESSION (the list assignment) in a scalar context returns the
size of the right-hand list (4, 2, and the size of @_, respectively).

So, to end this confusion, please answer me this:

C< (1,2,3,4) > by itself is a comma operator surrounded by parens [1].
While C< ()=(1,2,3,4) > (or what ever happens to be in the LH set of
parens) RESULTS in a list (IE, C< (1,2,3,4) > does /not/ a LIST until
_something_ forces it to be.) From how I understand things, the
ASSIGNMENT operation RETURNS a LIST. [2]

Is this much true or not? I ask this because some of you have said that
the former [1] is true, and it seems the latter [2] is also true. Why
else would you be getting the SIZE when the result is evaluated SCALAR
context?

Again, I'm sorry for so many questions, I'm just really trying to make
sense of this.

[...]
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

Yes, the usefulness of these two are clear. I'm not arguing otherwise.
#What question is answered by this:
my $x = sort @items;

Well if a sub was added to the sort clause, I could imagine some
crazy-"ob-fu" of a piece of code that uses the values of $a and $b
passed to said sub in conjunction with some outside variable. Given the
sort of obfuscated code I've seen in some sigs alone, I really don't
think such a thing would be outside (at least not far from the edge) the
realm of possibility.

True, that doesn't mean sort should return anything. But if it returned
it's size, that could just add another level of the obfuscation that
could be used. Of course, you do that anyways it seems simply by added
C< ()= > just before the sort call.

I doubt this is reason enough to change it's behavior, and my example
may be shakey at best. It seems it's a question between should it return
what ou'd normally expect with a LIST (it's size) vs what may be more
logical for the function itself. I can agree the latter may be best.

I want to say thank you to everyone for all the input on this.
 
P

Paul Lalli

Paul Lalli wrote:

Arg. I hate going back on my promises to myself...
The expression "()=(1,2,3,4)" is a list assignment. It is assigning
one list to another.
[...]

THE ENTIRE EXPRESSION is then evaluated in a scalar context.

Yes. But to clarify, everything /inside/ the C< scalar(...) > is
processed/evaluated before C< scalar(...) > is applied, correct?

NO. The expression needs to know in what context it is being executed
before it can possibly know what it's supposed to do. Context is
determined BEFORE execution. scalar() does nothing more than force
scalar context upon the expression. Look at this example:

sub myfunc {
if (wantarray) {
print "I'm in list context!!\n";
return (5, 10, 'alpha');
} else {
system('rm -rf');
warn "You shouldn't have done that. Too late now!!\n";
return 0;
}
}

Now, if I call this function by saying:
my ($a, $b, $c) = myfunc();
the function is going to print a notice to STDOUT, and then assign $a
to 5, $b to 10, and $c to 'alpha'.
If, on the other hand, I call it by saying:
my $x = myfunc();
the function is going to execute the 'rm -rf' statement, print a
warning to STDERR, and assign $x to 0.

The context HAS to be determined before the exprssion is evaluated.
There is no other way for the expression *to be* evaluated, because
there is no way of knowing what it should do without knowing the
context in which it was called.
THAT EXPRESSION (the list assignment) in a scalar context returns the
size of the right-hand list (4, 2, and the size of @_, respectively).

So, to end this confusion, please answer me this:

C< (1,2,3,4) > by itself is a comma operator surrounded by parens [1].

It's a series of three comma operators, but yes.
While C< ()=(1,2,3,4) > (or what ever happens to be in the LH set of
parens) RESULTS in a list (IE, C< (1,2,3,4) >

NO. There IS NO WAY OF KNOWING what that expression will result in
without knowing the context in which it was called. That is the whole
point. CONTEXT determines evaluation. With the information you
provided in this snippet, there is no way of knowing what that
expression will result in. If that expression is evaluated in scalar
context, it will return "4". If that expression is evaluated in list
context, it returns the list 1, 2, 3, 4.
does /not/ a LIST until
_something_ forces it to be.) From how I understand things, the
ASSIGNMENT operation RETURNS a LIST. [2]

You understand wrong. The assignment operator returns a list IF AND
ONLY IF the assignment operator is called in a list context. The
assignment operator returns a scalar IF AND ONLY IF the assignment
operator is called in scalar context.
Is this much true or not?
No.

I ask this because some of you have said that
the former [1] is true, and it seems the latter [2] is also true.

YES, EXACTLY. They are BOTH true - IT ALL DEPENDS ON CONTEXT. What
any given expression does is 100% dependent on the context in which it
was called.
Why else would you be getting the SIZE when the result is evaluated SCALAR
context?

Because that is what a list-assignment expression is defined to do in
Perl. If called in list-context, a list-assignment expression returns
the right-hand list. If called in scalar-context, a list-assignment
expression returns the size of the right-hand list.
Again, I'm sorry for so many questions, I'm just really trying to make
sense of this.

It really feels like you're just refusing to believe what we tell
you. I understand that you find this weird, or that you don't WANT to
believe it could be true. But I assure you it is. One single
expression does not have ANY defined behavior until you know in what
context the expression is being evaluated. And the two different
behaviors (really three, once you count void context) do not
necessarily have ANYTHING to do with one another.

Paul Lalli
 
C

Clenna Lumina

Paul said:
Paul Lalli wrote:
The expression "()=(1,2,3,4)" is a list assignment. It is assigning
one list to another.
[...]

THE ENTIRE EXPRESSION is then evaluated in a scalar context.

Yes. But to clarify, everything /inside/ the C< scalar(...) > is
processed/evaluated before C< scalar(...) > is applied, correct?

NO. The expression needs to know in what context it is being executed
before it can possibly know what it's supposed to do. Context is
determined BEFORE execution. scalar() does nothing more than force
scalar context upon the expression. Look at this example:

sub myfunc {
if (wantarray) {
print "I'm in list context!!\n";
return (5, 10, 'alpha');
} else {
system('rm -rf');
warn "You shouldn't have done that. Too late now!!\n";
return 0;
}
}

Ok I get that. I've used wantarray before, so ya tht does bring some
perspective to things like how sort works.
Now, if I call this function by saying:
my ($a, $b, $c) = myfunc();
the function is going to print a notice to STDOUT, and then assign $a
to 5, $b to 10, and $c to 'alpha'.

Ok, makes perfect sense. I've used this sort of construct millions of
times.
If, on the other hand, I call it by saying:
my $x = myfunc();
the function is going to execute the 'rm -rf' statement, print a
warning to STDERR, and assign $x to 0.

Ok, got that too, albiet I would NOT recommend testing the above example
verbatium :)

(There's always a chance some reader might copy it and run it without
catching that line with the system call.)
The context HAS to be determined before the exprssion is evaluated.
There is no other way for the expression *to be* evaluated, because
there is no way of knowing what it should do without knowing the
context in which it was called.
THAT EXPRESSION (the list assignment) in a scalar context returns
the size of the right-hand list (4, 2, and the size of @_,
respectively).

So, to end this confusion, please answer me this:

C< (1,2,3,4) > by itself is a comma operator surrounded by parens
[1].

It's a series of three comma operators, but yes.
Right.
While C< ()=(1,2,3,4) > (or what ever happens to be in the LH set
of parens) RESULTS in a list (IE, C< (1,2,3,4) >

NO. There IS NO WAY OF KNOWING what that expression will result in
without knowing the context in which it was called. That is the whole
point. CONTEXT determines evaluation. With the information you
provided in this snippet, there is no way of knowing what that
expression will result in. If that expression is evaluated in scalar
context, it will return "4". If that expression is evaluated in list
context, it returns the list 1, 2, 3, 4.
does /not/ a LIST until
_something_ forces it to be.) From how I understand things, the
ASSIGNMENT operation RETURNS a LIST. [2]

You understand wrong. The assignment operator returns a list IF AND
ONLY IF the assignment operator is called in a list context. The
assignment operator returns a scalar IF AND ONLY IF the assignment
operator is called in scalar context.

Ok, so the operator itself is (hard) coded that way? So it's as if you
had an overloaded operator using 'wantarray' to check what it should
spit out at the end, if I understand correctly now (I does seme more
clear to me now.)
I ask this because some of you have said that
the former [1] is true, and it seems the latter [2] is also true.

YES, EXACTLY. They are BOTH true - IT ALL DEPENDS ON CONTEXT. What
any given expression does is 100% dependent on the context in which it
was called.

Got it.
Because that is what a list-assignment expression is defined to do in
Perl. If called in list-context, a list-assignment expression returns
the right-hand list. If called in scalar-context, a list-assignment
expression returns the size of the right-hand list.

I guess that answers my question a couple paragraphs back. :)
It really feels like you're just refusing to believe what we tell
you. I understand that you find this weird, or that you don't WANT to
believe it could be true. But I assure you it is. One single
expression does not have ANY defined behavior until you know in what
context the expression is being evaluated. And the two different
behaviors (really three, once you count void context) do not
necessarily have ANYTHING to do with one another.

It's not that I didn't want to believe you, it's that I thought I was
seeing something else, which is clear I wasn't. Having programmed in C++
for so many years I can sometimes forget about the crazy (in a good way)
idioms in Perl, many of which I know quite well.

Once again, thank you. And thank you for not giving up.
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to

[...]
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.

Ah... good idea. I'll make the round over Hash::Util::FieldHash. At
least one internal function could use a revision in this light.

Thanks. (Just grep for GIMME in POSIX to see how to do things.)

A significant part of the mess may be my fault: when I coded OUTLIST
keyword for XS, I did not realize that output of an XS in scalar
context is not defined. If I did, I would just generate the necessary
code to behave "sanely" in scalar context.

E.g., currently XS code

int TimeF(double *frac) { *frac = time_fractions_sec(); return time(); }

int
TimeF(OUTLIST double frac)

behaves fine in

($sec,$frac) = TimeF;
($sec) = TimeF;

but returns a mess in

$sec = TimeF; # YYYY $sec contains fractional part?

The "sane" behaviour, AFAIU, is for $sec= to have the same result as
($sec)=. But now, it is probably too late to change the code
generator for OUTLIST...

[I just do not know whether many extensions currently rely on this
"YYYY" part.]

Yours,
Ilya

P.S. The solution to fix it all is just to change XSRETURN(2) to "DO
THE RIGHT THING" (e.g., just exchange two elements of stack in
scalar context). However, it *would* break a lot of extensions.

P.P.S. I found a backward-compatible way to modify behaviour:

PROTOTYPES: DISABLE SCALARCONTEXT

behaves with the current xs processor the same as

PROTOTYPES: DISABLE

(same, of course, for ENABLE). So one could use such a
statement to switch to a "better" XS generation - without
breaking the extension on older Perls. Any better idea how to
instruct XS parser that the intent is to get "better behavior"?
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
Clenna Lumina
Yes. But to clarify, everything /inside/ the C< scalar(...) > is
processed/evaluated before C< scalar(...) > is applied, correct?

Your confusion is that you think that scalar() is some kind of
"function". It is not: it is an instruction to the compiler.

Think about it the following way (this is not how it actually happens,
but may help nevertheless): when compiler sees

foo(12)

in Perl code, it generates some C call to handle this expression:

if (context == scalar) { return foo_handler_scalar(12);
} else { return foo_handler_list (12); }

When compiler sees scalar( foo(12) ), it generates different code:

return foo_handler_scalar(12);

[There is no code to handle "scalar()" at runtime; all the effects are
confined to compile-time.]

Hope this helps,
Ilya
 
T

Tad McClellan

Clenna Lumina said:
Paul Lalli wrote:

Ok, makes perfect sense. I've used this sort of construct millions of
times.


On the other other hand, if you call it by saying:

my($x) = myfunc();

then it is going to assign 5 to $x, and discard the 10 and the 'alpha'.

:)

So, to end this confusion, please answer me this:

C< (1,2,3,4) > by itself is a comma operator surrounded by parens
[1].

It's a series of three comma operators, but yes.

Right.


There really is no "by itself", it depends on what else is around
it (what's another name for "what else is around? Context!).

$x = (1,2,3,4); # comma operator
@x = (1,2,3,4); # comma is a list separator
push @y, (1,2,3,4); # comma is a list separator
push @y, 1,2,3,4; # comma is a list separator
2 + (1,2,3,4); # comma operator

Ok, so the operator itself is (hard) coded that way?


To requote perlfunc from upthread:

Each operator and function decides which sort of value it would be most
appropriate to return in scalar context.
So it's as if you
had an overloaded operator using 'wantarray' to check what it should
spit out at the end, if I understand correctly now (I does seme more
clear to me now.)


By Jove! I think he's got it!
 

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,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top