From: James Coglan Date: 2009-07-08T20:41:04+09:00 Subject: Re: Symbol#to_proc with arguments --0016368e2bc940f070046e303667 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit 2009/7/8 James Coglan > > > 2009/7/8 David A. Black > > Hi -- >> >> >> On Wed, 8 Jul 2009, James Coglan wrote: >> >> 2009/7/8 Max Williams >>> >>> hey folks >>>> >>>> I've often wondered if i can use Symbol#to_proc with arguments - reading >>>> Dave Thomas's explanation on this page >>>> http://pragdave.pragprog.com/pragdave/2005/11/symbolto_proc.html it >>>> looks like i would be able to do this: >>>> >>>> array = %w(apple banana peach plum pear) >>>>>> >>>>> => ["apple", "banana", "peach", "plum", "pear"] >>>> >>>>> array.collect(&:split, 'l') >>>>>> >>>>> SyntaxError: compile error >>>> (irb):12: syntax error, unexpected ',', expecting ')' >>>> array.collect(&:split, 'l') >>>> ^ >>>> (irb):12: syntax error, unexpected ')', expecting $end >>>> from (irb):12 >>>> >>>> But it fails as you can see. Trying to fully grasp what's going on with >>>> Symbol#to_proc makes my head hurt a little bit (it is only 9.16am here) >>>> and i'm clearly not getting it. Can anyone explain? >>>> >>> >>> >>> >>> The block argument (prefixed with '&') must be the last argument in the >>> list >>> when calling a method, so passing 'l' in your example is not valid >>> syntax. >>> You could rewrite Symbol#to_proc to take arguments, and call #to_proc >>> explicitly when calling #collect. >>> >>> class Symbol >>> def to_proc(*args) >>> lambda { |o| o.__send__(self, *args) } >>> end >>> end >>> >>> %w[apple banana peach plum pear].collect &:split.to_proc('l') >>> #=> [["app", "e"], ["banana"], ["peach"], ["p", "um"], ["pear"]] >>> >> >> That's going to be incomprehensible, except by guesswork, to anyone >> who doesn't know that you've modified Symbol. It also undoes whatever >> benefit you might get from the &obj idiom automatically calling >> #to_proc. I'd just do: >> >> array.map {|e| e.split('l') } > > > I wouldn't say it's incomprehensible since it maintains the existing > semantics of Symbol#to_proc. The explicit block version is shorter though, > and will likely perform better. > > No real reason to second-guess Ruby on this. If you really want to >> modify Symbol, creating an entirely new method would probably be >> better: >> >> array.map(&:split.to_argument_accepting_proc('l')) > > > The real problem here is that a Symbol contains a single piece of > information, whereas we want to build a Proc from several pieces of > information. So, an alternative: > > class Array > def to_proc > lambda { |o| o.__send__(first, *self[1..-1]) } > end > end > Silly me, this can actually be written simply as: class Array def to_proc lambda { |o| o.__send__(*self) } end end --0016368e2bc940f070046e303667--