def foo[](x)

G

Gavin Kistner

#Works
class Foo1
def [](x)
#...
end
end

#Syntax Error
class Foo2
def bar[](x)
#...
end
end


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?
 
G

gabriele renzi

#Works
class Foo1
def [](x)
#...
end
end

#Syntax Error
class Foo2
def bar[](x)
#...
end
end


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?
class C
def initialize
@bar=method :met
end
def met(x)
x**2
end
private :met
attr_reader :bar
end => nil
C.new.bar[12]
=> 144

alla callable objects (proc, method, continuations have a [] method.
But I'm not sure this is what you would see :)
 
J

Jamis Buck

Gavin said:
#Works
class Foo1
def [](x)
#...
end
end

#Syntax Error
class Foo2
def bar[](x)
#...
end
end


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 [](x)
...
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. ;(

- Jamis
 
D

David Heinemeier Hansson

....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.

Could this perhaps make it in as an RCR?
 
D

Dan Doel

Acutally, this might be better:

instead of:

class Foo
def bar[](*args)
# code
end
end

do:

class Foo
def bar
proc { |*args|
# code
end
end
end
 
G

Gavin Kistner

David said:
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 this perhaps make it in as an RCR?

I'm glad I'm not the only one. I have now added this as an RCR:
http://www.wobblini.net/rcr/RCR/RCR201

Please check it out and vote! :)
 
J

Joel VanderWerf

Gavin said:
I'm glad I'm not the only one. I have now added this as an RCR:
http://www.wobblini.net/rcr/RCR/RCR201

Question: in this method call:

x.foo[1]

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.)
 
G

Gavin Kistner

Joel said:
I'm glad I'm not the only one. I have now added this as an RCR:
http://www.wobblini.net/rcr/RCR/RCR201


Question: in this method call:

x.foo[1]

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)[](1)

I propose that it try:
x.foo[](1)
first, and if that method does not exist, then default to the current:
(x.foo)[](1)
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.
 
G

Gavin Kistner

Gavin said:
Joel said:
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.
 
J

Joel VanderWerf

Gavin Kistner wrote:
...
I propose that it try:
x.foo[](1)
first, and if that method does not exist, then default to the current:
(x.foo)[](1)
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:

class Base
def bar[](x)
"base"
end
end

class Sub < Base
def bar(x)
["sub"]
end
end

Sub.new.bar[0]

Would this return "base" or "sub"?
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: def foo[](x)"

|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[](1)), 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.

---
class ArefAttribute
def initialize(&block)
@block = block
end
def [](*args)
@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[x] || @childrenByName[x] || @childrenById[x]
}
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]
 
R

Robert Klemme

Gavin Kistner said:
I'm glad I'm not the only one. I have now added this as an RCR:
http://www.wobblini.net/rcr/RCR/RCR201

Please check it out and vote! :)

-1 (voting on the site didn't work for me)

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?

Regards

robert
 
G

Gavin Kistner

Yukihiro said:
[...] 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.

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! :)
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: def foo[](x)"

|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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,141
Messages
2,570,818
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top