# Idiom I've not seen before

**URL:** <https://rubytalk.org/t/idiom-ive-not-seen-before/44331>\
**Category:** ruby-talk\
**Created:** [7 February 2008 03:55 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331 "2008-02-07T03:55:07Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rob\_Saul](https://avatars.discourse-cdn.com/v4/letter/r/7993a0/32.png) [@Rob\_Saul](https://rubytalk.org/u/Rob_Saul)\
**Post date:** [7 February 2008 03:55 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331/1 "2008-02-07T03:55:07Z")

</div>

I came across this :  
&nbsp;&nbsp;elements.sort\_by(&:position).each  
in something I've taken over. I thought sort\_by  
took a block. Obviously I'm missing something.  
Can anyone shed some light on this trick?

&nbsp;&nbsp;~Rob

---

<div class="post-metadata">

**Author:** ![Rob\_Biedenharn1](https://avatars.discourse-cdn.com/v4/letter/r/57b2e6/32.png) [@Rob\_Biedenharn1](https://rubytalk.org/u/Rob_Biedenharn1)\
**Post date:** [7 February 2008 04:04 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331/2 "2008-02-07T04:04:06Z")

</div>

You've found Symbol#to\_proc

That line is equivalent to:

elements.sort\_by {|e| e.send(:position) }.each

The "something" is a Rails project, isn't it?

== vendor/rails/activesupport/lib/active\_support/core\_ext/symbol.rb ==  
class Symbol  
&nbsp;&nbsp;&nbsp;# Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:

> **···**
>
> On Feb 6, 2008, at 10:55 PM, Rob Saul wrote:
> 
> > I came across this :  
> > &nbsp;&nbsp;elements.sort\_by(&:position).each  
> > in something I've taken over. I thought sort\_by  
> > took a block. Obviously I'm missing something.  
> > Can anyone shed some light on this trick?
> > 
> > &nbsp;&nbsp;~Rob
> 
> &nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;# # The same as people.collect { |p| p.name }  
> &nbsp;&nbsp;&nbsp;# people.collect(&:name)  
> &nbsp;&nbsp;&nbsp;#  
> &nbsp;&nbsp;&nbsp;# # The same as people.select { |p| p.manager? }.collect { |p| p.salary }  
> &nbsp;&nbsp;&nbsp;# people.select(&:manager?).collect(&:salary)  
> &nbsp;&nbsp;&nbsp;def to\_proc  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Proc.new { |\*args| args.shift.\_\_send\_\_(self, \*args) }  
> &nbsp;&nbsp;&nbsp;end  
> end
> 
> I don't know how you can send additional arguments however.
> 
> -Rob
> 
> Rob Biedenharn [http://agileconsultingllc.com](http://agileconsultingllc.com)  
> Rob@AgileConsultingLLC.com

---

<div class="post-metadata">

**Author:** ![Jeremy\_Kemper1](https://avatars.discourse-cdn.com/v4/letter/j/c6cbf5/32.png) [@Jeremy\_Kemper1](https://rubytalk.org/u/Jeremy_Kemper1)\
**Post date:** [7 February 2008 04:06 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331/3 "2008-02-07T04:06:50Z")

</div>

Sure. &:position == :position.to\_proc == proc { |element, \*args|  
element.position(\*args) }

So elements.sort\_by(&:position) is shorthand for sorting the elements  
by position.

jeremy

> **···**
>
> On 2/6/08, Rob Saul \<wyrd@code-gnomemad.org\> wrote:
> 
> > I came across this :  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elements.sort\_by(&:position).each  
> > in something I've taken over. I thought sort\_by  
> > took a block. Obviously I'm missing something.  
> > Can anyone shed some light on this trick?

---

<div class="post-metadata">

**Author:** ![Gavin\_Kistner3](https://avatars.discourse-cdn.com/v4/letter/g/dfb087/32.png) [@Gavin\_Kistner3](https://rubytalk.org/u/Gavin_Kistner3)\
**Post date:** [7 February 2008 17:59 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331/4 "2008-02-07T17:59:58Z")

</div>

Loosely-related aside:

I've been learning Io[1] recently. Io (like Lisp, I gather) allows  
lazy evaluation of method arguments. In Ruby terms, this would mean  
that I can write something like this:

&nbsp;&nbsp;# Ruby-esque pseudo-code; neither Io nor Ruby  
&nbsp;&nbsp;class Array  
&nbsp;&nbsp;&nbsp;&nbsp;def select  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result =   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.each{ |el| result \<\< el if el.sendArg(0) }  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end

&nbsp;&nbsp;my\_array.select( isCool? )  
&nbsp;&nbsp;my\_array.select( \> 5 )  
&nbsp;&nbsp;my\_array.select( roughlyEquals( jim.newSize ) )

In Io, the "isCool?" method/message isn't (necessarily) evaluated when  
you call the select method. Instead, you can perform some  
introspection on the parsed message tree for each argument and choose  
to ignore it, change it to a string, or send it as a message to any  
object you want.

To be clear, in the above, the "isCool?" message/method would be send/  
invoked on each array element. Or each element would be sent a  
"\>( 5 )" message.

The Symbol#to\_proc technique is clever, but not quite as clean as  
being able to write (in Io):  
&nbsp;&nbsp;elements sortBy( position )  
&nbsp;&nbsp;elements map( \* 2 )  
&nbsp;&nbsp;elements select( size \> 5 )

This same ability in Io allowed me to add a debugging method "p" (in  
homage of Ruby) that labels a value with the exact call you made. For  
example:

&nbsp;&nbsp;# In Io with my custom method (not Ruby)  
&nbsp;&nbsp;p( gk )  
&nbsp;&nbsp;#=\> gk is Person\_0x4de0d8:  
&nbsp;&nbsp;#=\> name = "Gavin Kistner"  
&nbsp;&nbsp;#=\> nick = "Phrogz""

&nbsp;&nbsp;p( gk name )  
&nbsp;&nbsp;#=\> gk name is Gavin Kistner

&nbsp;&nbsp;p( gk nick size )  
&nbsp;&nbsp;#=\> gk nick size is 6

[1] [http://www.iolanguage.com/](http://www.iolanguage.com/)

> **···**
>
> On Feb 6, 8:55 pm, Rob Saul \<w...@code-gnomemad.org\> wrote:
> 
> > I came across this :  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elements.sort\_by(&:position).each

---

<div class="post-metadata">

**Author:** ![Rob\_Saul](https://avatars.discourse-cdn.com/v4/letter/r/7993a0/32.png) [@Rob\_Saul](https://rubytalk.org/u/Rob_Saul)\
**Post date:** [7 February 2008 04:14 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331/5 "2008-02-07T04:14:24Z")

</div>

Jeremy Kemper wrote:

> Sure. &:position == :position.to\_proc == proc { |element, \*args|  
> element.position(\*args) }
> 
> So elements.sort\_by(&:position) is shorthand for sorting the elements  
> by position.
> 
> jeremy

thanks to both Jeremy and Rob for the enlightenment. And  
yes, it is a Rails project.

---

<div class="post-metadata">

**Author:** ![Ryan\_Davis1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/ryan_davis1/32/1848_2.png) [@Ryan\_Davis1](https://rubytalk.org/u/Ryan_Davis1)\
**Post date:** [7 February 2008 05:16 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331/6 "2008-02-07T05:16:14Z")

</div>

Buyer beware:

#!/usr/local/bin/ruby -w

# # of iterations = 10000  
# user system total real  
# null\_time 0.000000 0.000000 0.000000 ( 0.001561)  
# map 0.880000 0.000000 0.880000 ( 0.878500)  
# to\_proc 2.790000 0.000000 2.790000 ( 2.799291)

# # of iterations = 100000  
# user system total real  
# null\_time 0.020000 0.000000 0.020000 ( 0.013951)  
# map 8.730000 0.010000 8.740000 ( 8.766693)  
# to\_proc 27.960000 0.030000 27.990000 ( 28.001288)

require 'benchmark'

class Symbol  
&nbsp;&nbsp;&nbsp;def to\_proc  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Proc.new { |\*args| args.shift.\_\_send\_\_(self, \*args) }  
&nbsp;&nbsp;&nbsp;end  
end

a = (1..100).to\_a

raise "stupid" unless a.map { |n| n.to\_s } == a.map(&:to\_s)

max = (ARGV.shift || 1\_000\_000).to\_i

puts "# of iterations = #{max}"  
Benchmark::bm(20) do |x|  
&nbsp;&nbsp;&nbsp;x.report("null\_time") do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i in 0..max do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# do nothing  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;x.report("map") do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i in 0..max do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a.map { |n| n.to\_s }  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;x.report("to\_proc") do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i in 0..max do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a.map(&:to\_s)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end  
end

> **···**
>
> On Feb 6, 2008, at 20:04 , Rob Biedenharn wrote:
> 
> > You've found Symbol#to\_proc
> > 
> > That line is equivalent to:
> > 
> > elements.sort\_by {|e| e.send(:position) }.each

---

<div class="post-metadata">

**Author:** ![Clifford\_Heath5](https://avatars.discourse-cdn.com/v4/letter/c/7ab992/32.png) [@Clifford\_Heath5](https://rubytalk.org/u/Clifford_Heath5)\
**Post date:** [7 February 2008 22:39 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331/7 "2008-02-07T22:39:56Z")

</div>

Phrogz wrote:

> I've been learning Io[1] recently. Io (like Lisp, I gather) allows  
> lazy evaluation of method arguments.

...

> In Io, the "isCool?" method/message isn't (necessarily) evaluated when  
> you call the select method.

This is known as "call by name", as opposed to by reference or by value.  
It was, more than anything, the single thing that caused the most difficulty  
for the authors of Algol68 optimising compilers :-).

Niklaus Wirt once joked that Europeans (who know how to pronounce his name)  
called him by name, whereas Americans called him by value (nickel's worth).  
Maybe apocryphal, but funny :-).

Clifford Heath.

---

<div class="post-metadata">

**Author:** ![Deepak\_Gole](https://avatars.discourse-cdn.com/v4/letter/d/e274bd/32.png) [@Deepak\_Gole](https://rubytalk.org/u/Deepak_Gole)\
**Post date:** [8 February 2008 11:33 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331/8 "2008-02-08T11:33:35Z")

</div>

Hello Rob

&nbsp;&nbsp;We can send arguments, Following is the way, But it throws an error.

&nbsp;&nbsp;def to\_proc  
&nbsp;&nbsp;&nbsp;&nbsp;Proc.new { |\*args| args.shift.\_\_send\_\_(self, \*args) }  
&nbsp;&nbsp;end

&nbsp;&nbsp;arr.collect(&[:concat,"Rocking"])

\* \*sample.rb:41:in `\_\_send\_\_': [:concat, "dee"] is not a symbol  
(TypeError)  
&nbsp;&nbsp;&nbsp;&nbsp;from sample.rb:41:in `to\_proc'  
&nbsp;&nbsp;&nbsp;&nbsp;from sample.rb:51:in `collect'  
&nbsp;&nbsp;&nbsp;&nbsp;from sample.rb:51

But if we change the implementation of to\_proc then it works.

&nbsp;&nbsp;&nbsp;def to\_proc  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lambda {|target| target.send \*self}  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;arr.collect(&[:concat,"Rocking"])

o/p =\> ["rubyRocking", "railsRocking", "rjaxRocking"]

I don't know how.

> **···**
>
> On Feb 6, 2008 8:04 PM, Rob Biedenharn \<Rob@agileconsultingllc.com\> wrote:
> 
> > On Feb 6, 2008, at 10:55 PM, Rob Saul wrote:  
> > \> I came across this :  
> > \> elements.sort\_by(&:position).each  
> > \> in something I've taken over. I thought sort\_by  
> > \> took a block. Obviously I'm missing something.  
> > \> Can anyone shed some light on this trick?  
> > \>  
> > \> ~Rob
> > 
> > You've found Symbol#to\_proc
> > 
> > That line is equivalent to:
> > 
> > elements.sort\_by {|e| e.send(:position) }.each
> > 
> > The "something" is a Rails project, isn't it?
> > 
> > == vendor/rails/activesupport/lib/active\_support/core\_ext/symbol.rb ==  
> > class Symbol  
> > &nbsp;&nbsp;# Turns the symbol into a simple proc, which is especially useful  
> > for enumerations. Examples:  
> > &nbsp;&nbsp;#  
> > &nbsp;&nbsp;# # The same as people.collect { |p| p.name }  
> > &nbsp;&nbsp;# people.collect(&:name)  
> > &nbsp;&nbsp;#  
> > &nbsp;&nbsp;# # The same as people.select { |p| p.manager? }.collect { |p|  
> > p.salary }  
> > &nbsp;&nbsp;# people.select(&:manager?).collect(&:salary)  
> > &nbsp;&nbsp;def to\_proc  
> > &nbsp;&nbsp;&nbsp;&nbsp;Proc.new { |\*args| args.shift.\_\_send\_\_(self, \*args) }  
> > &nbsp;&nbsp;end  
> > end
> > 
> > I don't know how you can send additional arguments however.
> > 
> > -Rob
> > 
> > Rob Biedenharn [http://agileconsultingllc.com](http://agileconsultingllc.com)  
> > Rob@AgileConsultingLLC.com

---

<div class="post-metadata">

**Author:** ![ThoML](https://avatars.discourse-cdn.com/v4/letter/t/d78d45/32.png) [@ThoML](https://rubytalk.org/u/ThoML)\
**Post date:** [8 February 2008 14:14 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331/9 "2008-02-08T14:14:59Z")

</div>

> Io (like Lisp, I gather) allows lazy evaluation of method arguments.

Are you referring to Lisp's macro facility? AFAIK macros are usually  
expanded at load/compile time. Since everything is a s-expression in  
lisp, the macro gets its arguments as list and can process them. The  
macro call is then replaced with the result. Or something along this  
line.

It seems Io provides a similar facility to treat code as data, which  
is cool. Unfortunately I'm not able to compile it. IIRC Forth was able  
to do something similar too BTW (just a side-note).

Since ruby doesn't have this feature (unless you use parsetree and  
ruby2ruby maybe), the ruby equivalent are strings, I'd say. One could  
thus write something like:

&nbsp;&nbsp;&nbsp;&nbsp;class Array  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def select\_by(snippet)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rv =   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.each do |e|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rv \<\< e if e.instance\_eval '%s %s' % [e.inspect,  
snippet]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rv  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;a = [1,2,3,4,5]  
&nbsp;&nbsp;&nbsp;&nbsp;a.select\_by '\> 3'

Which is about the same as your io example. It would be nice of course  
to be able to have real macros that are expanded at load time so that  
one could write something like the following which is incorrect ruby  
syntax and would have to be rewritten before the parser tries to make  
sense out of it:

&nbsp;&nbsp;&nbsp;&nbsp;module Macros  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def select\_by(code)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%{select {|e| e #{code}}}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;a = [1,2,3,4,5]  
&nbsp;&nbsp;&nbsp;&nbsp;a.select\_by(\> 3)

This would require that macro names are unique though. But it's just a  
delirious day-dreaming anyway.

Regards,  
Thomas.

---

<div class="post-metadata">

**Author:** ![Martin\_DeMello](https://avatars.discourse-cdn.com/v4/letter/m/f17d59/32.png) [@Martin\_DeMello](https://rubytalk.org/u/Martin_DeMello)\
**Post date:** [7 February 2008 05:04 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331/10 "2008-02-07T05:04:37Z")

</div>

Also, I believe Symbol.to\_proc is making it into 1.9

martin

> **···**
>
> On Feb 7, 2008 4:14 AM, Rob Saul \<wyrd@code-gnomemad.org\> wrote:
> 
> > thanks to both Jeremy and Rob for the enlightenment. And  
> > yes, it is a Rails project.

---

<div class="post-metadata">

**Author:** ![botp1](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@botp1](https://rubytalk.org/u/botp1)\
**Post date:** [7 February 2008 05:35 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331/11 "2008-02-07T05:35:18Z")

</div>

that will change in ruby1.9 since to\_proc is builtin.  
eg, a run in windows,

C:\ruby1.9\bin\>.\ruby.exe test.rb 1\_000  
# of iterations = 1000  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user system total real  
null\_time 0.000000 0.000000 0.000000 ( 0.000000)  
map 0.203000 0.000000 0.203000 ( 0.203000)  
to\_proc 0.156000 0.000000 0.156000 ( 0.172000)

C:\ruby1.9\bin\>.\ruby.exe test.rb 10\_000  
# of iterations = 10000  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user system total real  
null\_time 0.016000 0.000000 0.016000 ( 0.015000)  
map 1.937000 0.000000 1.937000 ( 2.515000)  
to\_proc 1.610000 0.000000 1.610000 ( 1.954000)

C:\ruby1.9\bin\>.\ruby.exe test.rb 100\_000  
# of iterations = 100000  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user system total real  
null\_time 0.328000 0.000000 0.328000 ( 0.328000)  
map 19.344000 0.000000 19.344000 ( 24.953000)  
to\_proc 17.296000 0.015000 17.311000 ( 18.016000)

not bad, imho.  
kind regards -botp

> **···**
>
> On Feb 7, 2008 1:16 PM, Ryan Davis \<ryand-ruby@zenspider.com\> wrote:
> 
> > Buyer beware:
> > 
> > # # of iterations = 10000  
> > # user system total real  
> > # null\_time 0.000000 0.000000 0.000000 ( 0.001561)  
> > # map 0.880000 0.000000 0.880000 ( 0.878500)  
> > # to\_proc 2.790000 0.000000 2.790000 ( 2.799291)
> > 
> > # # of iterations = 100000  
> > # user system total real  
> > # null\_time 0.020000 0.000000 0.020000 ( 0.013951)  
> > # map 8.730000 0.010000 8.740000 ( 8.766693)  
> > # to\_proc 27.960000 0.030000 27.990000 ( 28.001288)

---

<div class="post-metadata">

**Author:** ![Thomas\_Wieczorek](https://avatars.discourse-cdn.com/v4/letter/t/e47c2d/32.png) [@Thomas\_Wieczorek](https://rubytalk.org/u/Thomas_Wieczorek)\
**Post date:** [7 February 2008 05:13 UTC](https://rubytalk.org/t/idiom-ive-not-seen-before/44331/12 "2008-02-07T05:13:43Z")

</div>

Yes, it is in.  
Raganwald has a good blog entry about it, he also mentions  
String#to\_proc:  
[http://weblog.raganwald.com/2007/11/fun-with-symboltoproc.html](http://weblog.raganwald.com/2007/11/fun-with-symboltoproc.html)

> **···**
>
> On Thu, Feb 7, 2008 at 6:04 AM, Martin DeMello \<martindemello@gmail.com\> wrote:
> 
> > Also, I believe Symbol.to\_proc is making it into 1.9
