我遇到了导致错误或困惑的奇怪副作用。所以想象一下,这不是一个微不足道的例子,而是一个陷阱的例子。
name = "Zorg"
def say_hello(name)
greeting = "Hi there, " << name << "?"
puts greeting
end
say_hello(name)
puts name
# Hi there, Zorg?
# Zorg
这不会改变名称。姓名仍为Zorg
.
但是现在来看一个非常细微的差别。在下一个示例中:
name = "Zorg"
def say_hello(name)
greeting = name << "?"
puts "Hi there, #{greeting}"
end
say_hello(name)
puts name
# Hi there, Zorg?
# Zorg? <-- name has mutated
现在名称是 Zorg?
.疯狂的。 greeting =
的细微差别|任务。 Ruby 在内部使用解析(?)或消息传递链接做一些事情?我以为这只会像 name.<<("?")
一样把铲子链起来但我想这不会发生。
这就是为什么我在尝试进行串联时避免使用铲子运算符。我通常尽量避免改变状态,但 Ruby(目前)还没有为此进行优化(还)。也许 Ruby 3 会改变一切。对于关于 Ruby future 的范围蔓延/旁白讨论,我们深表歉意。
我认为这特别奇怪,因为副作用较少的示例(第一个)有两个铲操作符,而副作用较多的示例有较少的铲操作符。
更新 你是对的 DigitalRoss,我把它弄得太复杂了。 简化示例:
one = "1"
two = "2"
three = "3"
message = one << two << three
现在你认为一切都准备好了? (不要偷看!) 如果非要我猜的话,我会说:
one is 123
two is 23
three is 3
message is 123
但我错了两个。二是 2。
最佳答案
如果我们转换您的 a << b << c
构造成更像方法的形式并放入一堆隐式括号,行为应该更清晰。重写:
greeting = "Hi there, " << name << "?"
产量:
greeting = ("Hi there, ".<<(name)).<<("?")
String#<<
正在修改东西但是 name
永远不会作为 <<
的目标/左轴出现, "Hi there ," << name
字符串但name
没有。如果用变量替换第一个字符串文字:
hi_there = 'Hi there, '
greeting = hi_there << name << '?'
puts hi_there
你会看到 <<
已更改 hi_there
;在你的"Hi there, "
在这种情况下,此更改是隐藏的,因为您正在修改之后无法查看的内容(字符串文字)。
关于ruby - 为什么 Ruby 中的双铲不改变状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40877662/