Challenge

OPEN = File.method ‘open’

class File
def self.open(*a) 42 end
end
end

now restore File.open using OPEN - remember that open takes a

block…

-a

On Fri, 14 Jul 2006 [email protected] wrote:

OPEN = File.method ‘open’

class File
def self.open(*a) 42 end
end
end

now restore File.open using OPEN - remember that open takes a block…

correction. start here

open_m = File.method ‘open’

class File
def self.open(*a) 42 end
end
end

using a const makes it too easy and will accomplish what i need to do.

-a

[email protected] schrieb:

correction. start here

open_m = File.method ‘open’

class File
def self.open(*a) 42 end
end
end

using a const makes it too easy and will accomplish what i need to do.

class << File; self; end.class_eval do
remove_method :open
end

Regards,
Pit

On Fri, 14 Jul 2006, Pit C. wrote:

now restore File.open using OPEN - remember that open takes a block…

using a const makes it too easy and will accomplish what i need to do.

class << File; self; end.class_eval do
remove_method :open
end

wow. learn something every day!

~ > cat a.rb
class File
def File.open(*a) 42 end
end

p File.open(FILE)

class << File; self; end.class_eval do
remove_method :open
end

p File.open(FILE)

~ > ruby a.rb
42
#<File:a.rb>

i wasn’t aware remove_method had this ‘stacklike’ quality.

regards.

-a

On 7/14/06, [email protected] [email protected] wrote:

end
def self.open(*a) 42 end
wow. learn something every day!
end
i wasn’t aware remove_method had this ‘stacklike’ quality.
It does not, open is defined in IO, and becomes visible again :slight_smile:

regards.

-a

suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.

  • h.h. the 14th dali lama


Deux choses sont infinies : l’univers et la bêtise humaine ; en ce qui
concerne l’univers, je n’en ai pas acquis la certitude absolue.

  • Albert Einstein

[email protected] schrieb:

remove_method :open

i wasn’t aware remove_method had this ‘stacklike’ quality.

Ara, I just called

p open_m

and noticed that “open” wasn’t a method of class “File”, but of class
“IO”! So to get back to the normal behaviour it was enough to remove the
new method of class “File”.

This is even shorter:

class << File
remove_method :open
end

The “class_eval” part isn’t necessary.

Regards,
Pit

[email protected] wrote:

remove_method :open

i wasn’t aware remove_method had this ‘stacklike’ quality.

The open method is in fact defined in IO class which is extended by File
class. In your case another method for File eigenclass class was defined

lopex

[email protected] wrote:

(class << File; self; end).instance_eval {
define_method(:open,&open_m)
}

?

T.

On Fri, 14 Jul 2006 [email protected] wrote:

(class << File; self; end).instance_eval {
define_method(:open,&open_m)
and the block?

-a

On 7/14/06, [email protected] [email protected] wrote:

  • h.h. the 14th dali lama

I had to cheat :wink:

File::OPEN_M = open_m
class File
eval "
def self.open(*args, &block)
OPEN_M.call(*args, &block)
end
"
end

The problem is - as I’m sure you know - that define_method doesn’t
honour the block argument of the method reference. I’d be very
interested to see if you can do it cleanly in ruby 1.8.

Regards,
Sean

On Fri, 14 Jul 2006, Robert D. wrote:

It does not, open is defined in IO, and becomes visible again :slight_smile:

duh - need more coffee. so - back to original challenge!

-a

On 7/14/06, Sean O’Halpin [email protected] wrote:

suffering increases your inner strength. also, the wishing for
OPEN_M.call(*args, &block)

Block behavior is preserved though when we store a reference to a method
e.g.
----------------------- 8< ------------------------------
class X
def x(*args,&block)
block.call(1764) if block
end
end

OLD = X.instance_method :x

class X
def x; “rubbish”; end
end

class X

define_method(:x, OLD )

end

X.new.x{ |a| puts a }
----------------------- >8 ----------------------------------

That should do the trick, no?
But I cannot make it work with IO :(, some internal magic, maybe?

Cheers
Robert

On 7/14/06, Robert D. [email protected] wrote:


def self.open(*args, &block)
Sean

end

Excellent. Don’t use the & to convert the Proc into a block - just use
the method reference directly.

Are you getting the “singleton method called for a different object
(TypeError)” error?

Thanks,
Sean

[snip]

Excellent. Don’t use the & to convert the Proc into a block - just use
the method reference directly.

Too much honor, I seem to post too fast, furthermore the idea is ara’s
not
mine :slight_smile:

Are you getting the "singleton method called for a different object

(TypeError)" error?

Thanks,
Sean

Exactly
and though my original code is not well documenting the behavior ara is
exploiting it really does seem to be a problem because of the “internal”
nature of IO.
Here is eventually the code mimicking the structure of the inherited
class
method “open” and one can see that it works perfectly well:

class X # role of IO
class << self
def x(*args,&block) # role of open
block.call(1764) if block
end
end
end

OLD = X.method :x

class Y < X # role of File
class << self
def x; “rubbish”; end
end
end

class Y
class << self
define_method(:x, OLD )
end

end

Y.x{ |a| puts a }

Cheers
Robert

On 7/14/06, Robert D. [email protected] wrote:

nature of IO.

    define_method(:x, OLD )
end

end

Y.x{ |a| puts a }

Cheers
Robert

Hmmm. I’m still getting “singleton method called for a different
object (TypeError)” for this (ruby 1.8.4 (2005-12-24) [i386-mswin32]).

Sean

[SOLUTION] :wink:

OPEN =File.method ‘open’

class File
def self.open(*a) 42 end
end

class File
class << self
def open(*args,&block)
OPEN.call(*args, &block)
end
end
end

x=File.open(FILE){
|f|
puts f.read
}

Please do not flame me I am aware of the shortcomings( at least I hope
so),
but I just did not get the Metaprogramming to work, it would be good to
know
why!

Cheers
Robert

On 7/14/06, Sean O’Halpin [email protected] wrote:

The problem is - as I’m sure you know - that define_method doesn’t
honour the block argument of the method reference. I’d be very
interested to see if you can do it cleanly in ruby 1.8.

Regards,
Sean

Replying to myself to correct an error - it’s the implicit to_proc (&)
that strips the block argument, not define_method itself.

This illustrates the (perhaps surprising) behaviour:

def m1(*args, &block)
p args
block.call if block_given?
end

m1(1) do
puts “m1”
end

meth = method(:m1)

Object.instance_eval { define_method :m2, meth }

m2(2) do
puts “m2”
end

Object.instance_eval { define_method :m3, &meth }

m3(3) do # this block is not called
puts “m3”
end
END
[1]
m1
[2]
m2
[3]

Regards,
Sean

On 7/14/06, [email protected] [email protected] wrote:

On Fri, 14 Jul 2006, Sean O’Halpin wrote:

Hmmm. I’m still getting “singleton method called for a different
object (TypeError)” for this (ruby 1.8.4 (2005-12-24) [i386-mswin32]).

[SNIP]
you robert?

Me too, what was I executing???
Sorry,

btw. this challenge was not arbitrary: the increase in metaprogramming

On 7/14/06, [email protected] [email protected] wrote:

   def x(*args,&block) # role of open
 end

you robert?
instance_method 42
class_method{

but, of course, we are seeing that it doesn’t work.

regards.

-a

suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.

  • h.h. the 14th dali lama

In most cases, this works:

class Foo
def self.open(*args, &block)
p [args, block]
yield if block_given?
end
end

Foo.open(1) do
puts “hello”
end

open_m = Foo.method ‘open’

class Foo
def self.open(*a) p 42 end
end

Foo.open(2) do
puts “hello”
end

(class << Foo; self; end).instance_eval do
define_method(:open, open_m)
end

Foo.open(3) do
puts “bye”
end
END
[[1],
#Proc:0x02869018@c:/rubylib/experiments/redefine-class-method.rb:8]
hello
42
[[3],
#Proc:0x02867728@c:/rubylib/experiments/redefine-class-method.rb:26]
bye

but as we’ve seen, it doesn’t work in the case of the File(IO)
singleton. To be honest, I’m not clear about exactly what kind of
object the File(IO) singleton is. Anyone offer any enlightenment?

Regards,
Sean

On Sat, Jul 15, 2006 at 10:33:09AM +0900, Sean O’Halpin wrote:

On 7/14/06, [email protected] [email protected] wrote:

On Fri, 14 Jul 2006, Sean O’Halpin wrote:
In most cases, this works:

class Foo
def self.open(*args, &block)
p [args, block]
yield if block_given?
end
end
[…]
(class << Foo; self; end).instance_eval do
define_method(:open, open_m)
end
[…]
but as we’ve seen, it doesn’t work in the case of the File(IO)
singleton. To be honest, I’m not clear about exactly what kind of
object the File(IO) singleton is. Anyone offer any enlightenment?

Open is a singleton method of IO, not File; this is why the call fails
(in
1.9, it’d happen earlier, as soon as you try to rebind the method).
There’s
nothing that special about File itself:

class X
def self.foo; yield + 1 end
end

class Y < X
end

Y.foo{1} # => 2
m = Y.method(:foo)
def Y.foo; 10 end
Y.foo{1} # => 10
class << Y; self end.class_eval{define_method(:foo, m)}
Y.foo{1} # =>

~> -:13:in `foo’: singleton method bound for a different object

(TypeError)

~> from -:13

As for the File(IO) notation, it seems to mean that the singleton method
belongs to IO:

class X; def self.foo; yield + 1 end end
class Y < X; end
Y.method(:foo) # => #<Method: Y(X).foo>
X.method(:foo) # => #<Method: X.foo>

Keep in mind that the singleton class of a class is derived from that of
its
superclass:

class X; def self.foo; 1 end end
class Y < X; end
X.methods(false) # => [“foo”]
Y.methods(false) # => []
Y.foo # => 1