--- Yukihiro Matsumoto said:
Hi,
=20
In message "Re: A comparison by example of keyword argument
styles"
on Mon, 24 Oct 2005 05:50:39 +0900, Eric Mahurin
=20
|What use is it to have the named arguments appear twice? I
|understand the need if you don't have named arguments in the
|definition (compatibility), but as soon as named arguments
are
|specified, it seems to serve no purpose.
=20
It's for method delegation. Currently we do=20
=20
def foo(*args)
bar(*args)
end
=20
for method delegation.
To do the full delegation right now you really need:
def foo(*args, &block)
bar(*args, &block)
end
Under my proposal, this delegation
would still
work fine, since we have named arguments appear twice,
otherwise we
must change the code as
=20
def foo(*args, **keys)
bar(*args, **keys)
end
=20
everywhere, to just do delegation.
or rather:
def foo(*args, **keys, &block)
bar(*args, **keys, &block)
end
What's wrong with having to do that? The old delegation would
be able to delegate to any of the old non-named argument method
definitions. Existing code would not break. Only when you
start using new named arguments in your method definitions
would you have to fix the delegation methods.
I think you need to choose whether you want separation between
named and positional arguments (like lisp and command-line
options/args) or not (like python/sydney). And go with it.=20
Having named arguments appear in the positional *args does not
show good separation - what you want I think.
|Also, like we have array splatting when you call a method, I
|think hash splatting would also be useful. matz said that
|hashes would be automatically splatted if they were the last
|argument, but this results in ambiguity:
|
|def foo(a,b=3D{},c:2,**keys) ... end
|
|foo("a",{:x =3D> 1,:y =3D> 2})
|
|Does the above result in:
|
|a =3D "a", b =3D {:x =3D> 1,:y =3D> 2}, c =3D 2, keys =3D {}
|
|or:
|
|a =3D "a", b =3D {}, c =3D 2, keys =3D {:x =3D> 1,:y =3D> 2}
=20
The former. Keyword argument uses the last remaining hash.
This contradicts what you said above about method delegation.=20
If we had this delegation with the above foo:
def bar(*args)
foo(*args)
end
bar("a", x: 1, y: 2)
# bar: args =3D ["a",{:x =3D> 1, :y =3D> 2}]
# foo: a =3D "a", b =3D {:x =3D> 1,:y =3D> 2}, c =3D 2, keys =3D {}
That's not what you wanted for delegating. It should be:
foo: a =3D "a", b =3D {}, c =3D 2, keys =3D {:x =3D> 1,:y =3D> 2}
But then if you choose that, you have no way of passing a hash
to the last positional argument and giving no named arguments
(assuming they all have defaults).
I think with named arguments you should not give special
meaning to Hash or you'll run into the same problems you had
with multiple-value returns and assignments that you had with
Array. Explicitly splatting/unsplatting a Hash for named
arguments makes sense, but I don't think you should tie Hash as
part of the definition of named arguments.
|I'm hoping that we have enough reflection for these named
|arguments like #arity. I'm thinking that with named
arguments=20
|a potential simple application would be as a spec for
handling
|command-line options (named arguments). I'd like to see all
of
|the keywords and defaults accessible from Proc/Method
objects.=20
|It'd be nice to have access to defaults of positional args
|while wer'e asking.
=20
Accepting keywords should be obtained from some kind of
reflection
API, although the API is not fixed yet. But I'm not sure
default
values can be accessed since they are arbitrary expression,
and we
have no good way to represent pre-evaluated expression in
Ruby (unlike
in Lisp, where we can use S expression).
Sorry, I forgot that defaults can be expressions. I guess you
could have something that just says whether an arg (positional
or named) has a default or not. Another option is to be able
to access the default as a Proc. To evaluate the default,
you'd just #call it like any other Proc.
|Since Ruby 2 will also be completely redoing how
|multiple-values are handled, why not also consider being
able
|to name your return values? If a method returns a bunch of
|attributes, it would be nice for the caller to be able to
pick
|what they want.
=20
I have no good idea of multiple value binding for named
values
(i.e. syntax). Do you?
=20
matz.
Actually, I do. If you put the ability to handle named
arguments in a multi-assign, you'll have it. The LHS would
look like argument definitions in a def (except defaults aren't
allowed) and the RHS (or return) would look like a method call.
The problem is that this will force the named argument to be
put in a variable of the same name when assigning to the LHS.=20
To fix this problem, I propose that you be allowed to specify a
different local variable name for a named argument in a method
definition or LHS:
def foo(
a, # position: 0, local var: a, required
b=3D"b", # position: 1, local var: b, default: "b"
*args, # position: 2..-1, local var: args=20
w:, # name: w, local var: w, required
x:c, # name: x, local var: c, required
y:=3D"y", # name: y, local var: y, default: "y"
z:d=3D"z",# name: z, local var: d, default: "z"
**keys) # name: others, local var: keys
....
# maybe w: could be made equivalent to w:w
return a,b,*args,w:w,x:c,y:y,z:d,**keys
end
# only care about pos:0 and name:x - throw out the rest
aa,x:xx =3D foo(0,1,2,w:3,x:4,m:5)
Like you allow discarded positional args ("_"), you could also
allow discarded named args (name:_[=3Ddefault]). And "**" like
"*" could mean accept any other keys but throw them out.
BTW, I'd still like to see the ability to specify required
positional args after the *args and/or default positional args.
I see no reason why any of this named argument stuff would
conflict with this (RCR 315).
=09
__________________________________=20
Yahoo! FareChase: Search multiple travel sites in one click.
http://farechase.yahoo.com