(asking because a test testing for the converse was just checked in to
the Pugs repository [1])
sub foo ($n, *%rest) {...}
foo 13;
# $n receives 13, of course, %rest is ()
foo 13, foo => "bar";
# $n receives 13 again, %rest is (foo => "bar")
foo n => 13;
# $n receives 13, %rest is (), right?
foo n => 13, foo => "bar";
# $n receives 13, %rest is (foo => "bar"), right?
--Ingo
[1] http://svn.openfoundry.org/pugs/t/subroutines/slurpy_param.t
--
Linux, the choice of a GNU | Row, row, row your bits, gently down the
generation on a dual AMD | stream...
Athlon! |
Yep, that's all correct. Matter of fact, what %rest actually gets has
not been defined. "Maybe %rest mirrors all the named arguments, maybe
it doesn't". I can see a very small utility if it does, but it seems
like it would be faster[1] if it didn't. I think it's fair to say no
here.
[1] Yeah, yeah, premature optimization and whatnot. You always have
the sig (*%hash) if you really want to.
Luke
The Apocalypse explicitly left the question open because of the
performance issue, since we might be forced into copying all the
entries of a potentially huge hash just to weed out a few entries.
(Think environment variables.)
You can't just mark certain entries as unavailable since it's probably
a reference to someone else's hash. You could set up a proxying
filter hash that makes some of the keys vanish, but then you're at
the mercy of the owner of the real hash not to change the proxied
hash while your function is executing, and there's some overhead in
setting up the proxy hash. It's possible that COW hashes can be made
to work efficiently. We'll need to copy hashes if we want to modify
them to pass to subfunctions, just as when you change your environment
it doesn't affect your parent process's environment variables.
Actually, I envision the named arguments coming in as a separate list
of pairs and hash refs, so we could just say that all readonly access
to the slurpy hash actually scans that argument list. That assumes
that we don't care that much about the efficiency of "environmental"
lookups, but I think it might optimize for the common case of argument
binding if we process positionals in order and do scanning lookups in
the named list for missing positionals. Doing your primary scan on
the named list to look for things that might or might not be wanted
in the positional list is going to be really slow in cases where a
lot of "environment" is passed around.
Anyway, what I'm saying is that, assuming we bind the slurpy hash
interface to the list implementation, we could just put "nulling"
entries on the front of that list as we use up keys. So maybe that's
a way to remove keys that's not too much overhead. I suppose we could
even suppress that if there was a pragma allowing dups. So there's
something to be said for the cleaner semantics.
On the other hand, maybe those semantics are not actually cleaner.
If we take environment variables as our model, we *don't* remove
them from the environment when we "use" them, since child processes
may want the same value. If we weed out values from the slurpy
hash, we force environmental hashes to be passed some other way.
Whether that's a feature or not depends on whether you view such an
"environment" as default values for named parameter bindings.
Larry
> setting up the proxy hash. It's possible that COW hashes can be made
> to work efficiently. We'll need to copy hashes if we want to modify
> them to pass to subfunctions, just as when you change your environment
> it doesn't affect your parent process's environment variables.
I would assume that for parrot, with vtables, a "simple" COW hash would be
very efficient. By simple, I mean one that does a complete copy and separation
the first time someone tries to write to one of the "copies", rather than the
more complex concept of maintaining state on partial copies.
My hunch would be that a "simple" system of COW plus an overlay hash would
work very well for the case of adding to (or deleting from) a hash passed in
as default arguments, because 95% of the time that hash is only directly
manipulated by functions back up the call frame, so for the duration of the
call would be unchanged.
But this is all arm-wavy, and needs real code to analyse before committing
to it as a strategy.
Nicholas Clark