Ruby, with ActiveSupport
1
2
3
4
5
|
my_various_objects = [ "My", 3, { :assertions => 'are' }, true ]
my_various_objects.collect(&:class)
# => [ String, Fixnum, Hash, TrueClass ]
|
Read it as : "Collect the class of my various objects please", beautiful he :)
Now let's get back to standard Ruby
collect in Ruby takes a block and returns the array made with the results of the block call on each entry in the Enumerable object.
However, Ruby distinguish arguments and block in a method call. This means the following is wrong :
1
2
3
4
5
|
my_proc = lambda { |x| x.class }
my_various_objects.collect(my_proc)
# => ArgumentError: wrong number of arguments (1 for 0)
|
Because
collect doesn't expect an
argument but a
block.
What we wanted to do is :
1
2
3
4
5
6
7
8
9
|
my_various_objects.collect { |x| x.class }
# => [ String, Fixnum, Hash, TrueClass ]
# or
my_various_objects.collect do |x|
x.class
end
# which is the same...
|
But what we have in Ruby is
& :
1
2
3
|
my_various_objects.collect(&my_proc)
# => [ String, Fixnum, Hash, TrueClass ]
|
The ampersand prefix I used in the first snippet is a way to give a Proc object (made with lambda or Proc.new, even if they are differences) as a block in a method call.
Well, not exactly a Proc objet, in fact & sends to_proc on any
object, which should convert this object to a Proc (if someone as implemented it in the object's class of course) and then give it as a block to the method.
Calling to_proc on an instance of Proc simply returns the instance, so anything special happens, but what happens in the first example ?
:class is a symbol, so &:class will send to_proc to the symbol,
and give the block to collect.
Javascript, with Prototype
1
2
3
|
[ "My", 3, { assertions: 'are' }, true ].pluck('constructor');
// => [ String(), Number(), Object(), Boolean() ]
|
Read it as : "Collect the class of my various objects please", beautiful he :)