Project

General

Profile

Actions

Feature #20993

open

Allow `class <constant-path> = <expression>` syntax

Added by byroot (Jean Boussier) 5 days ago. Updated 5 days ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:120445]

Description

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:

class MyStruct < Struct.new(:foo, :bar)
  # ...
end

Or:

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:

>> 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.

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:

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:

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) feature-20993.diff nobu (Nobuyoshi Nakada), 12/30/2024 01:04 PM

Related issues 1 (1 open0 closed)

Related to Ruby master - Bug #20943: Constant defined in `Data.define` blockOpenActions
Actions #1

Updated by byroot (Jean Boussier) 5 days ago

  • Related to Bug #20943: Constant defined in `Data.define` block added

Updated by nobu (Nobuyoshi Nakada) 5 days ago

class MyStruct = Struct.new(:foo, :bar)
  p instance_methods(false) #=> [:foo=, :bar=, :foo, :bar]
end
Actions

Also available in: Atom PDF

Like0
Like0Like0