--- Yukihiro Matsumoto <matz / ruby-lang.org> wrote: > Hi, > > In message "Re: A comparison by example of keyword argument > styles" > on Mon, 24 Oct 2005 05:50:39 +0900, Eric Mahurin > <eric_mahurin / yahoo.com> writes: > > |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. > > It's for method delegation. Currently we do > > def foo(*args) > bar(*args) > end > > 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 > > def foo(*args, **keys) > bar(*args, **keys) > end > > 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. 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={},c:2,**keys) ... end > | > |foo("a",{:x => 1,:y => 2}) > | > |Does the above result in: > | > |a = "a", b = {:x => 1,:y => 2}, c = 2, keys = {} > | > |or: > | > |a = "a", b = {}, c = 2, keys = {:x => 1,:y => 2} > > The former. Keyword argument uses the last remaining hash. This contradicts what you said above about method delegation. If we had this delegation with the above foo: def bar(*args) foo(*args) end bar("a", x: 1, y: 2) # bar: args = ["a",{:x => 1, :y => 2}] # foo: a = "a", b = {:x => 1,:y => 2}, c = 2, keys = {} That's not what you wanted for delegating. It should be: foo: a = "a", b = {}, c = 2, keys = {:x => 1,:y => 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 > |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. > |It'd be nice to have access to defaults of positional args > |while wer'e asking. > > 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. > > I have no good idea of multiple value binding for named > values > (i.e. syntax). Do you? > > 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. 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="b", # position: 1, local var: b, default: "b" *args, # position: 2..-1, local var: args w:, # name: w, local var: w, required x:c, # name: x, local var: c, required y:="y", # name: y, local var: y, default: "y" z:d="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 = foo(0,1,2,w:3,x:4,m:5) Like you allow discarded positional args ("_"), you could also allow discarded named args (name:_[=default]). 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). __________________________________ Yahoo! FareChase: Search multiple travel sites in one click. http://farechase.yahoo.com