Ruby snippet: detaching a method from an object as a closure

Posted by Jeremy Voorhis Thu, 15 Jun 2006 04:28:00 GMT


irb(main):041:0> "cat".method( :size ).to_proc.call          
=> 3
irb(main):042:0> str = 'CAT'
=> "CAT" 
irb(main):043:0> aproc = str.method( :size ).to_proc
=> #<Proc:0x000cc064@(irb):43>
irb(main):044:0> aproc.call
=> 3
irb(main):045:0> aproc.call
=> 3
irb(main):046:0> str << 'FISH'
=> "CATFISH" 
irb(main):047:0> aproc.call
=> 7
irb(main):048:0> newstr = ''
=> "" 
irb(main):049:0> def newstr.metaclass; class << self; self; end; end # thx _why!
=> nil
irb(main):050:0> newstr.metaclass.send :define_method, :size, &aproc
=> #<Proc:0x000cc064@(irb):43>
irb(main):051:0> str
=> "CATFISH" 
irb(main):052:0> newstr
=> "" 
irb(main):053:0> str.size
=> 7
irb(main):054:0> newstr.size
=> 7

Comments

  1. \/ curry said 37 minutes later:

    Why???

    Also, all the `#to_proc`s are unnecessary.

    "cat".method(:size).call  # =&gt; 3
    str = "CAT"               # =&gt; CAT
    aproc = str.method(:size) # =&gt; #&lt;Method: String#size&gt;
    aproc.call                # =&gt; 3
    str &lt;&lt; "FISH"             # =&gt; "CATFISH" 
    aproc.call                # =&gt; 7
    newstr = ""               # =&gt; "" 
    def newstr.metaclass; class &lt;&lt; self; self; end; end # =&gt; nil
    newstr.metaclass.send(:define_method, :size, &aproc) # =&gt; #&lt;Proc:0x00050060@(irb):9&gt;
    str                       # =&gt; "CATFISH" 
    newstr                    # =&gt; "" 
    str.size                  # =&gt; 7
    newstr.size               # =&gt; 7

    Your irb session also has a strange error at the end… “CATFISH” is 7, not 8.

  2. JV said about 1 hour later:

    Ah, you are right. I took some editorial liberties and reformatted some of the code to read more clearly, but that should be 7, not 8.

    As to why? This is a completely absurd example, but I am amused by the possibilities.

  3. Ben Askins said about 5 hours later:

    What practicle applications do you see for this?

  4. Ben Askins said about 5 hours later:

    What practicle applications do you see for this?

  5. trans said about 8 hours later:

    The why is becuase the Ruby “compiles” the method in the context of the original object. So the resulting Proc carries along with it that “closure”.

    Many have asked for a way to rebind a proc to a differnt context, but it must be difficult to code for some reason, b/c we don’t have it yet.

    Personally I think the practical applications of the current functionality are rather limited.

  6. sammy said about 16 hours later:

    I feel a little dirty reading this.

    Very cool, though, even if it’s just as an exercise. Thanks for the summary.

(leave url/email »)