Presenting the Idiom
I found an interesting but unexplained alternative to an accepted answer. The code clearly works in the REPL. For example:
module Foo
class Bar
def baz
end
end
end
Foo.constants.map(&Foo.method(:const_get)).grep(Class)
=> [Foo::Bar]
However, I don't fully understand the idiom in use here. In particular, I don't understand the use of &Foo
, which seems to be some sort of closure, or how this specific invocation of #grep operates on the result.
Parsing the Idiom
So far, I've been able to parse bits and pieces of this, but I'm not really seeing how it all fits together. Here's what I think I understand about the sample code.
Foo.constants
returns an array of module constants as symbols.method(:const_get)
uses Object#method to perform a method lookup and return a closure.Foo.method(:const_get).call :Bar
is a closure that returns a qualified path to a constant within the class.&Foo
seems to be some sort of special lambda. The docs say:The & argument preserves the tricks if a Proc object is given by & argument.
I'm not sure I fully understand what that means in this specific context, either. Why a Proc? What "tricks," and why are they necessary here?
grep(Class)
is operating on the value of the #map method, but its features are not obvious.Why is this #map construct returning a greppable Array instead of an Enumerator?
Foo.constants.map(&Foo.method(:const_get)).class => Array
How does grepping for a class named Class actually work, and why is that particular construction necessary here?
[Foo::Bar].grep Class => [Foo::Bar]
The Question, Restated
I'd really like to understand this idiom in its entirety. Can anyone fill in the gaps here, and explain how the pieces all fit together?