What do you call the &: operator in Ruby? [duplicate] - ruby

This question already has answers here:
Closed 13 years ago.
Possible Duplicates:
Ruby/Ruby on Rails ampersand colon shortcut
What does map(&:name) mean in Ruby?
I was reading Stackoverflow and stumbled upon the following code
array.map(&:to_i)
Ok, it's easy to see what this code does but I'd like to know more about &: construct which I have never seen before.
Unfortunately all I can think of is "lambda" which it is not. Google tells me that lambda syntax in Ruby is ->->(x,y){ x * y }
So anyone knows what that mysterious &: is and what it can do except calling a single method?

There's a few moving pieces here, but the name for what's going on is the Symbol#to_proc conversion. This is part of Ruby 1.9 and up, and is also available if you use later-ish versions of Rails.
First, in Ruby, :foo means "the symbol foo", so it's actually two separate operators you're looking at, not one big &: operator.
When you say foo.map(&bar), you're telling Ruby, "send a message to the foo object to invoke the map method, with a block I already defined called bar". If bar is not already a Proc object, Ruby will try to make it one.
Here, we don't actually pass a block, but instead a symbol called bar. Because we have an implicit to_proc conversion available on Symbol, Ruby sees that and uses it. It turns out that this conversion looks like this:
def to_proc
proc { |obj, *args| obj.send(self, *args) }
end
This makes a proc which invokes the method with the same name as the symbol. Putting it all together, using your original example:
array.map(&:to_i)
This invokes .map on array, and for each element in the array, returns the result of calling to_i on that element.

Related

How can Ruby transform a method into a symbol as argument?

The respond_to? method takes as argument, a method to be checked, but as a symbol.
Why as symbol? And how does ruby convert the method into a symbol?
There's no magic. Methods are attached to objects by their name, which is a symbol. In fact, Math.sin(2) is basically a shorthand for Math.send(:sin, 2) ("send message :sin to Math object, with parameter 2"). You can also access methods itself: Math.method(:sin) will give you the associated Method object (whose name, Math.method(:sin).name, is of course :sin), and Math.methods will list all implemented methods' names. Math.respond_to?(:sin) can basically be rewritten as Math.methods.include?(:sin) (this is simplified, as it ignores respond_to_missing?, but... close enough for this discussion).
Think of it this way. You go to a friend's house, and their mother answers the door. You ask, "Hello, is Tim here?" You don't need to actually drag your friend to the door and ask "Hello, is this individual here?" The name works just as well. :)
EDIT:
Hmmm that's confusing right now for me. What does named mean exactly? I mean maybe with a little example. I call it with array.each. When does the "name" :each come into play then?
I am not sure how to explain it better. Methods have names, just like people have names. When you say array.each, it is sending the message :each to the object that is contained in the variable array, pretty much exactly what array.send(:each) would do. Methods are pieces of code attached to objects via their names: when an object receives a message, it runs the piece of code that is associated with that message.
Specifically, in the standard Ruby implementation, objects of class Array, when they receive the message :each, will invoke the C function rb_ary_each that is defined in the Ruby source code, and linked to the message :each using rb_define_method(rb_cArray, "each", rb_ary_each, 0) (also in the Ruby source code).
Inside Ruby, there are basically two equivalent ways to define methods. These two are equivalent:
class Foo
def bar
puts "hello"
end
end
class Foo
define_method(:bar) do
puts "hello"
end
end
Both of them do the same thing: associate the message :bar with the piece of code do puts "hello" end. When :bar is received by a Foo (whether through Foo.send(:bar) or by Foo.bar), this piece of code is run.

Are "begin" and "end" reserved words or not?

I'm kind of confused about reserved words in Ruby.
"The Ruby Programming Language", co-authored by Matz, says that begin and end are reserved words of the language. They're certainly used syntactically to mark out blocks.
However, range objects in the language have methods named begin and end, as in
(1..10).end
=> 10
Now, testing this out, I find that, indeed, I can define methods named "begin" and "end" on objects, though if I try to name a variable "begin" it fails. (Here's a sample of using it as a method name, it actually works...:)
class Foo
def begin
puts "hi"
end
end
Foo.new.begin
So, I suppose I'm asking, what actually is the status of reserved words like this? I would have imagined that they couldn't be used for method names (and yet it seems to work) or that at the very least it would be terrible style (but it is actually used in the core language for the Range class).
I'm pretty confused as to when they're allowed to be used and for what. Is there even documentation on this?
Yes, they are reserved words. Yes, they can be used for method names. No, you can't call them without an explicit receiver. It's probably not a good idea anyway.
class Foo
def if(foo)
puts foo
end
end
Foo.new.if("foo") # outputs foo, returns nil
Update: Here's a quote from "The Ruby Programming Language", by Matz (the creator of Ruby) himself:
In most languages, these words would be called “reserved words” and
they would be never allowed as identifiers. The Ruby parser is
flexible and does not complain if you prefix these keywords with #,
##, or $ prefixes and use them as instance, class, or global variable
names. Also, you can use these keywords as method names, with the
caveat that the method must always be explicitly invoked through an
object.
When they are given in a form that is unambiguously a method call, you can use them. If you have a period in front of it .begin or have parentheses after is begin(), then it is unambiguously a method call. When you try to use it as a variable begin, it is ambiguous (in principle).
Actually, as Perry, notes, begin() might be tricky. I checked with irb with Ruby 1.9.3, and the following strange thing happens:
irb(main):001:0> def begin(foo)
irb(main):002:1> puts 'a'
irb(main):003:1> end
=> nil
irb(main):004:0> begin(3)
irb(main):005:1>
irb(main):006:1* end
=> 3
It is not defined, and what looks like a method call might be just a block returning the last-evaluated 3. But the lines around def begin(foo) remains mystery.

in ruby is there a distinction between a method and function [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Ruby functions vs methods
Im just reading some ruby documentation and t seems to use the term function and method in an interchangeable way, i jut wanted to know if there is any distinction?
the docs im looking at refer to this as a function:
def saysomething()
puts "Hello"
end
saysomething
and this a method:
def multiply(val1, val2 )
result = val1 * val2
puts result
end
this may be a something semantic but i wanted to check
jt
In Ruby, there are not two separate concepts of methods and functions. Some people still use both terms, but in my opinion, using "function" when talking about Ruby is incorrect. There do not exist executable pieces of code that are not defined on objects, because there is nothing in Ruby that is not an object.
As Dan pointed out, there's a way to call methods that makes them look like functions, but the underlying thing is still a method. You can actually see this for yourself in IRB with the method method.
> def zomg; puts "hi"; end
#=> nil
> method(:zomg)
#=> #<Method: Object#zomg>
> Object.private_instance_methods.sort
#=> [..., :zomg]
# the rest of the list omitted for brevity
So you can see, the method zomg is an instance method on Object, and is included in Object's list of private instance methods.

`&:views_count` in `Post.published.collect(&:views_count)` [duplicate]

This question already has answers here:
What does map(&:name) mean in Ruby?
(17 answers)
Closed 8 years ago.
I saw the code from here
Post.published.collect(&:views_count)
I guess it equals to
.collect { |p| p.views_count }
But I never saw this usage before, does this have a name? Where can I find more information about it?
This is actually a rather clever hack made it into ruby 1.9.
Basically, & in front of a variable in ruby coerces it into a proc. It does that by calling to_proc. Some clever fellow (first time I saw this was in _whys code, but I won't credit him cause I don't know if he came up with it) added a to_proc method to Symbol, that is essentially {|obj| obj.send self}.
There aren't many coercians in ruby, but it seems like all of them are mostly used to do hacks like this (like !! to coerce any type into a boolean)
It's a use of Symbol#to_proc. The & operator turns a Proc object into a block, and because Ruby 1.8.7 and newer implement Symbol#to_proc, it can be used with a symbol like :views_count. And yes, it's equivalent to {|p| p.views_count}.

What exactly is `&:capitalize` in Ruby?

I just read this answer Converting upper-case string into title-case using Ruby.
There is the following line of code
"abc".split(/(\W)/).map(&:capitalize).join
What exactly is &:capitalize? Before I had put this into irb myself, I would have told you, it's not valid ruby syntax. It must be some kind of Proc object, because Array#map normaly takes a block. But it isn't. If I put it into irb alone, I get syntax error, unexpected tAMPER.
foo(&a_proc_object) turns a_proc_object into a block and calls foo with that block.
foo(&not_a_proc_object) calls to_proc on not_a_proc_object and then turns the proc object returned by to_proc into a block and calls foo with that block.
In ruby 1.8.7+ and active support Symbol#to_proc is defined to return a proc which calls the method named by the symbol on the argument to the proc.
It's Symbol#to_proc: see http://pragdave.pragprog.com/pragdave/2005/11/symbolto_proc.html
map(&:capitalize) is exactly the same as map { |x| x.capitalize }.
The ampersand is syntactic sugar that does a whole bunch of code generation with the to_proc message. See http://blog.codahale.com/2006/08/01/stupid-ruby-tricks-stringto_proc/

Resources