我已经被咬了好几次了,因为忘了这一点 x = y 在Ruby中,x引用与y相同的对象;我太习惯了Ruby语言的含义, x = y.dup.忘记了这一点,我不经意间改变了 y 当我认为在任务的右边是安全的时候。

我可以看到,这将是有道理的,以避免简单 x = y 没有特殊原因的任务,但同样的事情可以潜伏在其他地方,如

name = (person.last_name.blank? ? 'unknown' : person.last_name)

后来的地方 name << title 实际上会改变人。last_name而不仅仅是name。

如果这也发生在你身上,你是如何学会避免它的?是否有某些红旗或模式要寻找?你是否怀疑你所做的每一项任务?你用吗? .dup 很多?不知道Ruby的使用是否会成为我的第二天性,所以任何有用的提示都是受欢迎的。

有帮助吗?

解决方案

这可能听起来像Ruby这样的(本质上是命令式的)语言是非正统的,但我的建议是:避免 附带损害赔偿 完全不更新对象(除非绝对必要);创建新的。你付出了一些性能,但你会得到更清晰,更紧凑,更模块化和更容易调试的代码。

http://en.wikipedia.org/wiki/Functional_programming

因此,在您的示例中,只需使用新名称创建一个新字符串:

complete_name = name + title

其他提示

只是tokland的答案的补充:

功能方法坚持 不变性 -即不是改变现有的对象,而是在你想改变原来的对象时创建另一个对象。这在某种程度上违背了Ruby带来的面向对象的范式(对象在内部保持状态,可以通过调用方法来改变状态),所以你必须在这两种方法之间保持一点平衡(另一方面,我们受益于在一种语言中可以轻松访问多个范式)。

所以,现在要记住三件事:

  1. 了解Ruby中的赋值是什么:只有命名一个对象。所以,当你说 y=x, ,你只是说"我们给另一个名字 y 无论什么名字 x".
  2. name << title 变异体 对象调用 name.
  3. name += title 接受命名的对象 nametitle, ,将它们连接成 另一个 对象,并分配该新对象名称 name.它不会变异任何东西。

我也遇到了这样的情况,它导致了一个错误,我花了半天的时间来弄清楚。我基本上做了这样的事情

hash = {....}
filename = object.file_name
hash.each |k, v| {file_name.gsub!(k, v) if file_name.include? k}

这段代码在一个循环中,在循环中,我期望变量 file_name 以再次设置为原始值。但对象。file_name被更改,因为我正在执行 file_name.gsub!.有两种方法可以解决这个问题。要么替换 .gsub! 打电话给 file_name = file_name.gsub 还是做 file_name = object.file_name.dup.我选择了第二个选项。

我认为我们应该小心使用 !<<, ,因为它们改变了它们所作用的原始对象,特别是在这样的赋值之后。

方法不应该修改变量(例如通过使用移位运算符),除非它的定义说它会修改它。

所以:不要修改方法中的对象,而该方法既没有(a)创建它,也没有(b)修改它的文档。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top