[#111472] [Ruby master Bug#19274] Error installing ruby 3.2.0 on RH 8 — "aalllop (Alberto Allegue) via ruby-core" <ruby-core@...>
Issue #19274 has been reported by aalllop (Alberto Allegue).
5 messages
2022/12/28
[#111508] Data support for versions before 3.2.0 — Eustáquio Rangel via ruby-core <ruby-core@...>
I was wondering that every piece of code (gems, etc) that use the new Data =
3 messages
2022/12/29
[ruby-core:111527] [Ruby master Bug#19278] Constructing subclasses of Data with positional arguments
From:
"zverok (Victor Shepelev) via ruby-core" <ruby-core@...>
Date:
2022-12-30 10:56:06 UTC
List:
ruby-core #111527
Issue #19278 has been updated by zverok (Victor Shepelev).
> I do this all the time with structs. I assumed Data.define would basically just be a read-only Struct.new and that's how I got here.
(Wrote a long theoretical answer, deleted it!)
Wait. I now reread your initial example more attentively, and I see the source of the confusion now: that we are _adjusting_ the `initialize` to accept the arguments the initial class knew nothing about (not redefining it to accept the same args, but differently), and the behavior is indeed hard to grasp immediately.
I am not sure something can be done about it in a consistent manner, though.
That's a source of the conveniences that are provided in other cases (I think for "simple data classes" ability to be initialized by both keyword and positional argument is crucial for their adoption; and I still believe that the convention of "initialize is easy to redefine, but it should always accept keywords" is a good enough compromise).
It seems that "completely redefine what data is accepted to constructor" would be a natural limitation of `Data`, which seems more or less suitable (inheriting to provide some convenience methods is one thing, building an inheritance chain is another).
The only way I see so far to make your `Baz` work is this:
```ruby
Foo = Data.define
class Bar < Foo
def self.new(foo) = super(foo:) # convert positional to keyword
def initialize(foo:) = p foo # ...then they are safely passed to initialize
end
Bar.new(1)
#=> 1
```
BTW, note that before 3.2, for structs it was either `keyword_init: false`, or `keyword_init: true`, not both.
That's why you were able to easily redefine `initialize`: you _knew_ it receives either keywords or positionals, not "both and need to choose". After 3.2, it is different, and I think that people would stumble on that many times (the design decision was made differently, too, unlike Data):
```ruby
S = Struct.new(:x) do
def initialize(*a, **kwa)
puts "a=#{a}, kwa=#{kwa}"
end
end
S.new(1)
# a=[1], kwa={}
S.new(x: 1)
# a=[], kwa={:x=>1}
```
I think it will cause a fair share of confusion in completely different ways than the design choice for `Data` did :)
----------------------------------------
Bug #19278: Constructing subclasses of Data with positional arguments
https://bugs.ruby-lang.org/issues/19278#change-100891
* Author: tenderlovemaking (Aaron Patterson)
* Status: Feedback
* Priority: Normal
* ruby -v: ruby 3.2.0 (2022-12-25 revision a528908271) [arm64-darwin22]
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
I'd expect both of the following subclasses to work, but the subclass that uses positional parameters raises an exception:
```ruby
Foo = Data.define
class Bar < Foo
def initialize foo:
p foo
end
end
class Baz < Foo
def initialize foo
p foo
end
end
Bar.new foo: 1 # Prints 1
Baz.new 1 # Raises ArgumentError
```
I'd expect the subclass that uses positional arguments to work.
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- [email protected]
To unsubscribe send an email to [email protected]
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/