[ruby-core:111491] [Ruby master Bug#19280] Wrong error message about arity of Data::define.new

Issue #19280 has been reported by kyanagi (Kouhei Yanagita). ---------------------------------------- Bug #19280: Wrong error message about arity of Data::define.new https://bugs.ruby-lang.org/issues/19280 * Author: kyanagi (Kouhei Yanagita) * Status: Open * Priority: Normal * ruby -v: ruby 3.3.0dev (2022-12-28T16:43:05Z master cada537040) [x86_64-linux] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- ``` $ ~/work/r/bin/ruby -e 'Data.define(:a, :b).new(1, 2, 3)' -e:1:in `new': wrong number of arguments (given 3, expected 0..2) (ArgumentError) Data.define(:a, :b).new(1, 2, 3) ^^^^^^^ from -e:1:in `<main>' ``` On this message, "expected 2" is appropriate because fewer arguments are not allowed. ``` $ ~/work/r/bin/ruby -e 'Data.define(:a, :b).new(1)' -e:1:in `initialize': missing keyword: :b (ArgumentError) Data.define(:a, :b).new(1) ^ from -e:1:in `new' from -e:1:in `<main>' ``` -- https://bugs.ruby-lang.org/

Issue #19280 has been updated by zverok (Victor Shepelev). Status changed from Open to Closed The report about arity is correct. `Data` decouples `.new` and `#initialize` this way: * `.new` accepts positional and keyword args, and converts positional to keyword, and passes them to `#initialize` * `#initialize` accepts only keyword arguments, and is easy to redefine for custom processing; the default implementation has all keyword arguments mandatory. If `.new` method would be implemented in Ruby, for `Data.define(:a, :b)` it'll look this way: ```ruby KEYS = [:a, :b] def self.new(*args, **kwargs) # raise if both args and kwargs provided # handle args if args.any? raise ArgumentError if args.size > KEYS.size kwargs = args.zip(KEYS).to_h { |value, name| [name, value] } end allocate.initialize(**kwargs) end ``` It other words: * for `.new`, any number of positional args is correct, as long as it has names for them * they are converted to keyword args, and passed to initialize * ...which will raise if something is missing in the default implementation, but this implementation can be redefined **without `.new` thinking about it** Consider this: ```ruby Data.define(:a, :b) do def initialize(a:, b: 0) = super end.new(1) #=> #<data a=1, b=0> ``` Or even this: ```ruby Data.define(:a, :b) do def initialize(a: 0, b: 0) = super end.new #=> #<data a=0, b=0> ``` ...so, yeah, for `new`, the message "it expects 0 to 2 args" corresponds to reality. ---------------------------------------- Bug #19280: Wrong error message about arity of Data::define.new https://bugs.ruby-lang.org/issues/19280#change-100871 * Author: kyanagi (Kouhei Yanagita) * Status: Closed * Priority: Normal * ruby -v: ruby 3.3.0dev (2022-12-28T16:43:05Z master cada537040) [x86_64-linux] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- ``` $ ~/work/r/bin/ruby -e 'Data.define(:a, :b).new(1, 2, 3)' -e:1:in `new': wrong number of arguments (given 3, expected 0..2) (ArgumentError) Data.define(:a, :b).new(1, 2, 3) ^^^^^^^ from -e:1:in `<main>' ``` On this message, "expected 2" is appropriate because fewer arguments are not allowed. ``` $ ~/work/r/bin/ruby -e 'Data.define(:a, :b).new(1)' -e:1:in `initialize': missing keyword: :b (ArgumentError) Data.define(:a, :b).new(1) ^ from -e:1:in `new' from -e:1:in `<main>' ``` -- https://bugs.ruby-lang.org/
participants (2)
-
kyanagi (Kouhei Yanagita)
-
zverok (Victor Shepelev)