UnboundMethods Useless?

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.

T. Onoma wrote:

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…

···


Jamis Buck
jgb3@email.byu.edu

ruby -h | ruby -e ‘a=;readlines.join.scan(/-(.)[e|Kk(\S*)|le.l(…)e|#!(\S*)/) {|r| a << r.compact.first };puts “\n>#{a.join(%q/ /)}<\n\n”’

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

···

On Tue, Dec 16, 2003 at 05:09:00AM +0900, T. Onoma wrote:

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?

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

Try this
  

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

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

  Derived.new.foo()

now it must work

Guy Decoux

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.

···

On Tuesday 16 December 2003 08:54 pm, Dan Doel wrote:

You can do stuff like this:

class Object
def foo
puts “Bar”
end
end

u = Object.instance_method :foo

class Object
undef foo
end

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

···

On Wed, Dec 17, 2003 at 12:19:05AM +0900, ts wrote:

Try this

base_foo = Base.instance_method(:foo)
Derived.send(:define_method, :foo, base_foo)

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

Derived.new.foo()

now it must work

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.

···

On Wed, 17 Dec 2003, T. Onoma wrote:

Which class restriction?

Chad

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

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

Guy Decoux

Which class restriction?

He is trying to take a method from a class and define this method in the
superclass.

Just imagine :
   * take the method Array#pop and define it in Object
   * now just call Hash.new.pop

What do you expect ?

Guy Decoux

irb(main):001:0> class A
irb(main):002:1> def x
irb(main):003:2> print “Y”
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> class B
irb(main):007:1> end
=> nil
irb(main):008:0> u = A.instance_method(:x)
=> #<UnboundMethod: A#x>
irb(main):009:0> u.bind(B)
TypeError: bind argument must be an instance of A
from (irb):9:in `bind’
from (irb):9

···

On Wednesday 17 December 2003 01:17 pm, Chad Fowler wrote:

On Wed, 17 Dec 2003, T. Onoma wrote:

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.

Which class restriction?


T.

Expectations’ are precisely the point. The difference is all about the order
of exectution.

···

On Wednesday 17 December 2003 01:21 pm, ts wrote:

Which class restriction?

He is trying to take a method from a class and define this method in the
superclass.

Just imagine :

  • take the method Array#pop and define it in Object
  • now just call Hash.new.pop

What do you expect ?


T.

Expectations' are precisely the point.

If you expect something else than a coredump, then probably there is
something that you have not yet found.

Guy Decoux

Why Guy? In lisp you can move functions around til the cows come home. I’m
guessing that given your remarks that there’s something going on in Ruby’s
evaluation of method definitions that make them irreversible, i.e. incapable
of being pulled from the binding context and bound to another. If that is the
case then I would suggest that perhaps it would not be unwise for someone as
capabale as yourself to consider how one might preserve reversibility in
order to vanquish this limitation.

···

On Wednesday 17 December 2003 01:59 pm, ts wrote:

Expectations’ are precisely the point.

If you expect something else than a coredump, then probably there is
something that you have not yet found.


T.

I don’t know what you mean by (ir)reversible, but the point is that
it’s meaningless to talk about arbitrary objects being able to do
arbitrary things. For example (and Guy has already given some),
String#strip removes whitespace. What would it mean to remove
whitespace from a Hash or a Fixnum or a MyThing? And more to the
point, what would happen if

I don’t mean: “Could such objects have some method called ‘strip’
which made sense for them?” because that’s not what you’re suggesting.
What you’re suggesting is that String#strip, Array#join, Thread#join,
IO#readlines, Regexp.escape, MyThing#some_method, and every other
method written for any purpose in Ruby should, without change or
adaptation, work for any Ruby object.

David

···

On Wed, 17 Dec 2003, T. Onoma wrote:

On Wednesday 17 December 2003 01:59 pm, ts wrote:

Expectations’ are precisely the point.

If you expect something else than a coredump, then probably there is
something that you have not yet found.

Why Guy? In lisp you can move functions around til the cows come home. I’m
guessing that given your remarks that there’s something going on in Ruby’s
evaluation of method definitions that make them irreversible, i.e. incapable
of being pulled from the binding context and bound to another. If that is the
case then I would suggest that perhaps it would not be unwise for someone as
capabale as yourself to consider how one might preserve reversibility in
order to vanquish this limitation.


David A. Black
dblack@wobblini.net

Whoops, dropped off the cliff there, but let’s just say it’s for
dramatic effect :slight_smile:

David

···

On Wed, 17 Dec 2003, David A. Black wrote:

I don’t know what you mean by (ir)reversible, but the point is that
it’s meaningless to talk about arbitrary objects being able to do
arbitrary things. For example (and Guy has already given some),
String#strip removes whitespace. What would it mean to remove
whitespace from a Hash or a Fixnum or a MyThing? And more to the
point, what would happen if


David A. Black
dblack@wobblini.net

I don’t know what you mean by (ir)reversible, but the point is that
it’s meaningless to talk about arbitrary objects being able to do
arbitrary things. For example (and Guy has already given some),
String#strip removes whitespace. What would it mean to remove
whitespace from a Hash or a Fixnum or a MyThing? And more to the
point, what would happen if

I don’t mean: “Could such objects have some method called ‘strip’
which made sense for them?” because that’s not what you’re suggesting.
What you’re suggesting is that String#strip, Array#join, Thread#join,
IO#readlines, Regexp.escape, MyThing#some_method, and every other
method written for any purpose in Ruby should, without change or
adaptation, work for any Ruby object.

By the same reasoning, Ruby is suggesting that any module makes sense in
any class/object, because you can include a module in any class you’d
like. With freedom comes the possibility of doing something wrong, but
that doesn’t make freedom wrong, now does it?

Peter

I don’t know what you mean by (ir)reversible, but the point is that
it’s meaningless to talk about arbitrary objects being able to do
arbitrary things. For example (and Guy has already given some),
String#strip removes whitespace. What would it mean to remove
whitespace from a Hash or a Fixnum or a MyThing? And more to the
point, what would happen if

It is not meaningless. It is not arbitrary. Programmer’s do not just blow
their nose and snotty code comes out. Your extreme over simplification has no
bearing.

I don’t mean: “Could such objects have some method called ‘strip’
which made sense for them?” because that’s not what you’re suggesting.
What you’re suggesting is that String#strip, Array#join, Thread#join,
IO#readlines, Regexp.escape, MyThing#some_method, and every other
method written for any purpose in Ruby should, without change or
adaptation, work for any Ruby object.

No, that is not being said. What is being said: if the shoe fits, wear it.
Hmm… sounds like a bad work I know: *uck :wink:

It all about the Dynamics, baby! Let the Static go.

···

On Wednesday 17 December 2003 03:06 pm, David A. Black wrote:


T.

By the same reasoning, Ruby is suggesting that any module makes sense in

a module is not a class

Guy Decoux