Bug #1983
closedStruct doesn't define instance methods for valid method names
Description
=begin
foo = Struct.new(:foo?, :foo!).new(true, true)
=> #<struct :foo?=true, :foo!=true>
foo.foo?
NoMethodError: undefined methodfoo?' for #<struct :foo?=true, :foo!=true> from (irb):3 from /usr/local/bin/irb19:12:in
'
foo.foo!
NoMethodError: undefined methodfoo!' for #<struct :foo?=true, :foo!=true> from (irb):4 from /usr/local/bin/irb19:12:in
'
foo[:foo?]
=> true
foo[:foo!]
=> true
I think this is because foo?= and foo!= are not valid setter methods.
By why not generate the reader and skip the setter, then?
=end
Updated by tmat (Tomas Matousek) over 15 years ago
=begin
Since
irb(main):012:0> class C
irb(main):013:1> attr_accessor :foo?
irb(main):014:1> end
NameError: invalid attribute name `foo?'
I would rather think that the same error should be raised by Struct.new.
BTW, even more interesting names for attributes are operator names:
irb(main):007:0> Struct.new(:===, :+, :-)[1,2,3]
=> #<struct #Class:0x392b154 :====1, :+=2, :-=3>
=end
Updated by bitsweat (Jeremy Daer) over 15 years ago
=begin
Good point; struct is consistent with attr_*. Both use the same low-level check: (rb_is_local_id(id) || rb_is_const_id(id))
I'd like attr_reader :foo? to work too. It's a common convention for booleans. And for Struct, this is a nice way to stub out a duck-typed object.
=end
Updated by marcandre (Marc-Andre Lafortune) about 15 years ago
- Assignee set to matz (Yukihiro Matsumoto)
=begin
=end
Updated by mame (Yusuke Endoh) almost 15 years ago
- Status changed from Open to Rejected
=begin
Hi Jeremy,
By why not generate the reader and skip the setter, then?
In [ruby-core:4404], matz decided to prohibit such a field name once.
And in [ruby-core:4577], he relaxed the restriction:
having field names with "?" can be valid if field
accessor is disabled for such cases.
So it is currently intended, not a bug. I close this ticket.
You can re-register this as Feature ticket.
If you do, please elaborate the motivation example.
I'd like attr_reader :foo? to work too. It's a common convention for booleans.
We cannot define @foo? even by using reflection:
instance_variable_set(:"@foo?", 42)
#=> `@foo?' is not allowed as an instance variable name (NameError)
It is never a common convention.
IMO, if such a field name is allowed, we would next want to use foo?=
and @foo?. I think Ruby design is sane because it limits ourselves
from such earthly desires.
--
Yusuke Endoh mame@tsg.ne.jp
=end
Updated by bitsweat (Jeremy Daer) almost 15 years ago
=begin
Thanks Yusuke. It's a reasonable restriction, considering my only motivation is to use Struct to make stubs for testing other code.
=end