【问题标题】:Ruby: How does implicit return value work in blocks?Ruby:隐式返回值如何在块中工作?
【发布时间】:2017-09-11 10:03:30
【问题描述】:

编辑:我最初的问题与我的实际问题无关,但当我在此过程中学到一些东西时,我决定改写我最初的陈述。

我想用字符串中的一对括号内的_ 替换每个空格。这是我的示例输入:

This is my string (nice, isn't it?). It can have various types [of input].

期望的输出:

This is my string (nice,_isn't_it?). It can have various types [of_input].

我有以下代码:

my_string = my_string.gsub(/\([^\(\)]+\)|\[[^\[\]]+\]/) { |bracketed|
    bracketed.gsub(/ /, '_')
}

为什么bracketed.gsub(/ /, '_') 等于bracketed = bracketed.gsub(/ /, '_')?这与gsub! 有何不同?我不完全理解 Ruby 假设在这里返回什么背后的逻辑。

【问题讨论】:

  • 它会生成你想要的输出。什么不起作用?
  • 还有改进的余地,但您的代码运行良好。它已经达到了预期的输出。
  • 即您可以将代码简化为:my_string.gsub(/\([^)]+\)|\[[^\]]+\]/) { |bracketed| bracketed.tr(' ', '_') } ...但是您的版本已经可以使用了吗??
  • @TomLord 我怀疑 OP 想了解为什么这里不需要使用 return,Ruby 如何从块内修改 my_string。所以,问题实际上并不是关于正则表达式,而是关于一般的块。
  • @MrVocabulary 正如我上面所展示的,您甚至不需要将bracketed = 放入块中!块(或任何方法)的最后一行是ruby中的隐式响应值。

标签: ruby regex gsub


【解决方案1】:

为什么bracketed.gsub(/ /, '_') 等于bracketed = bracketed.gsub(/ /, '_')?这和gsub! 有什么不同?

  • gsub 返回一个 new 字符串。
  • gsub! 更改 现有 字符串。

所以bracketed = bracketed.gsub(/ /, '_')bracketed.gsub!(/ /, '_') 几乎是等价的。

(如果没有匹配的模式,gsub! 将返回 nil,这只是一个次要的行为差异。但无论哪种方式,您都会改变原始的 bracketed 变量同样的方式。)

但是,你问错了问题……让我们再看看你的原始代码,它可以写成:

my_string.gsub!(/\([^)]+\)|\[[^\]]+\]/) do |bracketed|
  bracketed.gsub(/ /, '_')
end

来自the documentation for String#gsub

在块形式中,当前匹配字符串作为参数传入[...] 块返回的值将在每次调用时替换匹配

在 ruby​​ 中,方法/块中的最终评估行是它的隐式返回值。您在这里所做的只是将值传递回原始的gsub 方法; 没关系你是否改变/重新分配 bracketed 变量。

也许这个例子会让事情更清楚一点:

"hello (world)".gsub!(/\([^)]+\)|\[[^\]]+\]/) do |bracketed|
  bracketed = "something different"
  "TEST!!!"
end

  # => "hello (TEST!!!)"

【讨论】:

  • 不一定是“最后一行”,而是评估的最后一个表达式(可以是多行if-elsif-else 构造)
  • 好的,我明白了。我没有使用! 版本正是因为潜在的nils 并且想知道这是不是隐含的东西,但我现在明白了很多:)
  • @Stefan 是的,抱歉——我真正的意思是“最后一行得到评估”。我将进行编辑以使其完全清楚。
猜你喜欢
  • 2010-11-07
  • 1970-01-01
  • 2014-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多