Project

General

Profile

Actions

Feature #20993

closed

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

Feature #20993: Allow `class <constant-path> = <expression>` syntax
1

Added by byroot (Jean Boussier) almost 2 years ago. Updated almost 2 years ago.

Status:
Rejected
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 2 (1 open — 1 closed)

Related to Ruby - Bug #20943: Constant defined in `Data.define` blockOpenActions
Has duplicate Ruby - Feature #22404: Make Data (and/or Struct, etc.) true "first-class citizens" and thank you!ClosedActions

Updated by byroot (Jean Boussier) almost 2 years ago Actions #1

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

Updated by nobu (Nobuyoshi Nakada) almost 2 years ago 1Actions #2 [ruby-core:120447]

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

Updated by matz (Yukihiro Matsumoto) almost 2 years ago Actions #3 [ruby-core:120562]

  • 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?)

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

# or

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

Matz.

Updated by mame (Yusuke Endoh) 5 days ago Actions #4

  • Has duplicate Feature #22404: Make Data (and/or Struct, etc.) true "first-class citizens" and thank you! added
Actions

Also available in: PDF Atom