Feature #11925
closedStruct construction with kwargs
Description
Propose to make Struct subclass constructors which accept keyword arguments. Not sure, if it's reasonable to allow .new
accept kwargs, so may be should use different method named like .create
:
Point = Struct.new(:x,:y, :color)
pt_1 = Point.create(x: 1, y: 2) # => Point<x: 1, y: 2, color: nil>
pt_2 = Point.create!(x: 1, y: 2) # => ArgumentError, color not specified.
It will greatly simplify work with big structures, especially in cases when struct layout changes and for cases when structure can have lots of non-significant values. It also allows simpler ways to use implement default values for struct members.
Updated by ksss (Yuki Kurihara) almost 9 years ago
Hi.
I have thought the same thing that want to use kwargs in Struct class.
But I can't come up with a good API.
Finally, I made a gem. https://github.com/ksss/type_struct
Updated by shyouhei (Shyouhei Urabe) over 8 years ago
We looked at this issue in yesterday's developer meeting. Nobody there was against the functionality -- but the name. create!
doesn't sound appropriate at all. create
also not that obvious for non-English speakers like us that it expects keywords.
Updated by herwinw (Herwin Quarantainenet) almost 8 years ago
What about new_from_kwargs(**kwargs)
? It's a bit long, but it describes the functionality exactly.
Updated by herwin (Herwin W) almost 8 years ago
https://github.com/ruby/ruby/pull/1468
A proposal for an implementation.
irb(main):001:0> MyClass = Struct.new(:a, :b, :c)
=> MyClass
irb(main):002:0> MyClass.new_from_kwargs(a:1, c: 3)
=> #<struct MyClass a=1, b=nil, c=3>
irb(main):003:0> MyClass.new_from_kwargs(1, 2, 3, b: 3)
=> #<struct MyClass a=1, b=3, c=3>
irb(main):004:0> MyClass.new_from_kwargs(d: 4)
NameError: no member 'd' in struct
from (irb):4:in `new_from_kwargs'
from (irb):4
from ./irb:11:in `<main>'
irb(main):005:0> MyClass.new_from_kwargs(1, 2, 4, 5, b: 3)
IndexError: offset 3 too large for struct(size:3)
from (irb):5:in `new_from_kwargs'
from (irb):5
from ./irb:11:in `<main>'
irb(main):006:0>
Updated by nobu (Nobuyoshi Nakada) almost 8 years ago
Herwin W wrote:
irb(main):003:0> MyClass.new_from_kwargs(1, 2, 3, b: 3) => #<struct MyClass a=1, b=3, c=3>
Why does new_from_kwargs
accept other than keyword arguments?
Updated by herwin (Herwin W) almost 8 years ago
To be prepared for "the great unification of constructors" of course.
It looked like a pretty logical step to support while I was coding this. It's also pretty easy to remove again
Updated by shyouhei (Shyouhei Urabe) almost 8 years ago
- Has duplicate Feature #9209: Struct instances creatable with named args added
Updated by ko1 (Koichi Sasada) over 7 years ago
Another idea is introducing another method to define own struct, such as T = Struct.define(:a, :b); T.new(a: 1, b: 2)
and so on.
(just idea) Moreover we can extend Struct with some properties, like: Struct.define(:a, b: :read_only)
.
These ideas are provided by another person.
Updated by nobu (Nobuyoshi Nakada) over 7 years ago
- Has duplicate Feature #13272: Keyword argument to instantiate a subclass of Struct added
Updated by k0kubun (Takashi Kokubun) almost 7 years ago
Similar to one commented by ko1, how about this interface?
T = Struct.new(:a, :b, keyword_argument: true)
T.new(a: 1, b: 2)
As keyword_argument
is long, another option is:
Struct.new(:a, :b, keyword_args: true)
Updated by k0kubun (Takashi Kokubun) almost 7 years ago
In case that my suggestion of the name is accepted, I wrote a patch for Struct.new(:a, :b, keyword_args: true).
https://github.com/ruby/ruby/pull/1771
Updated by knu (Akinori MUSHA) almost 7 years ago
What if Struct.new([:a, :b])
created a class with the desired constructor?
Updated by matz (Yukihiro Matsumoto) almost 7 years ago
I vote for the keyword argument (e.g. keyword_init:
) to Struct#new
.
Matz.
Updated by herwin (Herwin W) almost 7 years ago
knu (Akinori MUSHA) wrote:
What if
Struct.new([:a, :b])
created a class with the desired constructor?
If you'd compare the two possible constructors:
Struct.new(:a, :b)
Struct.new([:a, :b])
There is nothing in the second one that would indicate the second creates a keyword constructor. If I hadn't read this discussion, I would just expect them to behave the same.
Updated by k0kubun (Takashi Kokubun) almost 7 years ago
- Status changed from Open to Closed
Applied in changeset trunk|r61137.
struct.c: add keyword_init option to Struct.new
to initialize struct with keyword arguments.
[Feature #11925] [close GH-1771]
Updated by k0kubun (Takashi Kokubun) almost 7 years ago
As Matz approved, I committed only keyword_init option which is equivalent to "Point.create(x: 1, y: 2)" in original suggestion. If you still want "Point.create!" version which raises ArgumentError (keyword_init initializes unspecified fields with nil), please file another ticket.
Updated by nobu (Nobuyoshi Nakada) about 6 years ago
- Related to Feature #15076: Struct to raise error when keyword arguments used but not enabled added
Updated by k0kubun (Takashi Kokubun) about 6 years ago
- Related to Feature #15222: Add a way to distinguish between Struct classes with and without keyword initializer added
Updated by k0kubun (Takashi Kokubun) over 4 years ago
- Related to Feature #16806: Struct#initialize accepts keyword arguments too by default added