UnboundMethods Useless?

T

T. Onoma

Urrrr.....

class Q
end

class A
def x
print "X"
end
end

q = Q.new
meth = A.instance_method:)x)
meth.bind(q)
q.x; puts

results in

`bind': bind argument must be an instance of A (TypeError)

If I can only bind the method to an object of the same class from which I took
it, then what's the point!? What am I missing?

T.
 
J

Jamis Buck

T. Onoma said:
If I can only bind the method to an object of the same class from which I took
it, then what's the point!? What am I missing?

T.

I believe the idea is something like this: you have a class A and an
array of instances of A. You then want to call a method on each of the
instances, so you grab an unbound instance of the method you want to
call, iterate over the array and bind it successively to each member of
the array, and call it.

Yah, in this case, it's much easier just to use 'each' or something.
And I have to admit there have been more times that I've wished I could
bind an arbitrary object to an unbound method...
 
P

Paul Brannan

If I can only bind the method to an object of the same class from
which I took it, then what's the point!? What am I missing?

It's not useless; I found at least one use for it in [ruby-talk:29122].

In trying to demonstrate an additional use, I came across this
peculiarity:

class Base
def foo
puts "Base#foo"
end
end

class Derived < Base
def foo
puts "Derived#foo"
super
end
end

base_foo = Base.instance_method:)foo)
Derived.__send__:)define_method, :foo, base_foo)

# If I leave the following line out, then Derived.new.foo() results in:
# test.rb:32: private method `foo' called for #<Derived:0x4027d0cc> (NameError)
Derived.__send__:)public, :foo)

# The following code produces (on Ruby 1.6):
# test.rb:18:in `foo': bind argument must be an instance of Base (TypeError)
# from test.rb:18
# But on Ruby 1.8 it prints Base#foo as expected.
Derived.new.foo()

Can someone explain to me what's happening here?

Paul
 
P

Paul Brannan

Try this

P> base_foo = Base.instance_method:)foo)
P> Derived.__send__:)define_method, :foo, base_foo)

class A
base_foo = Base.instance_method:)foo)
Derived.__send__:)define_method, :foo, base_foo)
end

P> Derived.new.foo()

now it must work

By this I'm guessing you mean that I don't have to explictly make foo
public. Is this because all methods defined at the top level are
private by default, even if they are defined with
__send__:)define_method)?

Paul
 
T

ts

P> By this I'm guessing you mean that I don't have to explictly make foo
P> public. Is this because all methods defined at the top level are
P> private by default, even if they are defined with
P> __send__:)define_method)?

Yes, the default scope at top level is private : `class A; end' was just
to change the scope :)


Guy Decoux
 
D

Dan Doel

You can do stuff like this:

class Object
def foo
puts "Bar"
end
end

u = Object.instance_method :foo

class Object
undef foo
end

class ArbitraryClass
end

o = ArbitraryClass.new

b = u.bind o

b.call

Which isn't as generally useful, I know, but if you're constructing methods
from strings which you seem to be doing elsewhere, you can do something
like this:

class Object
def Object.universal_method(args, code)
eval %Q/
def method_44518982938293(#{args})
#{code}
end
/

m = instance_method :method_44518982938293

undef method_44518982938293

m
end
end

u = Object.universal_method %Q{foo, bar}, %Q{
puts foo, bar
}

class ArbitrarySubclass
end

o = ArbitrarySubclass.new

b = u.bind o

b.call 2, 3

Not exactly elegant code, but it works.

- Dan
 
T

T. Onoma

You can do stuff like this:

class Object
def foo
puts "Bar"
end
end

u = Object.instance_method :foo

class Object
undef foo
end

Ah ha! I see, by putting the method in Object you get a sort-of universal
method since everthing is an Object. Nice. Makes me wonder why the class
restiriction exists at all then.

Of course there is still the problem with super, but that doesn't take a way
from the usefulness you demonstrate.

Thanks, Dan!
T.
 

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,817
Members
47,364
Latest member
Stevanida

Latest Threads

Top