# How does something like ...sort\_by(&:f) actually manage to function?

**URL:** <https://www.ruby-forum.com/t/how-does-something-like-sort-by-f-actually-manage-to-function/159584>\
**Category:** Rails\
**Created:** [February 6, 2009, 1:08am UTC](https://www.ruby-forum.com/t/how-does-something-like-sort-by-f-actually-manage-to-function/159584 "2009-02-06T01:08:01Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kenneth\_McDonald](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/dc4da7/32.png) [@Kenneth\_McDonald](https://www.ruby-forum.com/u/Kenneth_McDonald)\
**Post date:** [February 6, 2009, 1:08am UTC](https://www.ruby-forum.com/t/how-does-something-like-sort-by-f-actually-manage-to-function/159584/1 "2009-02-06T01:08:01Z")

</div>

I’ve seen a claim on the web that &:f is just Ruby shorthand for &proc  
{ |i| i.f }, but I’ve certainly never been able to get this &:f  
notation to work in standard ruby.

Thanks,  
Ken

---

<div class="post-metadata">

**Author:** ![Kenneth\_McDonald](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/dc4da7/32.png) [@Kenneth\_McDonald](https://www.ruby-forum.com/u/Kenneth_McDonald)\
**Post date:** [February 6, 2009, 1:13am UTC](https://www.ruby-forum.com/t/how-does-something-like-sort-by-f-actually-manage-to-function/159584/2 "2009-02-06T01:13:53Z")

</div>

It is not possible in “plain” ruby because Rails extends the Symbol  
class with the possibility of converting it into a Proc (that’s what  
happens when you precede something with a &). From the Rails source  
code:

unless :to\_proc.respond\_to?(:to\_proc)  
class Symbol  
# Turns the symbol into a simple proc, which is especially useful  
for enumerations. Examples:  
#  
# # The same as people.collect { |p| p.name }  
# people.collect(&:name)  
#  
# # The same as people.select { |p| p.manager? }.collect { |p|  
p.salary }  
# people.select(&:manager?).collect(&:salary)  
def to\_proc  
Proc.new { |\*args| args.shift. **send** (self, \*args) }  
end  
end  
end

And it does come very handy indeed.  
Balint

On Feb 6, 1:07 am, Kenneth McDonald [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![Kenneth\_McDonald](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/dc4da7/32.png) [@Kenneth\_McDonald](https://www.ruby-forum.com/u/Kenneth_McDonald)\
**Post date:** [February 6, 2009, 2:25am UTC](https://www.ruby-forum.com/t/how-does-something-like-sort-by-f-actually-manage-to-function/159584/3 "2009-02-06T02:25:50Z")

</div>

On 6 Feb 2009, at 00:13, removed\_email\_address@domain.invalid wrote:

> It is not possible in “plain” ruby because Rails extends the Symbol  
> class with the possibility of converting it into a Proc (that’s what  
> happens when you precede something with a &). From the Rails source  
> code:

Although it’s worth noting that Symbol#to\_proc is in newer versions of  
ruby (1.9 and 1.8.7 IIRC)

Fred

---

<div class="post-metadata">

**Author:** ![Kenneth\_McDonald](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/dc4da7/32.png) [@Kenneth\_McDonald](https://www.ruby-forum.com/u/Kenneth_McDonald)\
**Post date:** [February 6, 2009, 4:40pm UTC](https://www.ruby-forum.com/t/how-does-something-like-sort-by-f-actually-manage-to-function/159584/4 "2009-02-06T16:40:22Z")

</div>

Thank you!

Ken

---

<div class="post-metadata">

**Author:** ![Kenneth\_McDonald](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/dc4da7/32.png) [@Kenneth\_McDonald](https://www.ruby-forum.com/u/Kenneth_McDonald)\
**Post date:** [February 6, 2009, 4:59pm UTC](https://www.ruby-forum.com/t/how-does-something-like-sort-by-f-actually-manage-to-function/159584/5 "2009-02-06T16:59:08Z")

</div>

OK, I see how this works now, but I can’t figure out how to get extra  
args in  
there, i.e. something like [1, 2, 3].collect(&:modulo, 2) doesn’t work  
because  
it’s improper Ruby syntax. I assume there’s a reason extra args are  
allowed,  
so could someone give a brief illustration of the calling convention?

Thanks in advance,  
Ken

---

<div class="post-metadata">

**Author:** ![Kenneth\_McDonald](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/dc4da7/32.png) [@Kenneth\_McDonald](https://www.ruby-forum.com/u/Kenneth_McDonald)\
**Post date:** [February 6, 2009, 5:29pm UTC](https://www.ruby-forum.com/t/how-does-something-like-sort-by-f-actually-manage-to-function/159584/6 "2009-02-06T17:29:42Z")

</div>

On 6 Feb 2009, at 15:58, Kenneth McDonald wrote:

> OK, I see how this works now, but I can’t figure out how to get extra  
> args in  
> there, i.e. something like [1, 2, 3].collect(&:modulo, 2) doesn’t work  
> because  
> it’s improper Ruby syntax. I assume there’s a reason extra args are  
> allowed,  
> so could someone give a brief illustration of the calling convention?

I don’t think you can - you just have to use the longhand syntax in  
those cases.

Fred

---

<div class="post-metadata">

**Author:** ![Kenneth\_McDonald](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/dc4da7/32.png) [@Kenneth\_McDonald](https://www.ruby-forum.com/u/Kenneth_McDonald)\
**Post date:** [February 6, 2009, 6:39pm UTC](https://www.ruby-forum.com/t/how-does-something-like-sort-by-f-actually-manage-to-function/159584/7 "2009-02-06T18:39:37Z")

</div>

The first of the parameters passed to the block is the object that is  
sent the message designated by the symbol. (Or in other words, the  
method designated by the symbol is called on the object that is the  
first parameter).

So people.collect(&:name) works because the collect iterator yields a  
member of the people enumerable at each pass. Plus that object needs  
to have name method. The important part to understand is that any  
extra parameters the iterator yields to the block will be passed to  
the method. In the above case, there is none, because collect only  
yields one member, nothing more. I’ll give you an (very-convoluted)  
example because it is hard to understand without one:

RND\_TOP = 10  
class Array  
def select\_with\_random  
selected = []  
self.each do |e|  
selected \<\< e if yield e, rand(RND\_TOP)  
end  
selected  
end  
end

numbers = Array.new(5) { rand(RND\_TOP) }  
above = numbers.select\_with\_random(&:\>)  
puts “numbers that are above another random number: #{above.inspect}}”

So I added a select iterator to the Fixnum class which not only yields  
an element but also a random number. That random number is the extra  
parameter that will be passed to the method designated by the symbol,  
in this case, \>. So iterating through random numbers, it will select  
those that are bigger than another random number (no sense at all, I  
know). The \> method needs one parameter and it gets it.

I am sure that this can have actual, real world uses, too, I just  
could not find out something realistic right now.

Balint

On Feb 6, 5:28 pm, Frederick C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
