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

han*_*cho 1 ruby block proc

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

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

作业问题非常简单.

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

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

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

我有两个问题 -

1 你怎么称呼这种方法,因为我放了

print reverser("Hello") 
Run Code Online (Sandbox Code Playgroud)

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

其次,为什么不写下面的方法呢?编写一个占用块的方法有什么好处?

def reverser(string)
  string.split.map{|x| x.reverse}.join(" ")
end 
Run Code Online (Sandbox Code Playgroud)

Mar*_*jaš 6

  1. 你这样称呼它:

    print reverser { "Hello" }
    
    Run Code Online (Sandbox Code Playgroud)

或者,如果您的块长几行,那么就像这样:

print reverser do
  "Hello"
end
Run Code Online (Sandbox Code Playgroud)
  1. 块与其他语言中的匿名函数非常接近.

地图就是一个很好的例子.映射的作用是根据您需要的规则对每个元素进行数组和映射(转换).

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

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

words.map { |word| word.reverse }.join(" ")
Run Code Online (Sandbox Code Playgroud)

如果您无法将块传递给map,那么您必须定义该函数并将其传递到某处 - 并命名该函数.那只是没有效率.

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

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

如果没有块,您需要定义该功能,这在任何其他地方都不需要并调用它.那只是没有效率.这就是它的样子

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)
Run Code Online (Sandbox Code Playgroud)