Other Ruby Map Shorthand Notation - ruby

I am aware of the shorthand for map that looks like:
[1, 2, 3, 4].map(&:to_s)
> ["1", "2", "3", "4"]
I was told this is shorthand for:
[1, 2, 3, 4].map{|i| i.to_s}
This makes perfect sense. My question is this: It seems there should be an easier way to write:
[1, 2, 3, 4].map{|x| f.call(x)}
for some procedure f. I know the way I just typed isn't all that long to begin with, but I'd contend that neither is the previous example for which the shorthand exists. This example just seems like the complement to the first example: Rather than calling i's to_s method for every i, I wish to call f for every x.
Does such a shorthand exist?

Unfortunately this shorthand notation (which calls "Symbol#to_proc") does not have a way to pass arguments to the method or block being called, so you couldn't even do the following:
array_of_strings.map(&:include, 'l') #=> this would fail
BUT, you are in luck because you don't actually need this shortcut to do what you are trying to do. The ampersand can convert a Proc or Lambda into a block, and vice-versa:
my_routine = Proc.new { |str| str.upcase }
%w{ one two three }.map &my_routine #=> ['ONE', 'TWO', 'THREE']
Note the lack of the colon before my_routine. This is because we don't want to convert the :my_routine symbol into a proc by finding the method and calling .method on it, rather we want to convert the my_routine Proc into a block and pass it to map.
Knowing this, you can even map a native Ruby method:
%w{ one two three }.map &method(:p)
The method method would take the p method and convert it into a Proc, and the & converts it into a block that gets passed to map. As a result, each item gets printed. This is the equivalent of this:
%w{ one two three }.map { |s| p s }

As of Ruby 2.7, numbered parameters (_1, _2, etc) are supported. This syntax can be cryptic, especially with more than one parameter, but it can be useful for simple situations.
[1, 2, 3, 4].map { f.call(_1) }

Related

Can you pass arguments to the method in `&method(:method_ name)` in ruby? [duplicate]

I am aware of the shorthand for map that looks like:
[1, 2, 3, 4].map(&:to_s)
> ["1", "2", "3", "4"]
I was told this is shorthand for:
[1, 2, 3, 4].map{|i| i.to_s}
This makes perfect sense. My question is this: It seems there should be an easier way to write:
[1, 2, 3, 4].map{|x| f.call(x)}
for some procedure f. I know the way I just typed isn't all that long to begin with, but I'd contend that neither is the previous example for which the shorthand exists. This example just seems like the complement to the first example: Rather than calling i's to_s method for every i, I wish to call f for every x.
Does such a shorthand exist?
Unfortunately this shorthand notation (which calls "Symbol#to_proc") does not have a way to pass arguments to the method or block being called, so you couldn't even do the following:
array_of_strings.map(&:include, 'l') #=> this would fail
BUT, you are in luck because you don't actually need this shortcut to do what you are trying to do. The ampersand can convert a Proc or Lambda into a block, and vice-versa:
my_routine = Proc.new { |str| str.upcase }
%w{ one two three }.map &my_routine #=> ['ONE', 'TWO', 'THREE']
Note the lack of the colon before my_routine. This is because we don't want to convert the :my_routine symbol into a proc by finding the method and calling .method on it, rather we want to convert the my_routine Proc into a block and pass it to map.
Knowing this, you can even map a native Ruby method:
%w{ one two three }.map &method(:p)
The method method would take the p method and convert it into a Proc, and the & converts it into a block that gets passed to map. As a result, each item gets printed. This is the equivalent of this:
%w{ one two three }.map { |s| p s }
As of Ruby 2.7, numbered parameters (_1, _2, etc) are supported. This syntax can be cryptic, especially with more than one parameter, but it can be useful for simple situations.
[1, 2, 3, 4].map { f.call(_1) }

How does ruby unpack arguments passed into Proc?

a_proc = Proc.new {|a,b,*c| p c; c.collect {|i| i*b }}
puts a_proc[2,2,4,3]
Code above is pretty intuitive according to https://ruby-doc.org/core-2.2.0/Proc.html, a_proc[2,2,4,3] is just a syntax sugar for a_proc.call(2,2,4,3) to hide “call”
But the following (works well) confused me a lot
a=[2,2,4,3]
puts a_proc.call(a)
puts a_proc.call(*a)
It seems very different from a normal function call, cause it doesn't check the number arguments passed in.
However, as expected the method calling semantics will raise an error if using parameters likewise
def foo(a,b,*c)
c.collect{|i| i*b}
end
foo([1,2,3,4]) #`block in <main>': wrong number of arguments (given 1, expected 2+) (ArgumentError)
foo(*[1,2,3,4]) #works as expected
I do not think such an inconsistency as a design glitch, so any insights on this will be appreciated.
Blocks use different semantics than methods for binding arguments to parameters.
Block semantics are more similar to assignment semantics than to method semantics in this regard. In fact, in older versions of Ruby, blocks literally used assignment for parameter binding, you could write something like this:
class Foo; def bar=(val) puts 'setter called!' end end
some_proc = Proc.new {|$foo, #foo, foo.bar|}
some_proc.call(1, 2, 3)
# setter called!
$foo #=> 1
#foo #=> 2
Thankfully, this is no longer the case since Ruby 1.9. However, some semantics have been retained:
If a block has multiple parameters but receives only a single argument, the argument will be sent a to_ary message (if it isn't an Array already) and the parameters will be bound to the elements of the Array
If a block receives more arguments than it has parameters, it ignores the extra arguments
If a block receives fewer arguments than it has parameters, the extra parameters are bound to nil
Note: #1 is what makes Hash#each work so beautifully, otherwise, you'd always have to deconstruct the array that it passes to the block.
In short, block parameters are bound much the same way as with multiple assignment. You can imagine assignment without setters, indexers, globals, instance variables, and class variables, only local variables, and that is pretty much how parameter binding for blocks work: copy&paste the parameter list from the block, copy&paste the argument list from the yield, put an = sign in between and you get the idea.
Now, you aren't actually talking about a block, though, you are talking about a Proc. For that, you need to know something important: there are two kinds of Procs, which unfortunately are implemented using the same class. (IMO, they should have been two different classes.) One kind is called a lambda and the other kind is usually called a proc (confusingly, since both are Procs).
Procs behave like blocks, both when it comes to parameter binding and argument passing (i.e. the afore-described assignment semantics) and also when it comes to the behavior of return (it returns from the closest lexically enclosing method).
Lambdas behave like methods, both when it comes to parameter binding and argument passing (i.e. strict argument checking) and also when it comes to the behavior of return (it returns from the lambda itself).
A simple mnemonic: "block" and "proc" rhyme, "method" and "lambda" are both Greek.
A small remark to your question:
a_proc[2,2,4,3] is just a syntax sugar for a_proc.call(2,2,4,3) to hide “call”
This is not syntactic sugar. Rather, Proc simply defines the [] method to behave identically to call.
What is syntactic sugar is this:
a_proc.(2, 2, 4, 3)
Every occurrence of
foo.(bar, baz)
gets interpreted as
foo.call(bar, baz)
I believe what might be confusing you are some of the properties of Procs. If they are given a single array argument, they will automatically splat it. Also, ruby blocks in general have some interesting ways of handling block arguments. The behavior you're expecting is what you will get with a Lambda. I suggest reading Proc.lambda? documentation and be careful when calling a ruby block with an array.
Now, let's start with the splat operator and then move to how ruby handles block arguments:
def foo(a, b, *c)
c.map { |i| i * b } # Prefer to use map alias over collect
end
foo([1, 2, 3, 4]) # `block in <main>': wrong number of arguments (given 1, expected 2+) (ArgumentError)
foo(*[1, 2, 3, 4]) # works as expected
So in your argument error, it makes sense: def foo() takes at least two arguments: a, b, and however many with *c. The * is the splat operator. It will turn an array into individual arguments, or in the reverse case here, a variable amount of arguments into an array. So when you say foo([1,2,3,4]), you are giving foo one argument, a, and it is [1,2,3,4]. You are not setting b or *c. What would work is foo(1, 1, 1, 2, 3, 4]) for example because you are setting a, b, and c. This would be the same thing: foo(1, 1, *[1,2,3,4]).
Now foo(*[1, 2, 3, 4]) works as expected because the splat operator (*) is turning that into foo(1, 2, 3, 4) or equivalently foo(1, 2, *[3, 4])
Okay, so now that we have the splat operator covered, let's look back at the following code (I made some minor changes):
a_proc = Proc.new { |a, b, *c| c.map { |i| i * b }}
a = [1, 2, 3, 4]
puts a_proc.call(a)
puts a_proc.call(*a)
Remember that if blocks/procs are given a single array argument they will automatically splat it. So if you have an array of arrays arrays = [[1, 1], [2, 2], [3, 3]] and you do arrays.each { |a, b| puts "#{a}:#{b}" } you are going to get 1:1, 2:2, and 3:3 as the output. As each element is passed as the argument to the block, it sees that it is an array and splats it, assigning the elements to as many of the given block variables as it can. Instead of just putting that array in a such as a = [1, 1]; b = nil, you get a = 1; b = 1. It's doing the same thing with the proc.
a_proc.call([1, 2, 3, 4]) is turned into Proc.new { |1, 2, [3, 4]| c.map { |i| i * b }} and will output [6, 8]. It splits up the arguments automatically it's own.

Can someone explain respond_to? :each?

Can someone help me understand the following code?
array = [1,2,3,4];
if array.respond_to? :each
puts "1234"
else
puts "5678"
end
I can understand the result of the code, but what is the syntax of :each?
Is :each a global method? Why can we write it like this? Or how I can find out about it?
:each is a Symbol, which is kind of like a String but more limited, and more efficient in comparisons for equality. It is not a method; it does happen to be a method name.
respond_to? is a method defined on Object, which (almost) all Ruby objects ultimately inherit from.
When you say [1, 2, 3, 4].each, it will send the message :each to the Array object [1, 2, 3, 4]. The Array class object is aware that its instances will know what to do when they receive such a message, and thus Array.respond_to?(:each) return true. Basically, if array.respond_to?(:each) is false, then array.each will raise an error. [Note that, as p11y notes in comments, if array is really an Array, then this will always return true. But programmers can lie, and array does not have to be an Array; for example: array = "not an Array, fooled you!"]
[1, 2, 3, 4].respond_to? :each is equivalent to [1, 2, 3, 4].respond_to?(:each).
On a side note, semicolons are only ever required in Ruby if you want to stuff several statements on one line. Unlike in C, for example, where semicolon is a statement terminator, in Ruby it is statement separator. It is thus bad style to write array = [1, 2, 3, 4];.

what is the mean of * and flatten in ruby

I am new to ruby language so when I was trying to sort a hash by value
I used this method to sort:
movie_popularity.sort_by{|m,p| p}.reverse
but the the sort method returns an array while I need a hash to be returned so I used this command:
movie_popularity=Hash[*movie_popularity.sort_by{|m,p| p}.reverse.flatten]
my Question is what is the meaning of * and flatten in the above line?
Thanks =)
The * is called the "splat operator"; I'm not sure I could give you the technical definition (though I'm sure you'd find it soon enough with Google's help), but the way I'd describe it is that it basically takes the place of hand-writing multiple comma-separated values in code.
To make this more concrete, consider the case of Hash[] which you've used in your example. The Hash class has a [] class method which takes a variable number of arguments and can normally be called like this:
# Returns { "foo" => 1, "bar" => 2 }
h = Hash["foo", 1, "bar", 2]
Notice how that isn't an array or a hash or anything that I passed in; it's a (hand-written) sequence of values. The * operator allows you to achieve basically the same thing using an array--in your case, the one returned by movie_popularity.sort_by{|m,p| p}.reverse.flatten.
As for that flatten call: when you call sort_by on a hash, you're really leveraging the Enumerable module which is included in a variety of classes (most notably Array and Hash) that provide enumeration. In the case of a hash, you've probably noticed that instead of iterating over one like this:
hash.each { |value| ... }
Instead you do this:
hash.each { |key, value| ... }
That is, iterating over a hash yields two values on each iteration. So your sort_by call on its own would return a sequence of pairs. Calling flatten on this result collapses the pairs into a one-dimensional sequence of values, like this:
# Returns [1, 2, 3, 4]
[[1, 2], [3, 4]].flatten
'flatten' flattens an array: http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-flatten
'*' is the splat operator: http://theplana.wordpress.com/2007/03/03/ruby-idioms-the-splat-operator/
The pertinent bit in the last url is this:
a = [[:planes, 21], [:cars, 36]]
h = Hash[*a] # => { :planes=>21, :cars=>36}

How do you get the class of an underlying object in a Ruby enumerable?

a = [4, 5, 3]
e = a.each
e.class #=> Enumerator
e.first.class #=> Fixnum
How do you find out if e is an enumerator for an array, hash or other type?
Working in Ruby 1.9.2
You can't (easily).*
Nor should you be able to. Enumerators aren't meant to care about what's contained within them, they're meant to iterate over something. You probably shouldn't be passing around enumerators anyway: just pass around the actual object.
Though, you could do nasty things like parse [].each.inspect with regex for either [] or {}, or the case where it's another type like #<Set: {}>. But this is just so horrible. I suggest re-thinking why you want to do this—and then not doing it.
* Note that the non-easy programmatic way would be to write C code using the Ruby C API and tap into the actual object pointer within the enumerator. This needs to be done because Enumerator is written in C, and causes doing things like [].each.instance_variables to return [].
Not that I propose that this is appropriate or in any way a good idea, but you CAN inspect an enumerator and potentially get some information that would give you a hint to the underlying object. This of course, begs the question of why you would want to do this...
a = [1,2,3,4]
=> [1, 2, 3, 4]
e = a.each
=> #<Enumerator: ...>
e.inspect
=> "<#Enumerator: [1, 2, 3, 4]:each>"
a = { :foo => "bar" }
=> {:foo=>"bar"}
e = a.each
=> #<Enumerator: ...>
e.inspect
=> "#<Enumerator: {:foo=>\"bar\"}:each>"
You can then use a regexp to try to tease out information about the underlying object. There are probably occasions for which this won't work (it does work for ranges). I'd emphasize again that there's probably no good reason to do this.
I would tentatively say that this can't be done. There doesn't seem to be any requirement, when creating an Enumerator, to actually reference the source object itself, only to tell the Enumerator how to get to the next, current, etc... values

Resources