How is this "map" working? [duplicate] - ruby

This question already has answers here:
What does map(&:name) mean in Ruby?
(17 answers)
Closed 9 years ago.
Could you explain what the code below is doing:
resp = s3.list_buckets
puts resp.buckets.map(&:name)
My question is specific to map. I am not able to understand how map is being used here. Also, what does (&:name) mean?
I referred map documentation. However, I'm not able to correlate it with the map in the code above. Per the documentation, Map should be followed by a {}, but it is followed by a () in the code above.
In perl context, map will work on an array/list and will return a new array/list. So, it seems to be doing something similar here as well, but I cannot decode that.
Any pointers to documentation would be helpful.

map is an alias for collect
map(&:name) is shortcut for map {|x| x.name }
map expects a block. & calls to_proc on the object, and passes it as a block and Symbol has to_proc implemented. Refer docs for more info

& of (&:name) means what follows it should be a Proc object and will be converted to a code block.
Since & expects a Proc object, :name will be converted to a Proc object, this is done by calling :name.to_proc.
After :name is converted to a Proc object, & then converts the resulting Proc object to a code block and gives the code block to map.
In summary, there are totally two type conversions occured, one is converting a symbol to a Proc object, the other is converting a Proc object to a code block.

Related

What does the `&:symb` do? [duplicate]

This question already has answers here:
What does map(&:name) mean in Ruby?
(17 answers)
Closed 4 years ago.
I've seen an example of how to sort a string. To sort case insensitively:
str.chars.sort(&:casecmp).join
#=> "ginrSt"
I'm curious about (&:casecmp). I found that for example:
arr.map(&:name)
is shorthand for
arr.map(&:name.to_proc)
which is same with
arr.map{|el| el.name}
I know the & (ampersand) tries to convert symbol to proc, and pass it as a block to a method. I do not understand how this would work for sort method, which is supposed to compare two values. Would it be as follows?
str.chars.sort{|a, b| a.casecmp ;b.casecmp}.join
It wouldn't be helpful since soft needs a block to return an integer and casecmp needs an argument. (Or is it called parameter in that case?) To me, it looks more like this:
str.chars.sort{|a, b| a.casecmp(b)}.join
How does &:casecmp know to take one of |a, b| as a caller and the other one as an argument? I wouldn't guess it that it is an option.
If more than one parameter is passed to your block, the proc created by Symbol#to_proc uses the additional block parameters as parameters to the method call.
http://phrogz.net/symbol-to-proc-with-multiple-arguments
So, what's really happening is, sort(&:casecmp) is converted to:
sort {|a,b| a.casecmp(b) }
because sort takes two parameters.

Ruby code what does "&:" do here [duplicate]

This question already has answers here:
What does map(&:name) mean in Ruby?
(17 answers)
Closed 5 years ago.
def reverse_words(s)
s.split.map(&:reverse).join(' ')
end
This code reverses each word in a sentence. But I do not understand "&:" in the code. Can someone explain that to me?
map expects a code block that takes one argument. What you would normally do is to call reverse on that argument:
map {|elt| elt.reverse }
With the & syntax you can shorten this to
map(&:reverse)
The colon is there to make a symbol out of the name reverse.
The & means that reverse is referencing a function, not a block.
This method assumes that the caller will pass it a String object.
First the method #splits the string on whitespaces into an array (if the string has no whitespaces it creates an array with the string as the only element)
Calls the Array#map method on the new array and passes it a reference to the String#reverse method.
The & tells the map method that the input is a reference to a method and not a standard block

When do you use a block as an object to be passed around? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Most of the examples I see are trivial, and I'm not sure what this adds to the language. I get why you would use blocks in Objective-C for handling callbacks or in Javascript with closures used as callbacks for timers, but I'm not sure what I'd be using blocks for in Ruby. Is it something that could be used instead of a function with something like inject?
Ruby uses blocks all over, it's one of the most ubiquitous features of the language. It is basically an optimised case of a function-as-a-value. A real function object, like in JavaScript is in Ruby an instance of a Proc class. A block is not an object, and thus avoids some of the overheads that objecthood incurs. The reasoning is, in almost all cases where you want to pass a function as an argument, you'll only be passing one, and you'll want to define it right there on the spot, so why not optimise, and make things a bit syntactically nicer?
This is a block:
[1, 2, 3].each do |i|
puts i
end
This is a function:
func = Proc.new do |i|
puts i
end
[1, 2, 3].hypothetical_each(func)
You can see that even defining a functional value involves a block (as a parameter to Proc constructor).
You normally use a block in inject, not a function. You use it in pretty much every loop structure in Ruby (while is very uncommonly used).
You also use blocks to construct domain-specific languages like Sinatra:
get 'index.html' do
"Hello World"
end
or Rspec:
describe "addition" do
it "should add two numbers together" do
(1+2).should equal(3)
end
end
Learn blocks well, because you can't read, nor write Ruby well without them.
The secret to blocks in ruby is held in the nature of ruby's design.
Ruby was designed with an object modal where method calls are sent as 'messages' to the object and return values are responses. In ruby (unlike python and some other languages), functions and methods are NOT object themselves.
Blocks are ruby's way of allowing function-like messages in this modal and are key to how ruby handles iteration in general.
Someone please correct me if I'm wrong but I believe it is in fact impossible to do any iteration in ruby without creating a block or using a while statement
and in fact the for i in object notation is just syntax shorthand for access to the object each method.
ie.
for i in 1..5
#do stuff with i
end
Is executed exactly the same as:
1..5.each do |i|
#do stuff with i
end
By the ruby VM where the Range object 1..5 (which includes the ruby standart lib Enumerable module) yields it's elements to the passed block
Under the hood this operation looks something like this (note this is a simplified version that fails to take into account the ... exclusive and .. inclusive version of range)
class Range
def init(start, end)
#start = start
#end = end
end
def each
i = #start
while i < #end
yield i
i += 1
end
end
end
So when that for loop is called it creates a range object obj = Range.new(1,5) then sends a message to the object obj.send(:each, &block) and inside the each method is use a while loop and yields to the block
TL;DR
Ruby uses block internally as they are critical to it's very design, without them the language itself would not work with it's message => object => response modal.
So you should not ask: "Why should I use blocks?" Because you can't write a ruby program without them.
Instead you should ask: "How is a block in ruby different than a block in Objective-C and Javascript?" Because they ARE a different.
I cant speak for Objective-C but in JavaScript a block is very much an object. It's a container for code that other objects can pick up and use to do whatever it needs to, the block doesnt even have to relate to the object using it.
In ruby a block is more like a set of instruction an object receives in the mail that it uses on itself (which it then passes to the mail man the next time he comes around)

`&: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 do you call the &: operator in Ruby? [duplicate]

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.

Resources