Ruby中最好的做法是避免滥用赋值“=”?

时间:2011-03-26 14:49:01

标签: ruby variable-assignment equals-operator dup

我忘记了Ruby中的x = y使得x引用与y相同的对象,我被咬了几次;在Ruby术语中,我已经习惯了语言,x = y.dup。忘掉这一点,当我认为在作业的右侧是安全的时候,我无意中改变了y

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

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

后面的name << title实际上会改变person.last_name而不只是名字。

如果这也发生在你身上,你是如何学会避免它的?是否有某些红旗或图案需要寻找?你对每个作业都怀疑吗?你经常使用.dup吗?我不知道Ruby的使用是否会成为我的第二天性,所以任何有用的提示都会受到欢迎。

4 个答案:

答案 0 :(得分:5)

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

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

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

complete_name = name + title

答案 1 :(得分:1)

只是对tokland答案的补充:

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

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

  1. 了解Ruby中的任务:除了命名对象外什么都没有。因此,当您说y=x时,您只是说“我们为名为y的任何内容提供了另一个名称x。”
  2. name << title 变更名为name的对象。
  3. name += title获取名为nametitle的对象,将它们连接到另一个对象,并指定新对象名name。它不会改变任何东西。

答案 2 :(得分:0)

我也遇到过这样的情况而且它导致了一个错误,我花了半天才弄明白。我基本上做了这样的事情

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

这段代码在循环中,在循环中,我期望变量file_name再次设置为原始值。但是,当我执行file_name.gsub!时,object.file_name已更改。有两种方法可以解决这个问题。将.gsub!来电替换为file_name = file_name.gsubfile_name = object.file_name.dup。我选择了第二种选择。

我认为我们应该谨慎使用!<<的方法,因为它们会更改他们正在行动的原始对象,尤其是在这样的作业之后。

答案 3 :(得分:0)

方法不应修改变量(例如,通过使用移位运算符),除非其定义表明它将修改它。

所以:永远不要修改一个没有(a)创建它的方法中的对象,或者(b)修改它修改它的文档。