Re: Function Prototype Context Conversion
by ariels (Curate) on Jun 12, 2002 at 20:05 UTC
|
...why can't @foo be treated as an implicit list for DWIM purposes?
Because you asked Perl to treat it specially!
Think of it like this: when you say sub foo($), you're telling Perl to convert to a scalar the first arg of foo. When you say ``foo(@foo)'', you know that @foo has only one element (and therefore can assume you know what you mean), but perl doesn't. All perl looks at is the syntax of your code: an array is being used in a scalar context. So it gets converted to a scalar. Your "rule" for converting only works for 1-element lists; Perl's rule for converting an array to a scalar works for any size array.
It looks like another behaviour of Perl's conversion semantics that manages to confuse people.
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Function Prototype Context Conversion
by japhy (Canon) on Jun 12, 2002 at 20:05 UTC
|
Perhaps you don't know that what the $ prototype does is place scalar(...) around the given argument to the function.
sub foo ($$) {
print "<@_>\n";
}
foo(@this, %that); # foo(scalar(@this), scalar(%that));
An array evaluated in scalar context returns its size.
_____________________________________________________
Jeff[japhy]Pinyan:
Perl,
regex,
and perl
hacker, who'd like a job (NYC-area)
s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??; | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Function Prototype Context Conversion
by Juerd (Abbot) on Jun 12, 2002 at 20:16 UTC
|
| [reply] [Watch: Dir/Any] |
Re: Function Prototype Context Conversion
by chromatic (Archbishop) on Jun 12, 2002 at 19:57 UTC
|
my @foo = ( 1 .. 5 );
my $list-to-scalar = @foo;
my $length-of-array = @foo;
| [reply] [Watch: Dir/Any] [d/l] |
|
No, that much is clearly understood. What I mean is that with respect to function prototypes, passing an array to a scalar prototype would seem to be a type mismatch, although these are kind of relative in such a loosely typed language as Perl. You'd hope for a warning, perhaps. You've asked for a scalar, but you're getting a list.
What I was expecting was that the @foo array would be expanded into the brackets in the function call and passed through as a list, but Perl appears to be doing some truly clever things to try and handle the prototype, taking it to the ultimate extreme.
Update:
japhy and everyone else who has been kind enough to post remarks on this subject is 100% correct, of course. What led to this insight into prototypes was one part ass, one part you, one part me, and we all know what that adds up to.
The counter-intuitive component of this is that I'd expected an automatic array-to-list conversion to be peformed before said list is then passed to the prototype, but this is not the case. A list of an array is not the same as a list of the array elements.
| [reply] [Watch: Dir/Any] |
|
sub foo ($) { ... }
@a = (1,10,100);
foo(@a); # no error, '3' is passed to foo()
foo(1,10,100); # error, too many args
you'd have seen. Arrays and lists are not the same thing.
_____________________________________________________
Jeff[japhy]Pinyan:
Perl,
regex,
and perl
hacker, who'd like a job (NYC-area)
s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??; | [reply] [Watch: Dir/Any] [d/l] |
Re: Function Prototype Context Conversion
by Abigail-II (Bishop) on Jun 13, 2002 at 11:00 UTC
|
why can't @foo be treated as an implicit list for DWIM purposes?
What DWIM purposes? You want a scalar as
first argument to foo, so Perl is doing exactly
that, evaluating the first argument of foo in
scalar context.
This is a known issue with prototypes, and one of the reasons
prototypes in Perl are often thought of a "a failed experiment".
If you prototype foo as taking one scalar as
argument, and you want foo @foo to succeed, what's
the point of using a scalar prototype? Any argument is going
to be scalar anyway. The only "use" could be to fail if
@foo != 1. But that means you cannot do prototype
checking at compile time, but have to defer it to runtime.
But the neat thing about prototypes is compile time checking.
Abigail
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
It all has to do with compile time and run time.
Prototyping has a compile time effect, while the number of
elements in an array isn't known till run time. I fail the
see the relevancy of your shell example. Prototyping changes
the way perl parses Perl. Expecting no changes when using
prototypes is a mistake (if you don't want changes, don't
change your code! ;-)).
Abigail
| [reply] [Watch: Dir/Any] |