Ruby - 为什么使用Block作为参数?

时间:2017-05-02 15:20:30

标签: ruby block proc

我在ruby中理解Blocks vs Procs时遇到了麻烦。我得到一个基本的想法,即proc是一个保存为对象的方法,你可以反复调用,而不必一遍又一遍地继续编写相同的代码行。

我的麻烦在于接受块作为方法中的参数。

家庭作业问题非常简单。

编写一个接受块作为参数的方法,并反转字符串中的所有单词。

以下是他们正在寻找的答案。

def reverser(&prc)
  sentence = prc.call
  words = sentence.split(" ")
  words.map { |word| word.reverse }.join(" ")
end

我有两个问题 -

1 如何调用此方法,因为如果我放

print reverser("Hello") 

我收到错误"错误的参数数量(给定1,预期为0)"

其次,为什么不写下面的方法呢?编写一个阻塞方法的好处是什么?

def reverser(string)
  string.split.map{|x| x.reverse}.join(" ")
end 

1 个答案:

答案 0 :(得分:6)

  1. 你这样称呼它:

    print reverser { "Hello" }
    
  2. 或者如果您的区块长了几行,那么就像这样:

    print reverser do
      "Hello"
    end
    
    1. 块与其他语言的匿名函数非常接近。
    2. 地图就是一个很好的例子。 根据您需要的规则,映射需要一个数组并映射(转换)每个元素。

      这些映射规则必须是代码。这意味着,它不能是字符串或数字或其他东西,它必须是一个函数。这里使用块作为函数,您可以使用最少的代码编写。

      所以在你的例子中你有这个:

      words.map { |word| word.reverse }.join(" ")
      

      如果你无法将块传递给map,那么你必须定义该函数并将其传递到某个地方 - 并命名该函数。那效率不高。

      让我们更改此块以使其仅在以大写字母开头时才会反转单词。

      words.map do |word| 
        if word[0] =~ /[A-Z]/ 
          word.reverse
        else
          word
      end.join(" ")
      

      没有块你需要定义那个你在任何其他地方都不需要的函数并调用它。那只是没有效率。 这就是它的样子

      def reverse_if_starts_with_capital_letter(word)
        if word[0] =~ /[A-Z]/ 
          word.reverse
        else
          word
        end
      end
      
      # not sure if this syntax would work, just demonstrates idea
      words.map(&reverse_if_starts_with_capital_letter)