Issue #22404 has been updated by asoffa (Aaron Soffa). I investigated this a bit more this week. Consider the following: ```ruby D = Data.define(:x, :y) # *not* expecting a body d = Data.define(:x, :y) # *not* expecting a body def d = Data.define(:x, :y) # *not* expecting a body # vs. the original proposal class D = Data.define(:x, :y) # now expecting a body followed by `end` # ... end ``` In Ruby, the current `=` syntax universally denotes a one-liner unless what comes after the `=` specifies otherwise. The proposal for the `=` syntax for classes as described above would then break this universality, which would most likely be undesirable unless there is a very good reason for doing so. This is much less of an issue with `<` because `<` is used primarily for only two purposes: evaluating an ordering and specifying a superclass. (Consider that `<` can be defined as a method, whereas `=` cannot.) Part of my investigation included looking at alternatives to the `=` syntax in this context. My opinion now matches Matz's opinion above, though perhaps a future proposal will supersede all of these considerations. In any case, thinking of a `Data` (or `Struct`, etc.) class as specifying "just data" (with additional `class` functionality being opt-in via one of the approaches above) gives me total peace of mind with the current behavior. My preferred approach by default is e.g.: ```ruby # "Specify the data" D = Data.define :a, :b, :c, :d, :e, :f # "Then specify the class" if more enhanced functionality is needed/desired class D # Constants and methods here end ``` We reopen modules and classes when we split their definitions across files, so I think of "specifying the data" and "specifying the class" as using two (or more) different "files" (even if they're both in the same physical file). ---------------------------------------- Feature #22404: Make Data (and/or Struct, etc.) true "first-class citizens" and thank you! https://bugs.ruby-lang.org/issues/22404#change-119457 * Author: asoffa (Aaron Soffa) * Status: Closed ---------------------------------------- First of all, I would like to give a **huge** shoutout to the Ruby community for staying true to Ruby's mission of increasing developer productivity and thereby happiness and thereby enrichment of people's lives, especially mine in so many ways! THANK YOU! As a scientist (who likes data), I have ultimately so far discovered **only** this (relatively minor!) nitpick about the Ruby programming language: data/value objects are not "first-class citizens" for constants in the way that general modules and classes are. The current solution is to write something like ```ruby D = Data.define(:x, :y) do self::D_CONSTANT = 1 end ``` where the `self::` is required to keep `D_CONSTANT` in the scope of `D` here. Alternatively, we can write the following: ```ruby D = Data.define(:x, :y) class D D_CONSTANT = 1 end ``` which reopens the `D` class to keep `D_CONSTANT` scoped to `D` or otherwise ```ruby class D < Data.define(:x, :y) D_CONSTANT = 1 end ``` which creates an anonymous class (which is not generally desired). My proposal is for something like the following: ```ruby class D = Data.define(:x, :y) D_CONSTANT = 1 end ``` to avoid the above complications. This enhancement request may or may not make sense depending on how frequently `Data` (and/or `Struct`, etc.) are to be considered "first-class citizens" in Ruby. My thought is that the `=` in the class definition here very nicely dovetails with the `<` for creating subclasses and also with the relatively new `=` syntax now allowed for method definitions (e.g. `def f = 1`). This enhancement would be analogous to allowing upgrading ```ruby C = Class.new do self::C_CONSTANT = 1 end ``` to ```ruby class C C_CONSTANT = 1 end ``` for `Data`, `Struct`, etc. and would address the last points mentioned in [1]. [1] https://bugs.ruby-lang.org/issues/16122 -- https://bugs.ruby-lang.org/