当内省模块类时,"#map(&proc)"成语如何工作?

Tod*_*obs 13 ruby idioms constants introspection proc

介绍成语

我发现了一个有趣但无法解释的替代方案.代码清楚地在REPL中起作用.例如:

module Foo
  class Bar
    def baz
    end
  end
end
Foo.constants.map(&Foo.method(:const_get)).grep(Class)
=> [Foo::Bar]
Run Code Online (Sandbox Code Playgroud)

但是,我并不完全理解这里使用的习语.特别是,我不理解使用&Foo,这似乎是某种闭包,或者#grep的这种特定调用如何对结果进行操作.

解析成语

到目前为止,我已经能够解析这部分内容了,但我并没有真正看到它们是如何组合在一起的.以下是我认为我对示例代码的理解.

  1. Foo.constants 返回模块常量数组作为符号.

  2. method(:const_get)使用Object#方法执行方法查找并返回闭包.

  3. Foo.method(:const_get).call :Bar 是一个闭包,它返回类中常量的限定路径.

  4. &Foo似乎是某种特殊的lambda.文档说:

    如果Proc对象由&参数给出,&参数将保留技巧.

    我不确定我是否完全理解这在特定背景下的含义.为什么选择Proc?什么"诡计",为什么这里有必要?

  5. grep(Class)正在运行#map方法的值,但其功能并不明显.

问题,重申

我真的很想完全理解这个成语.任何人都可以在这里填补空白,并解释这些部分是如何组合在一起的吗?

Mic*_*ohl 9

&Foo.method(:const_get)是该方法const_get的的Foo对象.这是另一个例子:

m = 1.method(:+)
#=> #<Method: Fixnum#+>
m.call(1)
#=> 2
(1..3).map(&m)
#=> [2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

所以最后这只是一种无拘无束的说法Foo.constants.map { |c| Foo.const_get(c) }.grep用于===选择元素,因此它只会获取引用类的常量,而不是其他值.这可以通过添加另一个常数来验证Foo,例如Baz = 1,哪个不会得到grepped.

如果您还有其他问题,请将其添加为评论,我会尝试澄清它们.