On Thu, Mar 03, 2005 at 01:03:07AM -0500, Abhijit Mahabal wrote: : I was thinking about how binding of arguments to parameters in a : sub/method call would happen. Seems to be a darn tricky thing with all : sorts of potential pitfalls! : : I have a few questions. Consider the following piece of code. Are my : expectations correct? : : sub foo($x, $y, *%slurp) { $x + $y } : say "expecting 10: ", foo(3,7); : say "expecting 10: ", foo(x => 3, y => 7); : say "expecting 10: ", foo(y => 7, x => 3); : say "expecting 10: ", foo :y<7> :x<3>;
Those should all work. : my $c = "x"; my $d = "y"; : say "compile time error?: ", foo($c => 3, $d => 7); No error, just prevents any compile-time optimization of named arguments. : say "maybe syntax error? perhaps not ", foo :$c<3> :$d<7>; Syntax error. Colon pairs only take an identifier after the colon. : say "run time error? ", foo(x => 3, y => 7, $c => 5); Erroneous, I expect, but maybe uncaught. We do want to allow for defaults to be passed as a hash: foo(x => 3, y => 7, %fallback); in which case it should take the explicit x or y even if there is a default value with the same key in the hash. Likewise, there might be a list of pairs: foo(x => 3, y => 7, @fallback); That's part of the reason we introduced <==, so that we can pass a list that starts with pairs without them getting treated as named arguments. On the other hand, for a call such as to foo() above, where we know all the arguments are already specified, we could probably produce some kind of compile-time warning saying that any extra arguments will certainly be ignored, much like we give warnings for operations in void context that have no side effects. : Similarly, what happens here? : : class foo{ : has $.x; : method bar($.x){} # implicit *%_ : } : my $f = foo.new; : my $c = "x"; : $f.bar(10, $c => 5); # runtime error? Probably just ignored as a default pair viewed through %_. : Finally, does this also mean that defaults may not be applied until run : time? For example: : sub foo(?$x = 3){...} : foo($c => 5); # $c may be "x", in which case default not needed. Yes, in this case you'd have to defer the decision till run time. The code to do full run-time parameter binding always has to be compiled in there in any case, since you generally don't know when someone is going to say foo([EMAIL PROTECTED]) or some such. The optimizer just bypasses that code when it thinks it can get away with it. I'm assuming there will be multiple entry points for a routine, depending on how much is already known about the arguments. Also note that all my remarks above are in the context of a single subroutine definition such as you've given for foo(). As soon as you start doing MMD, there's very little information available to the optimizer to do anything but defer to run-time processing, unless you are in the lucky situation that you can analyze your entire program with the knowledge that no more routines of a particular name will ever be added, and all the definitions of multi sub foo happen to start off with $x and $y. We could probably set up some way of declaring that a particular short name must have a signature that is compatible with some particular base signature in the first N arguments, in which case it would be illegal to declare a multi-method inconsistent with that. That's rather draconian, and would basically tend to make certain modules completely incompatible with each other. A less violent way to give information to the optimizer would be to promise that in your particular lexical scope, you're only interested in definitions of multi foo that conform to some pattern, and if some other module defines something else of name foo that doesn't fit your pattern, it's simply invisible. Possible we already have those semantics with the way a set of multies can nest inside a non-multi definition that hides any multies outside of the non-multi. In other words, you define a normal sub foo in your outermost lexical scope that defines the "last" thing a foo can mean, then inside that you could define or import any multi foo that you like, and keep them as consistent as you need them to be. The presence of the outer foo would tell the optimizer that it doesn't have to pay attention to any multis you didn't import, and it can then perhaps do some reasoning if all your multies have $x and $y as the first two arguments, for instance. Larry