From: "mame (Yusuke Endoh)" Date: 2012-04-24T22:01:37+09:00 Subject: [ruby-core:44590] [ruby-trunk - Feature #5474][Closed] keyword argument Issue #5474 has been updated by mame (Yusuke Endoh). Status changed from Assigned to Closed Sorry for leaving this ticket for a long time. Nobu improved the implementation of keyword argument. Let's check the current situation. And then, I'd like to file tickets for each remaining issues, and close this ticket. Please let me know if I miss something. ## ** with no keyword [ruby-core:40518] [ruby-core:41772] The following DOES work currently. Thanks nobu! def foo(x, **h) p [x, h] end foo(1) #=> [1, {}] foo(1, key: 42) #=> [1, {key: 42}] foo(1, 2) #=> wrong number of arguments (2 for 1) ## Method#parameters with keyword argument [ruby-core:40518] The following DOES work currently. def foo(k1: 42, k2: 42, **kr) end p method(:foo).parameters #=> [[:key, :k1], [:key, :k2], [:keyrest, :kr]] ## caller-side ** [ruby-core:40518] The following does NOT work. h = {x: 42} foo(**h) Unfortunately, it is not trivial for me to implement. I'll explain the detail in a separate ticket. ## alternative syntax proposal As far as I know, there is no proposal that matz approved. It looks difficult to me to change the syntax, because matz seems to like "**" very much. [ruby-core:41822] ## Marc-Andre's hash decomposition [ruby-core:41772] Unfortunately, matz is not so positive. [ruby-core:41822] ## ArgumentError message related to keyword argument Currently, "unknown keyword" error shows which keyword is missing: def a(k: 42) end a(foo: 42) # => unknown keyword: foo (ArgumentError) There is another proposal about "wrong number of arguments" error. See: http://bugs.ruby-lang.org/issues/6086 ## changing stdlib API to use keyword arguments [ruby-core:42037] I think we should progress it, without breaking compatibility. But currently, I don't know which API is the target. Please file a ticket if you find such an API. -- Yusuke Endoh ---------------------------------------- Feature #5474: keyword argument https://bugs.ruby-lang.org/issues/5474#change-26163 Author: mame (Yusuke Endoh) Status: Closed Priority: Normal Assignee: mame (Yusuke Endoh) Category: core Target version: 2.0.0 Hello, I'm sending a patch for keyword arguments. (This feature had been discussed in #5454, but I'm re-creating a new ticket because the old ticket was resigtered in ruby-dev) Matz himself proposed this feature. It is also basically promised to include the feature in 2.0. [ruby-core:39837] I'm planning to commit the patch after it is reviewed by koichi. But the detail of the spec is not fixed yet, and may be changed drastically. We would like to hear your comments and suggestions, especially, with a use case and/or an actual experience. The background of this proposal is that, in the recent Ruby, the last argument (as a Hash) is often used to pass optional information. This feature is intended to aid the style. Look an example: def create_point(x, y, color: "white", size: 1) # keyword arguments ^^^^^^^^^^^^^^^^^^^^^^^ here! p [x, y, color, size] end create_point(2, 3, color: "red") #=> [2, 3, "red", 1] The caller size is a traditional hash argument notation. This feature is Hash parsing in the callee side. (So it is more suitable to call it "keyword parameter." But I use "keyword argument" because everyone calls so.) We can implement the similar behavior in pure Ruby. However, this feature is easier to read/write, and richer in the some aspects: - it raises an TypeError when unknown keyword is given create_point(2, 3, style: "solid") #=> unknown keyword (TypeError) - you can use ** argument to suppress the TypeError and/or to get the given hash itself: def create_point(x, y, color: "white", size: 1, **h) p [x, y, color, size, h] end create_point(2, 3, style: "solid") #=> [2, 3, "red", 1, {:style=>"solid"}] - it is easily used even when there is a rest argument def create_point(x, y, *r, color: "solid", size: 1) ... end (a complex and non-essential code is required to implement the same behavior in pure Ruby) - there is room for optimizing the speed (though I have not done any optimization yet) An alternative design is to treat all parameters as keyword arguments (as Evan said in [ruby-core:40195]). def create_point(x, y, color = "white", size = 1) p [x, y, color, size] end create_point(color: "red", x: 2, y: 3) #=> [2, 3, "red", 1] Actually I also like this, but I'm afraid if it is too flexible and seems difficult to implement and optimize. Thanks, -- Yusuke Endoh -- http://bugs.ruby-lang.org/