是否';厄普卡斯';不在Ruby中变异变量?
我只是想确定我明白这里发生了什么。我知道+=是重新分配的,所以也许这就是str没有被修改的原因,但是为什么是否';厄普卡斯';不在Ruby中变异变量?,ruby,Ruby,我只是想确定我明白这里发生了什么。我知道+=是重新分配的,所以也许这就是str没有被修改的原因,但是为什么upcase在这里修改str def change_me(str) str+=“?” 上回! 结束 问:“你叫什么名字?” 改变我(问题) 提出问题 “你叫什么名字?” =>零 执行str+=“?”时,您正在创建一个新字符串,因此str指向的字符串与作为参数传递的字符串不同 你所做的基本上是这样的: def change_me(str) new_str = str + "?&q
upcase代码>在这里修改str
def change_me(str)
str+=“?”
上回!
结束
问:“你叫什么名字?”
改变我(问题)
提出问题
“你叫什么名字?”
=>零
执行str+=“?”
时,您正在创建一个新字符串,因此str
指向的字符串与作为参数传递的字符串不同
你所做的基本上是这样的:
def change_me(str)
new_str = str + "?"
new_str.upcase!
end
这就是为什么没有更改以前的字符串。如果希望该功能产生副作用,应执行以下操作:
def change_me(str)
str << "?"
str.upcase!
end
def change_me(str)
str
“上格!”不在Ruby中变异变量
方法不可能对变量进行变异。Ruby是一种面向对象的语言,因此方法可以改变对象(更准确地说,方法可以改变它的接收者),但变量不是Ruby中的对象。(与大多数其他语言一样,几乎没有以变量为对象的语言。)
变异变量的唯一方法是赋值。请注意,我们通常不讨论“变异”变量,而是讨论“重新绑定”或“重新分配”
我只是想确定我明白这里发生了什么。我知道+=是重新分配的,所以也许这就是str没有被修改的原因,但是为什么upcase代码>在这里修改str
同样,您混淆了变量和对象<代码>上传
修改由str
引用的对象,但不修改str
听起来你希望Ruby是一种通过引用传递的语言,但事实并非如此。Ruby完全是按值传递的,始终没有例外。更准确地说,传递的值是指向对象的不可修改、不可伪造的指针
以下是执行流程中发生的情况:
question=“你叫什么名字”
- 字符串文本
“What's your name”
将被计算,结果是一个字符串
对象,其内容为What's your name
- 局部变量
question
用一个不可变、不可伪造的指针初始化,该指针指向在步骤#1中创建的字符串对象
change\u me(问题)
- 局部变量
question
被取消引用,导致指向步骤#1中创建的字符串对象的不可变、不可伪造的指针
- 将制作该指针的副本
- 步骤4的副本被放入调用
change\u me
str+=“?”
- 在
change\u me
方法主体内部,参数绑定str
绑定到从步骤4和步骤5复制的不可变不可伪造指针
- 这一行被分解为
str=str+“?”
,因此发生的是:
str
被取消引用,导致从步骤4、5和6复制的不可变、不可伪造指针
- 我们跟随指针并将消息
+
发送到对象,该对象带有一个不可变的、不可伪造的指针,指向通过将字符串文本“?”
作为参数求值而创建的字符串对象
String#+
返回一个新字符串(或者更准确地说,是指向新字符串的不可变、不可伪造的指针)
str
被重新绑定到调用str+(“?”
返回的新的不可变、不可伪造指针
str.upcase代码>
str
被取消引用,导致从步骤7c到7d的新的不可变、不可伪造指针
- 我们跟随指针并发送消息
upcase代码>到对象
String#upcase
将改变receiver对象(在本例中,是步骤#7c中新创建的字符串),使所有字母都大写
String#upcase如果代码>对接收器做了任何更改,它将返回指向接收器对象本身的不可变、不可格式化指针(即用于调用方法的指针),或者如果字符串已经是大写或不包含任何字母,它将返回指向对象的不可变、不可格式化指针nil
回到change\u me(问题)
- 然而,这个返回值只是被忽略了,被丢弃了,没有打印,没有分配给变量,没有作为参数传递给其他方法,没有存储在数据结构中
提出问题
好的,现在变量被取消引用,我将保存细节,等等
关键部分是:变量question
从未被触及,也从未被重新赋值,因此它仍然包含与整个过程完全相同的内容:指向步骤1和步骤2中字符串对象的不可变、不可伪造的指针
我们将此对象指定给变量,并且我们:
- 从不重新指定变量,因此变量仍然指向同一对象
- 从未要求对象自身发生变异,因此对象的内容仍然相同
因此,对象仍然不变,变量仍然指向同一个对象,因此我们得到的结果是没有任何变化
我们在change\u me
方法内部更改了str
参数绑定的绑定,但该绑定是该方法的本地绑定。(参数绑定实际上相当于局部变量。)因此,它在方法返回时就不存在了
我们更改了新创建的string对象,但由于我们从未获得指向该对象的指针,因此无法访问它。一个指针存储在str
中,但它已经不存在了。另一个指针是从change\u me
返回的,但是我们把它扔掉了,所以它也不见了。因为没有参考t
def change_me(str)
str.upcase!
42
end
x = 'hello'
puts x # => hello
change_me(x)
puts x # => HELLO
def change_me(str)
p str.object_id
str += "?"
p str.object_id
str.upcase!
p str.object_id
end
def change_me_2(str)
p str.object_id
str << "?"
p str.object_id
str.upcase!
p str.object_id
end
def change_me(str)
str.upcase + '?'
end
question = "what's your name"
question = change_me(question)
question = change_me("what's your name")
def change_me(str)
str += "?"
str.upcase!
end
question = "whats your name"
puts change_me(question)