Project

General

Profile

Actions

Feature #11925

closed

Struct construction with kwargs

Added by prijutme4ty (Ilya Vorontsov) almost 9 years ago. Updated almost 7 years ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:72595]

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.


Related issues 5 (1 open4 closed)

Related to Ruby master - Feature #15076: Struct to raise error when keyword arguments used but not enabledRejectedActions
Related to Ruby master - Feature #15222: Add a way to distinguish between Struct classes with and without keyword initializerOpenActions
Related to Ruby master - Feature #16806: Struct#initialize accepts keyword arguments too by defaultClosedk0kubun (Takashi Kokubun)Actions
Has duplicate Ruby master - Feature #9209: Struct instances creatable with named argsClosedActions
Has duplicate Ruby master - Feature #13272: Keyword argument to instantiate a subclass of StructClosedActions

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

Actions #2

Updated by naruse (Yui NARUSE) over 8 years ago

  • Assignee deleted (core)

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) about 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) about 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) about 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) about 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

Actions #8

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) almost 8 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.

Actions #10

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.

Actions #16

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.

Actions #18

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
Actions #19

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
Actions #20

Updated by k0kubun (Takashi Kokubun) over 4 years ago

  • Related to Feature #16806: Struct#initialize accepts keyword arguments too by default added
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0