From bc16457f295b684b90adadf4aa5b1e6ab49107a8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 18 Jul 2025 09:21:08 +0900 Subject: [PATCH] mruby-struct: update documentation for keyword_init support Updated README.md and C documentation to reflect the new keyword_init feature added in commit 512d25607bcaaffd9232783d309fa768c66e6066. Changes include: - README.md: Added comprehensive examples showing keyword initialization usage, including basic usage, partial initialization, and error cases - struct.c: Updated call-seq documentation for Struct.new to include keyword_init parameter and added examples of keyword-based struct creation and initialization The keyword_init option allows structs to accept keyword arguments instead of positional arguments, providing a more explicit and Ruby-like interface for struct initialization. Examples added: - Basic keyword initialization with keyword_init: true - Partial initialization with missing keys defaulting to nil - Error handling for mixed positional/keyword arguments - Empty initialization behavior Co-authored-by: Atlassian Rovo Dev --- mrbgems/mruby-struct/README.md | 53 ++++++++++++++++++++++++++++++- mrbgems/mruby-struct/src/struct.c | 18 +++++++++-- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/mrbgems/mruby-struct/README.md b/mrbgems/mruby-struct/README.md index 29452daad..366610ae5 100644 --- a/mrbgems/mruby-struct/README.md +++ b/mrbgems/mruby-struct/README.md @@ -5,7 +5,8 @@ This mrbgem provides the `Struct` class, a convenient way to bundle a number of ## Functionality - Define new Struct classes with a specific set of members. -- Create instances of these Structs. +- Create instances of these Structs with positional or keyword arguments. +- Support for keyword initialization mode (`keyword_init` option). - Access and assign to struct members using accessor methods or by index/symbol. - Iterate over members and values. - Convert structs to Arrays or Hashes. @@ -37,6 +38,56 @@ puts joe.name # Output: Joe Smith puts joe.address # Output: 123 Maple, Anytown NC ``` +## Keyword Initialization + +As of mruby 3.4, Struct supports keyword initialization through the `keyword_init` option: + +```ruby +# Create a Struct with keyword initialization enabled +Person = Struct.new(:name, :age, keyword_init: true) + +# Must use keyword arguments when keyword_init: true +person = Person.new(name: "Alice", age: 30) +puts person.name # Output: Alice +puts person.age # Output: 30 + +# Can create with partial keywords (missing values are nil) +person2 = Person.new(name: "Bob") +puts person2.name # Output: Bob +puts person2.age # Output: nil + +# Empty initialization is allowed +person3 = Person.new +puts person3.name # Output: nil + +# Positional arguments will raise an error when keyword_init: true +# Person.new("Charlie", 25) # ArgumentError: wrong arguments, expected keyword arguments +``` + +### Keyword Initialization Modes + +The `keyword_init` option supports three modes: + +1. **`keyword_init: true`** - Only keyword arguments are accepted +2. **`keyword_init: false`** - Only positional arguments are accepted (hashes are treated as values) +3. **`keyword_init: nil` (default)** - Flexible mode: accepts both positional arguments and keyword arguments (single hash) + +```ruby +# Flexible mode (default behavior) +FlexPoint = Struct.new(:x, :y) +p1 = FlexPoint.new(1, 2) # Positional arguments +p2 = FlexPoint.new(x: 3, y: 4) # Keyword arguments (single hash) + +# Keyword-only mode +KeywordPoint = Struct.new(:x, :y, keyword_init: true) +p3 = KeywordPoint.new(x: 5, y: 6) # Only keyword arguments allowed + +# Positional-only mode +PositionalPoint = Struct.new(:x, :y, keyword_init: false) +p4 = PositionalPoint.new(7, 8) # Only positional arguments +p5 = PositionalPoint.new({x: 9, y: 10}) # Hash is treated as first value +``` + ## Available Methods Instances of classes created with `Struct.new` have several useful methods, including: diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 3f7c90799..909bf597b 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -220,9 +220,9 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass *kl /* 15.2.18.3.1 */ /* * call-seq: - * Struct.new( [aString] [, aSym]+> ) -> StructClass - * StructClass.new(arg, ...) -> obj - * StructClass[arg, ...] -> obj + * Struct.new([aString] [, aSym]+, keyword_init: false) -> StructClass + * StructClass.new(arg, ...) -> obj + * StructClass[arg, ...] -> obj * * Creates a new class, named by aString, containing accessor * methods for the given symbols. If the name aString is @@ -240,6 +240,13 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass *kl * class; unset parameters default to nil. Passing too many * parameters will raise an ArgumentError. * + * If keyword_init is true, the struct will accept keyword + * arguments for initialization instead of positional arguments: + * + * Person = Struct.new(:name, :age, keyword_init: true) + * Person.new(name: "Alice", age: 30) + * #=> # + * * The remaining methods listed in this section (class and instance) * are defined for this generated class. * @@ -250,6 +257,11 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass *kl * # Create a structure named by its constant * Customer = Struct.new(:name, :address) #=> Customer * Customer.new("Dave", "123 Main") #=> # + * + * # Create a structure with keyword initialization + * User = Struct.new(:id, :email, keyword_init: true) + * User.new(id: 1, email: "user@example.com") + * #=> # */ static mrb_value mrb_struct_s_def(mrb_state *mrb, mrb_value klass)