mruby-struct: update documentation for keyword_init support

Updated README.md and C documentation to reflect the new keyword_init
feature added in commit 512d25607b.

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
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-07-18 09:21:08 +09:00
parent 0fcfa7677d
commit bc16457f29
2 changed files with 67 additions and 4 deletions
+52 -1
View File
@@ -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:
+15 -3
View File
@@ -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 <i>aString</i>, containing accessor
* methods for the given symbols. If the name <i>aString</i> is
@@ -240,6 +240,13 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass *kl
* class; unset parameters default to <code>nil</code>. Passing too many
* parameters will raise an <code>ArgumentError</code>.
*
* If <code>keyword_init</code> 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)
* #=> #<struct Person 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") #=> #<struct Customer name="Dave", address="123 Main">
*
* # Create a structure with keyword initialization
* User = Struct.new(:id, :email, keyword_init: true)
* User.new(id: 1, email: "user@example.com")
* #=> #<struct User id=1, email="user@example.com">
*/
static mrb_value
mrb_struct_s_def(mrb_state *mrb, mrb_value klass)