当前位置:  开发笔记 > 后端 > 正文

为什么我们可以修改复杂参数但不修改ruby函数中的标量?

如何解决《为什么我们可以修改复杂参数但不修改ruby函数中的标量?》经验,为你挑选了1个好方法。

问题是Ruby通过引用或值传递?吸引了很多有用的答案,也有很多不同意见.到目前为止,我在任何答案中都没有看到的是解释以下内容的任何内容:

ruby -e "def f(x) x=7 end; a=3; f(a); print a" 打印3.

ruby -e "def f(x) x[0]=7 end; a=[3]; f(a); print a[0]" 打印7.

根据经验,这看起来像标量对象和更复杂的对象(如散列和数组)之间存在某种区别,标量通过引用传递给值和复杂对象.这类似于C的语义.

我的理解是ruby中的所有东西都是一个对象,而早期问题的答案都没有提到标量和复杂类型之间的区别.那么我的描述是错误的,如果是,那么更好的描述是什么?



1> tadman..:

这里术语的问题是Ruby是"通过对象引用传递",这是一种在其他语言中使用"指向对象的指针"的方式.Ruby中指针和引用之间的界限是模糊的,因为没有实际的指针,加上对象本身通过引用计数保存在内存中,其中指针最终成为引用.所以它们是指向对象的指针,而不是传统意义上与同一个变量硬链接的引用.

根据定义,每个变量总是代表一个对象,即使它没有被定义:nil它本身就是一个对象以及数字,甚至是浮点数.这使得术语"标量"几乎无关紧要,Ruby中没有基本类型,就像你在其他语言中一样,布尔值,数字,字符串和类实例之间的区别很大.

一般规则是您永远不能将变更反向传播到变量,但通过方法进行的更改确实会传播.要理解为什么,这里是Ruby看到你的代码的方式:

def f(x)
  # Change value of local variable x to 7
  x = 7
end

这只是重新定义x指向的对象,因为即使7是一个对象.

其他代码与Ruby的感知方式截然不同:

def f(x)
  # Send the []= method call to x with the argument 7
  x.send(:[]=, 7)
end

这会发送一条消息(方法调用)x来触发该[]=方法.该方法可以使用该值执行任何操作,但对于具有特定含义的数组,哈希和复数.它更新对象x引用的内部状态.

您可以在其他场景中看到这种情况:

def f(x)
  x += 'y'
end

这扩展到x = x + y使用中间结果进行变量重新分配.原始x值未修改.

def f(x)
  x << 'y'
end

在这种情况下,x.send(:<<, 'y')它会进行就地修改x,因此原始版本会被修改.

在编写和理解Ruby代码时,能够识别方法调用是一件很重要的事情.有时它们甚至都不那么明显.你认为存在=意味着"变量赋值",但事实并非如此:

def f(x)
  x.y = 'z'
end

这看起来像是分配给y属性,x但它不是,它只是调用y=方法,它相当于可以通过多种方式解释的x.send(:y=, 'z')东西x.这可能会修改价值,或者它可能会做一些完全不同的事情.没有x更密切的了解就无法知道.

推荐阅读
echo7111436
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有