Tuesday, October 21, 2008

(5)赋值操作

在Ruby中复制操作通过=实现,这个我们前面一再提到。比如:
x+=1 #等同于x=x+
x*=1 #等同于x=x*1
x,y,z=1,2,3 #Ruby中的平行赋值,x=1,y=2,z=3
x,y,z=[1,2,3] #Ruby中的平行赋值,等号右边可以是一个数组,x=1,y=2,z=3
这些都很好理解,我主要想说说两个特殊情况。局部变量和平行赋值:
对于局部变量,因为没有类似全局变量的符号前缀,所以Ruby无法区分你现在用的x是一个局部变量还是一个方法,在这种情况下,如果你给x赋值那么Ruby认为这是一个局部变量。看下面的代码:
class Ambiguous
  def x; 1; end # 定义一个方法x,返回值为 1

  def test
    puts x      # 没有找到变量名为x,所以调用上面定义的方法:打印 1

    # 因为 "if false" 下面的第一行的赋值不会被执行. 但是
# Ruby解析器已经把他视为一个局部变量了.
    x = 0 if false

    puts x    # 现在x是一个变量但是没有被赋值: 打印nil

    x = 2     # 赋值为2
    puts x    # 所以现在打印 2
  end
end 
 
说到平行赋值,考虑下面的情况,如果等号左边只有一个变量,而右边有多个值,这种情况Ruby会将右边的值转换为一个数组:
x = 1, 2, 3      # x = [1,2,3]
但是如果左边的变量后有一个逗号,结果就不同了:
x, = 1, 2, 3   
  # x = 1;
 其他的值被忽略了
如果等号两边的变量和值不同,结果也不同:
Created with colorer-take5 library. Type 'ruby'

x, y = 1, 2, 3 # x=1; y=2; 3 is not assigned anywhere
#*有特殊的含义,表示后面是一个单独的数组
x, y, z = 1, *[2,3]  # Same as x,y,z = 1,2,3
x,*y = 1, 2, 3  # x=1; y=[2,3]
x,*y = 1, 2     # x=1; y=[2]
x,*y = 1        # x=1; y=[]
#如果存在括号,那么括号内的变量对应等号右边的相应值
x,y,z = 1,[2,3]             #  没有括号:x=1;y=[2,3];z=nil
x,(y,z) = 1,[2,3]           #  加上了括号:x=1;y=2;z=3
a,b,c,d = [1,[2,[3,4]]]     #  没有括号:a=1;b=[2,[3,4]];c=d=nil
a,(b,(c,d)) = [1,[2,[3,4]]] #  加上了括号:a=1;b=2;c=3;d=4
另外需要注意的一点是,如果平行赋值出现在一个方法的后面,Ruby会把逗号分隔的部分当作是方法的参数:
puts x,y=1,2 #Ruby会认为你给puts方法赋值x , y=1 和2 这3个参数。

No comments: