[ruby-core:120445] [Ruby master Feature#20993] Allow `class <constant-path> = <expression>` syntax

Issue #20993 has been reported by byroot (Jean Boussier). ---------------------------------------- Feature #20993: Allow `class <constant-path> = <expression>` syntax https://bugs.ruby-lang.org/issues/20993 * Author: byroot (Jean Boussier) * Status: Open ---------------------------------------- This is meant as a solution for: https://bugs.ruby-lang.org/issues/20943 ## Context When using `Struct.new` or `Data.define`, you often see one of these patterns: ```ruby class MyStruct < Struct.new(:foo, :bar) # ... end ``` Or: ```ruby MyStruct = Struct.new(:foo, :bar) do # ... end ``` The first one is OK, but not ideal because `MyStruct` inherits from an anonymous class. That's not that big of a deal, but it's an extra, generally useless class: ```ruby
MyClass.ancestors => [MyClass, #<Class:0x000000012a811548>, Struct, ...]
The second one is OK too, but can lead to two mistakes.
First, since it doesn't create a nesting, if you assign a constant, it won't be set where you expect it.
```ruby
MyStruct = Struct.new(:foo) do
BAR = 1 # This sets Object::BAR, not MyStruct::BAR
end
The second potential issue is that the class only get named after the block complete, so some `inherited` or `included` hooks that rely on the class name may break. ## Proposal The "ideal" way to define a `Struct` or `Data` would be: ```ruby MyStruct = Struct.new(:foo, :bar) class MyStruct # body end ``` But it's a bit awkward. Given that `class <constant-path> < <expression>` is valid, this makes me think we could also accept `class <constant-path> = <expression>` such as: ```ruby class MyStruct = Struct.new(:foo, :bar) # body end ``` Would be valid syntax and the recommended way to define `Struct` and `Data` classes. Of course `module <constant-path> = <expression>` would be valid as well. If the expression doesn't return the expected type (either `Class` or `Module`), it would raise a `TypeError`. -- https://bugs.ruby-lang.org/

Issue #20993 has been updated by nobu (Nobuyoshi Nakada). File feature-20993.diff added ```ruby class MyStruct = Struct.new(:foo, :bar) p instance_methods(false) #=> [:foo=, :bar=, :foo, :bar] end ``` ---------------------------------------- Feature #20993: Allow `class <constant-path> = <expression>` syntax https://bugs.ruby-lang.org/issues/20993#change-111227 * Author: byroot (Jean Boussier) * Status: Open ---------------------------------------- This is meant as a solution for: https://bugs.ruby-lang.org/issues/20943 ## Context When using `Struct.new` or `Data.define`, you often see one of these patterns: ```ruby class MyStruct < Struct.new(:foo, :bar) # ... end ``` Or: ```ruby MyStruct = Struct.new(:foo, :bar) do # ... end ``` The first one is OK, but not ideal because `MyStruct` inherits from an anonymous class. That's not that big of a deal, but it's an extra, generally useless class: ```ruby
MyClass.ancestors => [MyClass, #<Class:0x000000012a811548>, Struct, ...]
The second one is OK too, but can lead to two mistakes.
First, since it doesn't create a nesting, if you assign a constant, it won't be set where you expect it.
```ruby
MyStruct = Struct.new(:foo) do
BAR = 1 # This sets Object::BAR, not MyStruct::BAR
end
The second potential issue is that the class only get named after the block complete, so some `inherited` or `included` hooks that rely on the class name may break. ## Proposal The "ideal" way to define a `Struct` or `Data` would be: ```ruby MyStruct = Struct.new(:foo, :bar) class MyStruct # body end ``` But it's a bit awkward. Given that `class <constant-path> < <expression>` is valid, this makes me think we could also accept `class <constant-path> = <expression>` such as: ```ruby class MyStruct = Struct.new(:foo, :bar) # body end ``` Would be valid syntax and the recommended way to define `Struct` and `Data` classes. Of course `module <constant-path> = <expression>` would be valid as well. If the expression doesn't return the expected type (either `Class` or `Module`), it would raise a `TypeError`. ---Files-------------------------------- feature-20993.diff (3.51 KB) -- https://bugs.ruby-lang.org/

Issue #20993 has been updated by matz (Yukihiro Matsumoto). Status changed from Open to Rejected This is a too trivial issue to add new syntax. I suggest the following (I know the difference, but it works OK, doesn't it?) ```ruby MyStruct = Struct.new(:foo, :bar) class MyStruct ... end # or class MyStruct < Struct.new(:foo, :bar) ... end ```` Matz. ---------------------------------------- Feature #20993: Allow `class <constant-path> = <expression>` syntax https://bugs.ruby-lang.org/issues/20993#change-111380 * Author: byroot (Jean Boussier) * Status: Rejected ---------------------------------------- This is meant as a solution for: https://bugs.ruby-lang.org/issues/20943 ## Context When using `Struct.new` or `Data.define`, you often see one of these patterns: ```ruby class MyStruct < Struct.new(:foo, :bar) # ... end ``` Or: ```ruby MyStruct = Struct.new(:foo, :bar) do # ... end ``` The first one is OK, but not ideal because `MyStruct` inherits from an anonymous class. That's not that big of a deal, but it's an extra, generally useless class: ```ruby
MyClass.ancestors => [MyClass, #<Class:0x000000012a811548>, Struct, ...]
The second one is OK too, but can lead to two mistakes.
First, since it doesn't create a nesting, if you assign a constant, it won't be set where you expect it.
```ruby
MyStruct = Struct.new(:foo) do
BAR = 1 # This sets Object::BAR, not MyStruct::BAR
end
The second potential issue is that the class only get named after the block complete, so some `inherited` or `included` hooks that rely on the class name may break. ## Proposal The "ideal" way to define a `Struct` or `Data` would be: ```ruby MyStruct = Struct.new(:foo, :bar) class MyStruct # body end ``` But it's a bit awkward. Given that `class <constant-path> < <expression>` is valid, this makes me think we could also accept `class <constant-path> = <expression>` such as: ```ruby class MyStruct = Struct.new(:foo, :bar) # body end ``` Would be valid syntax and the recommended way to define `Struct` and `Data` classes. Of course `module <constant-path> = <expression>` would be valid as well. If the expression doesn't return the expected type (either `Class` or `Module`), it would raise a `TypeError`. ---Files-------------------------------- feature-20993.diff (3.51 KB) -- https://bugs.ruby-lang.org/
participants (3)
-
byroot (Jean Boussier)
-
matz (Yukihiro Matsumoto)
-
nobu (Nobuyoshi Nakada)