接受块的传递方法

问题描述 投票:1回答:2

如何传递接受块的方法的好方法?

即将该方法视为变量,以便可以通过以下方式使用:

(@glob&.each || crawl_dir(@base_dir)) do |file|
        puts "#{file}"
      end

一个可以尝试的简单示例:

> require 'csv'
=> true

> CSV {|v|v}
=> <#CSV io_type:$stdout encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">

> a=CSV
=> CSV

> a==CSV
=> true

> a {|v|v}
Traceback (most recent call last):
        1: from (irb):14
NoMethodError (undefined method `a' for main:Object)

这可能吗?

ruby closures
2个回答
0
投票

您可以始终在任何对象上使用tap

tap

0
投票

在您的示例中,您使用的都是称为a.tap do |v| p v end 的不同事物。

CSV

[这里,您正在使用块调用名为CSV {|v|v} 的方法。您将获得该方法的返回值。诸如此类的方法通常用作转换器。例如。 CSV方法带有一个参数(例如字符串),该参数被转换为Integer()对象。通常,这些方法与它们返回的对象的类相同。

Integer

这里,您正在将a=CSV 常量的值(为CSV类)分配给CSV变量。然后,在您的代码中,可以使用a常量或CSV变量来引用类对象。

a

在这里,由于Ruby试图调用名为a {|v|v} 的方法(该方法不存在),您会收到一条错误消息。即使这行得通,在这一点上a变量还是对a类的引用(不能直接调用)。

((注意:要调用名称存储在变量中的方法,可以使用CSV方法,例如send。]

现在,要解决最初的问题,您可以创建一个方法对象,并使用它来调用所需的方法,例如

my_receiver.send(a)

但是,这不是非常惯用的Ruby。在这里,很少携带方法引用(而不是在Java或Python中,通常使用传递的函数对象来执行方法引用)。 Ruby中更惯用的实现可能是:

method = @glob&.method(:each) || method(:crawl_dir).curry(@base_dir)
method.call do |file|
  puts file
end

[如果您的def handle_file(file) puts file end if @glob.respond_to(:each) @glob.each { |file| handle_file(file) } else crawl_dir(@base_dir) { |file| handle_file } end 方法将(可选)返回crawl_dir对象,这将更加简化,在这种情况下,您可以简化调用代码:

Enumerator

这里发生的是,您无障碍调用def crawl_dir(directory) return enum_for(__method__) unless block_given? # the rest of the method here... end (@glob&.each || crawl_dir(@base_dir)).each do puts file end @glob.each。在这两种情况下,您都将获得一个crawl_dir(@base_dir)对象。然后可以使用Enumerator枚举此对象。因此,您的两个方法都具有相同的返回类型,因此可以类似地使用。

© www.soinside.com 2019 - 2024. All rights reserved.