1

举个例子:

greeting = "world hello".split.reverse.join(" ")
greeting << ", here me shouting!!"
greeting.upcase!

p greeting # "HALLO WORLD, HERE ME SHOUTING!!"

这使用局部变量greeting来存储字符串。现在,如果我们之前在代码中已经使用过这个变量,那么它的原始值就会丢失。

greeting = "Hi World."

...

greeting = "world hello".split.reverse.join(" ")
greeting << ", here me shouting!!"
greeting.upcase!

p greeting # "HALLO WORLD, HERE ME SHOUTING!!" ... original "Hi World." is gone.

所以我在想是否有一种方法可以通过使用块来为这样的小片段创建范围。该变量greeting将进入块中并且只会隐藏外部变量,而不是覆盖它:

greeting = "Hi World."

"world hello".scope do |greeting|
  greeting.split.reverse.join(" ")
  greeting << ", here me shouting!!"
  greeting.upcase!
  p greeting # "HALLO WORLD, HERE ME SHOUTING!!"
end

p greeting # "Hi World."

注意scope我在这里使用的方法。我将此方法猴子修补到Object. scope获取块并使用局部变量产生它self

class Object
  def scope
    yield self
  end
end

依靠猴子修补Object类,特别是使用名为 的方法,我感觉不太舒服scope,这似乎很可能被其他类覆盖,其实例不能再像这样限定范围。

那么,Ruby 中有没有内置的方法可以做到这一点?

另外 - 如果我必须继续使用猴子补丁 - 我认为这self可能是一个比scope. 即使也是关键字,也可以定义为方法名;它有效,我测试了它。self似乎不太可能被其他类覆盖。它也很适合其他最常用的“块方法”的风格each

collection.each do

“在每个元素上执行以下块。”

object.self do

“对(你)自己执行以下块”。

self用作方法名称有什么缺点吗?(其他命名建议表示赞赏)。

4

1 回答 1

1

这个问题被反复问过。一种方法是:

"world hello".instance_eval do
  ...
end

但这很重,不是首选。建议的更好方法是:

"world hello".tap do |s|
  ...
  break s
end

但在您的特定情况下,方法链是最简单的:

"world hello"
.split
.reverse
.join(" ")
.concat(", here me shouting!!")
.upcase
.tap{|s| p s}
于 2013-02-22T12:24:37.453 回答