Is there no way to define a method that has a name and in it, to be
able to do something like:
myObj = Foo.new
puts myObj.bar[12]
…without having to create a new class for bar and define the
method in that class?
.
Well… you could so this:
class Foo2
def
…
end
def bar
self
end
end
myObj = Foo.new
puts myObj.bar[12]
But then you’re limited to one such attribute per class. Other than
that, I know of no way to do what you described, aside from (as you
mentioned) creating a different class that defines , and then having
an instance of that class associated with the bar attribute of Foo2. ;(
…without having to create a new class for bar and define the
method in that class?
I’ve been puzzled by this myself. There has been many times where I’ve
wanted to fake the appearance of a collection within a class without
actually making another class just for the purpose.
I’ve been puzzled by this myself. There has been many times where I’ve
wanted to fake the appearance of a collection within a class without
actually making another class just for the purpose.
I’ve been puzzled by this myself. There has been many times where I’ve
wanted to fake the appearance of a collection within a class without
actually making another class just for the purpose.
what is the search order? First for #foo, and then for #foo? Or the
other way around?
Suppose it’s #foo, then #foo. What if #foo is implemented in the
superclass, but #foo is implemented in the class of x itself? In other
words, depth-first search or breadth-first search?
It seems difficult to resolve the ambiguities inherent in this notation.
(But I have sometimes wished this feature existed.)
“Gavin Kistner” gavin@refinery.com schrieb im Newsbeitrag
news:QkgRb.157054$xy6.751016@attbi_s02…
David Heinemeier Hansson wrote:
I’ve been puzzled by this myself. There has been many times where I’ve
wanted to fake the appearance of a collection within a class without
actually making another class just for the purpose.
Could any of the proposers of this feature explain, why it is needed? And
why especially the proposed solution that used self for this isn’t
sufficient, i.e., why one would need several of those “virtual” members?
what is the search order? First for #foo, and then for #foo? Or the
other way around?
I addressed this in the RCR.
Currently the following are equivalent:
x.foo[1]
(x.foo)[1]
(x.foo)
I propose that it try:
x.foo
first, and if that method does not exist, then default to the current:
(x.foo)
Suppose it’s #foo, then #foo. What if #foo is implemented in the
superclass, but #foo is implemented in the class of x itself? In other
words, depth-first search or breadth-first search?
Hrm…this is a good point. You’re saying that with the following, the
syntax would allow both, but there would be ambiguity:
class Foo
def initialize
@beernuts=[]
@peanuts=[]
end
def bar
return @peanuts
end
def bar[](x)
return @beernuts[x]
end
end
x = Foo.new
puts x.bar[0] #Is this @peanuts[0] or @beernuts[0]
Adding both would be foolish as a developer (perhaps even throwing a
warning about them at compile time), but as long as the search order was
clearly defined, I personally wouldn’t be too worried.
I propose that it try:
x.foo
first, and if that method does not exist, then default to the current:
(x.foo)
Suppose it’s #foo, then #foo. What if #foo is implemented in the
superclass, but #foo is implemented in the class of x itself? In
other words, depth-first search or breadth-first search?
Hrm…this is a good point. You’re saying that with the following, the
syntax would allow both, but there would be ambiguity:
class Foo
def initialize
@beernuts=[]
@peanuts=[]
end
def bar
return @peanuts
end
def bar[](x)
return @beernuts[x]
end
end
x = Foo.new
puts x.bar[0] #Is this @peanuts[0] or @beernuts[0]
Your rule above, as I read it, would resolve the ambiguity: @beernuts[0].
Trying #bar before #bar, as you propose, makes sense because if you
really want #bar, you can easily force it with parens: (x.bar)[0],
whereas there’s no way to force #bar, short of using #send.
But what I had in mind was something involving inheritance:
Suppose it’s #foo, then #foo. What if #foo is implemented in the
superclass, but #foo is implemented in the class of x itself? In
other words, depth-first search or breadth-first search?
Adding both would be foolish as a developer (perhaps even throwing a
warning about them at compile time), but as long as the search order was
clearly defined, I personally wouldn’t be too worried.
To be more clear (since I only realized what you meant halfway
through)…I’m not sure which makes more sense. It’s sort of like
7+3*2
which should come first, addition or multiplication? By convention,
multiplication, but there’s not (AFAIK) a strong reason for it. That’s
just how it is, and once you know that, you know what to expect.
If I had to pick one, I suppose I’d choose breadth first; the most
recently/closely defined method should be used.
But this does point out a potential confusing point in the RCR, and
probably explains why it hasn’t been included in the language
already…not oversight, but purposeful omission.
To be more clear (since I only realized what you meant halfway
through)…I’m not sure which makes more sense. It’s sort of like
7+3*2
which should come first, addition or multiplication? By convention,
multiplication, but there’s not (AFAIK) a strong reason for it. That’s
just how it is, and once you know that, you know what to expect.
The example above (7+3*2) is just a matter of precedence, but this one
(say, obj.foo[1]) cannot be resolved by precedence; there are two
possible interpretation ((obj.foo)[1] and obj.foo), and worse,
you can tell them only by trying. I don’t like this kind of
ambiguity.
The problem shown in the RCR can be solved like the following. And I
feel this is far better solution for this particular problem.
matz.
···
In message “Re: def foo” on 04/01/27, Gavin Kistner gavin@refinery.com writes:
class ArefAttribute
def initialize(&block) @block = block
end
def @block.call(*args)
end
end
class Module
def attr_aref(name, &body)
name = name.to_s
accr = name+“_accessor”
define_method(accr, &body)
define_method(name) {
ArefAttribute.new {|*args|
self.send(accr, *args)
}
}
end
end
class HTMLElement
attr_aref(:children) {|x| @childElements || @childrenByName || @childrenById
}
def initialize
@childElements={1=>2}
@childrenByName={2=>4}
@childrenById={4=>8}
end
end
h = HTMLElement.new
p h.children[1]
p h.children[2]
p h.children[4]
p h.children[0]
The problem shown in the RCR can be solved like the following. And I
feel this is far better solution for this particular problem.
Thanks for your consideration of the problem, and thanks for the source
code solution. That’s relatively generic and useful.
I’ve changed my vote to oppose my own RCR, and am happy to have it
rejected
(Matz, you commented on the RCR: “Three consequent objection might
discourage you, but it always happens in the design process of a
language.” I am not at all discouraged. I’m happy that those who
understand the language better than I were able to find flaws with my
proposal and keep from adding to the language something that would make
it less clean. The process works…yay!
I’ve changed my vote to oppose my own RCR, and am happy to have it
rejected
You can withdraw it by yourself. I’m not going to reject any RCR
until the end of March if it provides all information needed.
(Matz, you commented on the RCR: “Three consequent objection might
discourage you, but it always happens in the design process of a
language.” I am not at all discouraged. I’m happy that those who
understand the language better than I were able to find flaws with my
proposal and keep from adding to the language something that would make
it less clean. The process works…yay!
I appreciate your understanding. Last 10 years so many ideas have
passed by in my brain, and I had to reject most of them by myself.
matz.
···
In message “Re: def foo” on 04/01/28, Gavin Kistner gavin@refinery.com writes: