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

···

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

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

···

On Fri, 14 Jul 2006 Ara.T.Howard@noaa.gov 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...

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

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

···

ara.t.howard@noaa.gov wrote:

  OPEN = File.method 'open'

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

ara.t.howard@noaa.gov schrieb:

···

On Fri, 14 Jul 2006 Ara.T.Howard@noaa.gov 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.

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

Regards,
Pit

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

?

T.

···

ara.t.howard@noaa.gov wrote:

On Fri, 14 Jul 2006 Ara.T.Howard@noaa.gov 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

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 Fri, 14 Jul 2006, Pit Capitain wrote:

ara.t.howard@noaa.gov schrieb:

On Fri, 14 Jul 2006 Ara.T.Howard@noaa.gov 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.

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

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

and the block?

-a

···

On Fri, 14 Jul 2006 transfire@gmail.com wrote:

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

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

> ara.t.howard@noaa.gov schrieb:
>>>
>>> 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.
>
> 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.

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

regards.

···

On 7/14/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

On Fri, 14 Jul 2006, Pit Capitain wrote:
>> On Fri, 14 Jul 2006 Ara.T.Howard@noaa.gov wrote:

-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

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

···

ara.t.howard@noaa.gov wrote:

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.

ara.t.howard@noaa.gov schrieb:

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.

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

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 7/14/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

On Fri, 14 Jul 2006 transfire@gmail.com wrote:

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

-a
--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

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

-a

···

On Fri, 14 Jul 2006, Robert Dober wrote:

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

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

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, Sean O'Halpin <sean.ohalpin@gmail.com> wrote:

On 7/14/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:
> On Fri, 14 Jul 2006 transfire@gmail.com wrote:
>
> > (class << File; self; end).instance_eval {
> > define_method(:open,&open_m)
> and the block?
>
> -a
> --
> suffering increases your inner strength. also, the wishing for
suffering
> makes the suffering disappear.
> - 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

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, Sean O'Halpin <sean.ohalpin@gmail.com> 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

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

···

On 7/14/06, Robert Dober <robert.dober@gmail.com> wrote:

On 7/14/06, Sean O'Halpin <sean.ohalpin@gmail.com> wrote:
>
> On 7/14/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:
> > On Fri, 14 Jul 2006 transfire@gmail.com wrote:
> >
> > > (class << File; self; end).instance_eval {
> > > define_method(:open,&open_m)
> > and the block?
> >
> > -a
> > --
> > suffering increases your inner strength. also, the wishing for
> suffering
> > makes the suffering disappear.
> > - 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
>
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

[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

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

···

On 7/14/06, Robert Dober <robert.dober@gmail.com> wrote:

[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

[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

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

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

> 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, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

On Fri, 14 Jul 2006, Sean O'Halpin wrote:
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
--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama