Challenge

On 7/18/06, Mauricio F. [email protected] wrote:

end
1.9, it’d happen earlier, as soon as you try to rebind the method). There’s
m = Y.method(:foo)
class X; def self.foo; yield + 1 end end
Y.methods(false) # => []
Y.foo # => 1


Mauricio F. - http://eigenclass.org - singular Ruby

I think that certainly fits the description of enlightenment :slight_smile:

I can see now that my example was missing the essential aspect of
using a parent’s singleton method in a derived class.

And so back to Ara’s challenge…

Regards,
Sean

On Wed, 19 Jul 2006, Sean O’Halpin wrote:

I think that certainly fits the description of enlightenment :slight_smile:

I can see now that my example was missing the essential aspect of using a
parent’s singleton method in a derived class.

And so back to Ara’s challenge…

yeah - i never solved satisfactorily…

good luck!

-a

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

me too.

harp:~ > cat a.rb
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 }

harp:~ > ruby a.rb
a.rb:23:in `x’: singleton method called for a different object
(TypeError)
from a.rb:23

harp:~ > ruby -v && cat /etc/redhat-release && uname -srm
ruby 1.8.4 (2005-12-01) [i686-linux]
Red Hat Enterprise Linux WS release 3 (Taroon Update 7)
Linux 2.4.21-40.EL i686

you robert?

btw. this challenge was not arbitrary: the increase in metaprogramming
popularity means people are doing things like

def class_method
alias ‘instance_method’, ‘instance_method’ # push

 define_method 'instance_method' do
   # ...
   __instance_method__ 42
   # ...
 end

ensure
alias ‘instance_method’, ‘instance_method’ # pop
end

but this is neither thread safe (easy to fix) or re-entrant (not easy to
fix).
what i mean is doing

class_method{
class_method{
}
}

blows up.

to avoid this i wanted to develop this pattern

def class_method
instance_method = method ‘instance_method’ # push

 define_method 'instance_method' do
   # ...
   __instance_method__.call 42
   # ...
 end

ensure
define_method ‘instance_method’, instance_method # pop
end

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

regards.

-a

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

Just another thaught about it, what is wrong with my OPEN.call solution, is
it not general enough?

Cheers
Robert

Nothing wrong with it - it’s just not an answer to the challenge!

In Ara’s second post he notes: “using a const makes it too easy and
will accomplish what i need to do.”

The reason it’s not so useful to use consts is that it’s not
re-entrant (so you can’t nest and it’s not thread-safe), it pollutes
the constant namespace, it becomes harder to manage the more instances
you have, it’s not contained within local scope, etc. so I guess it
wouldn’t pass as a general solution. You could probably overcome some
of these issues by using thread-local stacks but then that would
quickly start to get messy and wouldn’t address the using out-of-scope
information issue.

However, back in the real world ;), yours is a pragmatic solution that
works as long as you understand its limitations.

Regards,
Sean

On Wed, Jul 19, 2006 at 06:22:18PM +0900, Robert D. wrote:

it not general enough?
It’d require one constant per method call for Ara’s intended use, in the
general case (when several “layers” can be added at any point in time,
i.e.
you want it to be reentrant).

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

information issue.

However, back in the real world ;), yours is a pragmatic solution that
works as long as you understand its limitations.

Regards,
Sean

I guess I fail to understand the challange :frowning:
Nevertheless the constant is just one way to store a reference to the
original methods, it would be very simple to export references of all
methods into a hash or a delegation object or whatever.
The constant was just part of the original challange.

I also have difficulties to see why

X.some
is any different from
X.method(“some”).call
concerning Thread Safety or even reentrance.

But anyway I too would prefer to reinstall the original method
structure,
which is perfectly possible if the method was not from a superclass. And
if
it was from the superclass we do not need to redefine it, so how about

class File
class << self
remove_method :open
define_method( :open, OPEN ) unless respond_to? :open
end
end

Cheers
Robert


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

Mauricio F. schrieb:

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:
(…)

The problem is, if you change the method of the superclass (IO), and
then later restore the original version, that you can’t call it on the
subclass (File):

class X; def self.foo; 1 end end
class Y < X; end

Y.foo # => 1

m = X.method(:foo)
def X.foo; 2 end

Y.foo # => 2

class << X; self end.class_eval{define_method(:foo, m)}

X.foo # => 1
Y.foo # => singleton method called for a different object

Do you know why this happens?

Regards,
Pit

[email protected] wrote:

OPEN = File.method ‘open’

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

It seems there’s an “end” too much. But to the real story: here’s a
completely different idea - although not very nice either:

irb(main):004:0> F2=SimpleDelegator.new File
=> File
irb(main):005:0> def F2.open(*a) 42 end
=> nil
irb(main):006:0> F_OLD=File
=> File
irb(main):007:0> File=F2
(irb):7: warning: already initialized constant File
=> File
irb(main):008:0> File.open
=> 42
irb(main):009:0> File=F_OLD
(irb):9: warning: already initialized constant File
=> File

Drawback is the const reassignment…

Kind regards

robert

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

Just another thaught about it, what is wrong with my OPEN.call solution,
is
it not general enough?

Cheers
Robert


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