我正在学习 Ruby,并认为我对以下代码很聪明:
[@start,@end].map!{ |time| time += operation == :add ? amount : -(amount) }
其中@start、@end 是两个模块级变量,operation 可以是:add 或:sub 之一,amount 是一个 float ,用于调整@start 和@end。
虽然它只为我节省了一行代码,但为什么这种方法不起作用,我怎样才能得到类似的东西呢?
(我的预期输出是对@start/@end 进行相应修改,但单元测试显示它们保持原始值。)
最佳答案
在 Ruby 中记住变量和它们持有的对象之间的区别很重要。简单地设置一个变量永远不会改变该变量引用的对象。当您执行 a += b
时,它只是 a = a + b
的简写。因此,您正在为变量 a 分配一个新值,而不是更改曾经存在的对象或更改对该对象的任何其他引用。所以改变变量 time
不会改变 @start
。
为了分配给实例变量,您需要实际分配给该实例变量。这里有一种方法可以满足您的需求:
operation = :+
amount = 12
@start, @end = [@start, @end].map {|time| time.send(operation, amount)}
您会注意到我们也没有在处理 :add
和 :sub
业务——我们可以只传递我们想要的消息的实际名称发送(我在这种情况下使用 +,但它可以是任何东西)。
如果您有一个很大的、动态生成的要设置的 ivar 列表,它只会稍微复杂一点。唯一的区别是需要按名称获取和设置 ivar。
ivars = [:@start, :@end, :@something_else]
operation = :+
amount = 12
ivars.each {|ivar| instance_variable_set(ivar, instance_variable_get(ivar).send(operation, amount))}
关于ruby - 在 Ruby 中修改匿名数组中的模块级变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1490816/