« Enterprise Integration with Ruby goes Beta | Main | The First Rails Studio »

November 03, 2005

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83451c41c69e200d83572a02869e2

Listed below are links to weblogs that reference Symbol#to_proc:

Comments

Claudio Harringer

Nice hack. But there's a case in that it does not behave as expected.

I got surprised when handling arrays. Simple example (using Ruby/Extensions):
[[1,2], [3,4,5]].map(&:size)
I expected [2, 3] but it resulted in an ArgumentError, because of trying to call "1.send(:size,2)" and "3.send(:size,[3,4,5])" instead of "[1,2].send(:size)" and "[3,4,5].send(:size)".

This happens because of Ruby's way assigning arrays to multiple variables. A small change makes the hack more robust:

class Symbol
def to_proc
proc { |*args| args[0].send(self, *args[1...args.size]) }
end
end

I considered these three test cases:

%w{john terry fiona}.map(&:capitalize)
[5,6,2].inject(&:+)
[[0,1], [2,3,4]].map(&:size)

All three work as expected with my version. The Ruby/Extensions version on the other hand screws up the last one. And it's easy to make a (too) simple to_proc which screws up the second one.

weyus

This is very cool looking, but it is slow as hell.

http://www.ruby-forum.com/topic/161089

eno

Hey dave,

thanks to that article I finally understood the *args multiple parameters thingy. Thanks for that!

Besides, I found that creating a Proc object for each invocation may cause a serious memory and runtime penalty. I thought about caching the Proc inside the Symbol, i.e.

def to_proc
@to_proc ||= Proc.new { |*args| args.shift.__send__(self, *args) }
end

As far as I can see this should work just fine. But if a Proc bears some invisible luggage, like a thread environment or such, this would fail, of course. So, given your ruby experience: Would you say that approach is safe?

I have a post on my blog that goes into that in more detail: http://1rad.wordpress.com/2008/11/10/0x0a-some-optimization-hacks/

Tom Swindell

I just decided to do a little twist on this lovely Symbol#to_proc magic:

class Array
def to_proc
proc {|recv, *args| inject(recv) {|i,j| i.send(j, *args)}}
end
end

Perfect for:
array_of_symbols.map(&[:to_s, :capitalize]).join(', ')

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been posted. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

Now in Beta

  • Programming Ruby, 3rd Edition
    Third Edition, Covering Ruby 1.9, now available
My Photo

Pragmatic Stuff

Photos

  • www.flickr.com
    This is a Flickr badge showing public photos from pragdave tagged with pragdave_badge. Make your own badge here.

Site Search

  • Google Search

    The web
    PragDave