Symbol#to_proc with arguments

M

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?
 
J

James Coglan

[Note: parts of this message were removed to make it a legal post.]

2009/7/8 Max Williams said:
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"]]
 
D

David A. Black

Hi --

2009/7/8 Max Williams said:
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') }

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'))

though either way I admit it doesn't feel necessary or adviseable to
me.


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Now available: The Well-Grounded Rubyist (http://manning.com/black2)
Training! Intro to Ruby, with Black & Kastner, September 14-17
(More info: http://rubyurl.com/vmzN)
 
J

James Coglan

[Note: parts of this message were removed to make it a legal post.]

2009/7/8 David A. Black said:
Hi --


On Wed, 8 Jul 2009, James Coglan wrote:

2009/7/8 Max Williams said:
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

%w[apple banana peach plum pear].collect &[:split, 'l']
#=> [["app", "e"], ["banana"], ["peach"], ["p", "um"], ["pear"]]

It's still not a huge saving over the explicit block, but I think it's worth
knowing how you can manipulate the language for times when it becomes
*really* useful.
 
M

Max Williams

Thanks guys.

I would automatically shy away from overriding to_proc as it seems like
the sort of thing that would slip a timebomb under my app :)

I was just wondering if it was possible as is, not because it's soooo
much work to write out a proper block, but simply out of curiosity. "No
you can't" is a good enough answer for me.

What got me wondering actually was using a Ramaze based framework and
missing lots of nice ways that rails extends the core ruby classes (with
Symbol#to_proc being an example). Is it easy to just require all of
these gems/modules and get the same stuff back? I guess i should answer
my own question by just trying it, so feel free to just say "why not try
it and see?". :)

thanks again
max
 
J

James Coglan

[Note: parts of this message were removed to make it a legal post.]

2009/7/8 James Coglan said:
2009/7/8 David A. Black <[email protected]>

Hi --
On Wed, 8 Jul 2009, James Coglan wrote:

2009/7/8 Max Williams said:
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
 
J

James Coglan

[Note: parts of this message were removed to make it a legal post.]
What got me wondering actually was using a Ramaze based framework and
missing lots of nice ways that rails extends the core ruby classes (with
Symbol#to_proc being an example). Is it easy to just require all of
these gems/modules and get the same stuff back? I guess i should answer
my own question by just trying it, so feel free to just say "why not try
it and see?". :)


require 'active_support'
 
R

Robert Dober

Thanks guys.

I would automatically shy away from overriding to_proc as it seems like
the sort of thing that would slip a timebomb under my app :)

I was just wondering if it was possible as is, not because it's soooo
much work to write out a proper block, but simply out of curiosity. "No
you can't" is a good enough answer for me.

What got me wondering actually was using a Ramaze based framework and
missing lots of nice ways that rails extends the core ruby classes (with
Symbol#to_proc being an example). Is it easy to just require all of
these gems/modules and get the same stuff back? I guess i should answer
my own question by just trying it, so feel free to just say "why not try
it and see?". :)
I am sharing your laziness ;) and you might want to check out Labrador
http://rubyforge.org/frs/?group_id=3D3824&release_id=3D33008 which will
allow you to do things like:

irb(main):001:0> %w{ a,b c,d e,f }.map( :split, "," )
=3D> [["a", "b"], ["c", "d"], ["e", "f"]]

They idea was not to change #to_proc but to enhance the Enumerable behavior=
 
D

David A. Black

Hi --

2009/7/8 David A. Black said:
Hi --


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.

I don't think that's right. The existing semantics don't include any
arguments. So my reaction would be: isn't that going to raise an
exception? Then I'd have to figure out that you'd probably overridden
then method.
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


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.

Just rename your override of #to_proc to #to_proc_with_args (or
whatever). It will still work the same. (You're dispensing with the
automatic calling of #to_proc anyway.)
So, an alternative:

class Array
def to_proc
lambda { |o| o.__send__(first, *self[1..-1]) }

That doesn't differ from __send__(*self), does it?


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Now available: The Well-Grounded Rubyist (http://manning.com/black2)
Training! Intro to Ruby, with Black & Kastner, September 14-17
(More info: http://rubyurl.com/vmzN)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,278
Latest member
BuzzDefenderpro

Latest Threads

Top