映射函数的简写

时间:2012-02-24 20:39:01

标签: ruby functional-programming

map中,我可以使用方便的&:表示法调用传入值的方法:

nums = (0..10).to_a
strs = nums.map(&:to_s)

是否有类似的东西用于调用函数,并将值作为第一个参数传入?

nums = (0..10).to_a
nums.each(puts) # error!

4 个答案:

答案 0 :(得分:11)

免责声明:这篇文章纯粹是教育性的。 nums.each {|n| puts n}实际上是在一个真实项目中写的唯一合理的东西。

了解nums.map(&:to_s)

现有的简表非常简单。 &在符号上调用to_proc,符号上的to_proc就像这样定义。

class Symbol
  def to_proc
    Proc.new { |*args| args.shift.__send__(self, *args) }
  end
end

由于此proc将开始像传递给map的常规块一样,因此在这种情况下*args实际上是我们迭代的每个元素。我们采用args中的第一个(因为*将参数转换为数组),并向其发送selfself是实际符号,例如:to_s。传入剩余的参数。所以就像说nums.map{ |*args| args.shift.__send__(:to_s, *args) }

更改它以启用nums.each(&:puts)

我们可以轻松地重新实施to_proc以采取不同的行动。这是一个简单的例子。

class Symbol
  def to_proc
    Proc.new { |*args| __send__(self, *args) }
  end
end

(1..10).each(&:print) # => 12345678910

这里不是将符号名作为消息发送给元素,而是将符号作为当前上下文的方法调用,只需将迭代元素作为参数传递给它。

所以这更像是在说(1..10).each{|*args| __send__(:print, *args)}

了解nums.each(&method(:puts))

那就是说,正如纳什所指出的,你可以打电话给nums.each(&method(:puts))。会发生什么,你得到一个使用ruby的puts方法表示方法method的对象。然后&调用方法对象上的.to_proc,将其转换为proc,它本身开始扮演传递到each(或map)的块的角色。传递给proc的参数(你正在迭代的每个元素)然后成为该方法的参数。整齐。

实施xargs

为了避免覆盖标准行为,我们可以假设实现我们自己的xargs功能,就像在shell脚本中一样。 (不要在家里这样做,太聪明也不好。)

class Symbol
  def to_xargs
    Proc.new{ |*args| __send__(self, *args) }
  end
end

def xargs(sym)
  sym.to_xargs
end

(1..10).each(&xargs(:print)) # prints 12345678910

答案 1 :(得分:9)

使用它:

nums.each(&method(:puts))

但实际上它并不短得多:)

答案 2 :(得分:2)

不完全相似,但如何:

nums.each {|n| puts n}

答案 3 :(得分:0)

实际上,当puts收到一个数组时,它会在一个新行中打印每个元素......

  

将给定对象写入ios,与IO#print一样。写一条记录   在任何尚未结束的分隔符之后的分隔符(通常是换行符)   换行序列。 如果使用数组参数调用,则写入每个参数   新行上的元素。如果不带参数调用,则输出一个   记录分隔符。

因此...

puts nums