新手问题 关于一个赋值的问题,求原理

jarorwar · 2013年02月19日 · 最后由 jjym 回复于 2013年02月20日 · 2705 次阅读

x,y=1,2 x,y=y,x

puts x,y

输出为:2,1

想问的是 x,y=y,x 的内部是怎么实现的?

谁知道的回答下,在传统的语言中,我们需要有一个临时中间数来辅助完成交换工作 如下: temp = x x=y y=temp

以这样理解的话 x,y=y,x 其实的值应该是 2 2

还是不明白啊~求解。

就是并行赋值 大概从逻辑上来讲应该是这样,右值会放到一个数组中,然后被依次赋值给左值(这个数组也是一个对象),可以用一个数组去赋值试试,发现结果会是一样的

做个实验如下:

1.9.3-p362 :001 > x, y = 1, 2
 => [1, 2]
1.9.3-p362 :002 > x.object_id
 => 3
1.9.3-p362 :003 > y.object_id
 => 5
1.9.3-p362 :006 > x, y = y, x
 => [2, 1]
1.9.3-p362 :007 > x.object_id
 => 5
1.9.3-p362 :008 > y.object_id
 => 3
1.9.3-p362 :009 > x, y = [y, x]
 => [1, 2]
1.9.3-p362 :010 > x.object_id
 => 3
1.9.3-p362 :011 > y.object_id
 => 5

当然,底层应该还是解释器去实现的

#1 楼 @Tony612 非常感谢您的回答。您这个代码很不错~非常感谢。另外,从您的例子来看 1.9.3-p362 :006 > x, y = y, x => [2, 1] 1.9.3-p362 :007 > x.object_id => 5 1.9.3-p362 :008 > y.object_id => 3

其实底层是 object_id 做了交换!或许在解释器执行的时候存在过一个临时 的 temp,ruby 把这部分工作也做了?

欢迎继续讨论,新手问题,望各位不吝赐教,在此先谢过了

#2 楼 @jarorwar 关于这个 我想是因为 ruby 是纯面向对象的,所以即使是直接赋值

1.9.3-p362 :001 > x = 1
 => 1
1.9.3-p362 :003 > x.object_id
 => 3
1.9.3-p362 :004 > y = 2
 => 2
1.9.3-p362 :005 > y.object_id
 => 5
1.9.3-p362 :006 > x = y
 => 2
1.9.3-p362 :007 > x.object_id
 => 5

如果要问再改变 y 的值,x 会怎样。可以发现,x 并不会改变,原因应该是一个数字其实也是一个对象。

1.9.3-p362 :008 > y.object_id
 => 5
1.9.3-p362 :009 > y = 3
 => 3
1.9.3-p362 :010 > x
 => 2
1.9.3-p362 :011 > x.object_id
 => 5
1.9.3-p362 :012 > y.object_id
 => 7

不知道我解释的对不,欢迎高手指正。。

@Tony612 我又做了一个试验。如果单个赋值的话按正常理解没有任何问题 irb(main):001:0> x=1 => 1 irb(main):002:0> y=2 => 2 irb(main):003:0> x.object_id => 3 irb(main):004:0> y.object_id => 5 irb(main):005:0> x=y => 2 irb(main):006:0> x.object_id => 5 irb(main):007:0> y => 2 irb(main):008:0> y.object_id => 5 irb(main):009:0> y=x => 2 irb(main):010:0> y.object_id => 5 irb(main):011:0> puts x,y 2 2

不知道这个我理解的对不对。即使这个理解是正确的,我还是无法明白 x,y=y,x 这样赋值会交换,x 和 y

#5 楼 @jarorwar 语法糖啊,这个要看编译后的虚拟机指令是什么

#6 楼 @jjym 这个编译后指令,我怎么去看啊~ 刚接触 ruby,还是很不懂啊~发现跟 java 完全不一样了啊~

#7 楼 @jarorwar 请@论坛里的高手们并坐等答案。。。

#8 楼 @jjym 呵呵,好的。谢谢大家的关注啊

"x = 1;y = 2; x,y = y,x"
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
local table (size: 3, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 3] x          [ 2] y          
0000 trace            1                                               (   1)
0002 putobject        1
0004 setlocal         x
0006 trace            1
0008 putobject        2
0010 setlocal         y
0012 trace            1
0014 getlocal         y
0016 getlocal         x
0018 newarray         2
0020 dup              
0021 expandarray      2, 0
0024 setlocal         x
0026 setlocal         y
0028 leave

1# 说的对

需要 登录 后方可回复, 如果你还没有账号请 注册新账号