Struct construction with kwargs
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
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 shyouhei (Shyouhei Urabe) over 4 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 herwin (Herwin W) almost 4 years ago
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 ko1 (Koichi Sasada) over 3 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 herwin (Herwin W) almost 3 years ago
knu (Akinori MUSHA) wrote:
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 3 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.