« 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(', ')

The comments to this entry are closed.

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.