hoodwink.d enhanced
RSS
2.0
XHTML
1.0

RedHanded

A Lambda Camcorder #

by why in inspect

Beware magic-haters, a hack from Mike Williams, wherein you do a bunch of method calls on an anonymous object and the recording can get dup’d to lambda format.

 people.select(&its.name.length > 10)

It’s the its method that’s the camcorder, creating a blank MessageBuffer to tape on to.

said on 04 Oct 2006 at 14:19

SQLBuilder in Ruby!

said on 04 Oct 2006 at 14:54

ez-where is sql builder in ruby sort of ;)

said on 04 Oct 2006 at 15:41

Great name. I really like this. A lot. :)

said on 04 Oct 2006 at 21:05

This reminds me of some old Objective-C hacks which could be worth checking out, if you’re into that.

said on 04 Oct 2006 at 21:07

The idea there is more like people.whose.name.length > 10, though. I can’t decide which I like better.

said on 05 Oct 2006 at 07:48

... and of some new ones ( http://www.cocoade.com/developer.html )

said on 05 Oct 2006 at 08:22

v. awesome!

said on 05 Oct 2006 at 08:28

does this “it” camcorder do weddings?

said on 05 Oct 2006 at 16:13

My own try at implementing it:


class ItProc < Proc

  instance_methods.each {|m| undef_method m unless m =~ /^__/}

  def method_missing(*args, &blk)
    ItProc.new {|x| Proc.instance_method(:call).bind(self).call(x).send(*args, &blk)}
  end

end

# A little more magical for its that might be passed around.
def it
  if block_given?
    ItProc.new # automatically yanks the block on it
  else
    ItProc.new {|x| x}
  end
end
private :it

[1,2,3].map(&it.succ.to_s)

Of course call can be added back to allow this sort of stuff:


it.to_s[0].call(42) #=> 52

The biggest plus is that it is already a Proc object, so we really don’t need any method visible… ruby will just use it as is. Something obscure like this now becomes possible:


[:to_s].map(&it.to_proc)

The use of method_missing like this reminds me of >>= in Haskell… :-)

said on 05 Oct 2006 at 20:40

Very cool. And yes, the names its is sweet.

This is very similar to facet/recorder too. I wonder if I can integrate this. Recorder is essentially a method probe. It records everthing that happens to it, building an internal parse tree. You can then pass a substitute object and apply the recoding to it. Or you can utilize the parse tree.

The only limitation of Recorder is with special operators, like if, &&, ||, etc. Since they are not true methods they can’t be recorded. (Too bad for Ruby.)

Simple Example:

   class Z
     def name ; 'George' ; end
     def age ; 12 ; end
   end
   z = Z.new
   r = Recorder.new
   q = proc { |x| (x.name == 'George') &
                  (x.age > 10) }
   x = q[r]
   x.__call__(z)

produces true. Here’s the code:

class Recorder
  # Privatize all kernel methods.
  private *instance_methods

  def initialize( msg=nil )
    @msg = msg
  end

  def inspect
    "&lt;Recorder #{@msg.inspect}&gt;" 
  end

  def __call__( orig )
    return orig unless @msg
    sym  = @msg[0]
    args = @msg[1..-1].collect do |a|
      Recorder === a ? a.__call__(orig) : a
    end
    obj  = args.shift
    obj.__send__( sym, *args )
  end

  def method_missing( sym, *args, &blk )
    object_class.new( [ sym, self, *args ] )
  end
end

Note that object_class == self.class.

11 Jul 2010 at 21:00

* do fancy stuff in your comment.

PREVIEW PANE