[ruby-core:126919] [Ruby Feature#22404] Make Data (and/or Struct, etc.) true "first-class citizens" and thank you!
Issue #22404 has been reported by asoffa (Aaron Soffa). ---------------------------------------- Feature #22404: Make Data (and/or Struct, etc.) true "first-class citizens" and thank you! https://bugs.ruby-lang.org/issues/22404 * Author: asoffa (Aaron Soffa) * Status: Open ---------------------------------------- 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/
Issue #22404 has been updated by matz (Yukihiro Matsumoto). Status changed from Open to Closed Thank you for the kind words. This is the same proposal as #20993, and my opinion has not changed. It is too small an issue to add new syntax for. Please use one of the existing forms you listed. Matz. ---------------------------------------- Feature #22404: Make Data (and/or Struct, etc.) true "first-class citizens" and thank you! https://bugs.ruby-lang.org/issues/22404#change-119363 * 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/
Issue #22404 has been updated by asoffa (Aaron Soffa). Just to document for possible future reference, here is a case for why the current behavior might even be a feature rather than an issue and why something like ```ruby class D = Data.define(:x, :y) # ... end ``` might *not* be desired: Classes defined via `Data.define` (or `Struct.new`, etc.) are "naturally" *simple* with no methods or constants beyond those specified by `Data` (or `Struct`, etc.), i.e. "just data." That said, if a more sophisticated class is desired, the options listed above are available. Thank you for the prompt response and for doing what you do! ---------------------------------------- Feature #22404: Make Data (and/or Struct, etc.) true "first-class citizens" and thank you! https://bugs.ruby-lang.org/issues/22404#change-119375 * 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/
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/
participants (2)
-
asoffa (Aaron Soffa) -
matz (Yukihiro Matsumoto)