Ruby怪异的赋值行为

时间:2010-06-12 16:07:35

标签: ruby

这是一个红宝石虫吗?

target_url_to_edit = target_url

if target_url_to_edit.include?("http://")
  target_url_to_edit["http://"] = ""
end

logger.debug "target url is now #{target_url}"

这将返回不带http://

的target_url

4 个答案:

答案 0 :(得分:10)

您需要复制内存中对象,因为变量名只是对内存中对象的引用:

target_url_to_edit = target_url.dup

现在为target_url_to_edit分配了原始对象的新副本。

对于您的情况,此代码可能只在一行中执行相同操作(无重复,否则为:)

target_url_to_edit = target_url.sub(%r{^http://}, "")

答案 1 :(得分:5)

不,这不是Ruby中的错误,这就是共享可变状态的工作方式,不仅仅是在Ruby中,而是在任何编程语言中。

这样想:我的妈妈称我为“儿子”,我的朋友称我为“Jörg”。如果我剪了头发,那么你用哪个名字来引用我并不重要:我是同一个人,无论你是叫“儿子”还是“Jörg”或“Mittag先生”还是“嘿, douchebag“,因此我的头发总是很短。如果你用不同的名字给我打电话,它就不会神奇地重新长出来。

在您的代码中也会发生同样的事情:您通过两个不同的名称来引用字符串,但使用哪个名称并不重要;如果字符串发生变化,则会发生变化。

当然,解决方案是不共享可变状态而不是改变共享状态,就像在@ hurikhan77的回答中一样。

答案 2 :(得分:0)

这不是一个错误。这是预期的行为,因为target_url_to_edit指向内存中的同一对象target_url,因为Ruby使用引用进行对象分配。如果你知道C,它就像指针一样。

答案 3 :(得分:-1)

以下是如何更改其行为以强制按值传递(请注意星号):

target_url_to_edit = *target_url.to_s

if target_url_to_edit.include?("http://")
  target_url_to_edit["http://"] = ""
end

logger.debug "target url is now #{target_url}"

就像红宝石中的许多东西一样,很难找到它所记录的位置......