Ruby中避免滥用赋值"="的最佳实践是什么?
-
12-11-2019 - |
题
我已经被咬了好几次了,因为忘了这一点 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带来的面向对象的范式(对象在内部保持状态,可以通过调用方法来改变状态),所以你必须在这两种方法之间保持一点平衡(另一方面,我们受益于在一种语言中可以轻松访问多个范式)。
所以,现在要记住三件事:
- 了解Ruby中的赋值是什么:只有命名一个对象。所以,当你说
y=x
, ,你只是说"我们给另一个名字y
无论什么名字x
". name << title
变异体 对象调用name
.name += title
接受命名的对象name
和title
, ,将它们连接成 另一个 对象,并分配该新对象名称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)修改它的文档。