当您将参数传递给Ruby中的方法时,任何人都可以扩展,更正或验证我的感受。这些点中的任何一个都错了吗?我错过了什么作品吗?
有没有办法让一个方法将其参数作为其中一个参数作为整数,做一些事情,并且可能作为副作用更改值,一旦方法退出就反映出该变化。也许我只是不想“红宝石的方式”。
答案 0 :(得分:20)
Ruby中的所有东西都是一个对象。
足够近。
变量是对象的引用
没有。变量“命名”一个对象:当一个变量被计算时,它会计算出它当前“命名”的对象。在内部,这是通过“存储指针”(或等效机制)来完成的。 (虽然实现不需要总是使用指针:例如,在Ruby MRI中,Fixnum值实际上存在而没有一个真实对象。)
(将变量传入方法时):捕获变量的方法中的参数是该方法的局部变量。参数(局部变量)现在也有对同一对象的引用。
没有。往上看。但是,这两个变量现在都命名(或“评估为”)同一个对象。参数使用Call-by-Value在内部传递 - 即内部,传递对象的指针 - 尽管Ruby具有Call-by-Object-Sharing语义,这是我试图推广的一个术语,因为我发现它简洁地描述了这种行为。
我可以改变对象(就地),当退出方法范围时,这种改变将成立。在方法范围之外引用此对象的任何变量都将反映该对象已被更改。
是的,一个物体本身。如果你改变那个对象,你就会在任何地方改变那个对象。但请注意:没有任何变量被更改。内部和外部变量仍名称(或“评估为”)同一对象。
对该参数的新赋值(局部变量)不会更改原始对象,因此当方法离开作用域时对它的任何引用都将保持不变。
正确。如果为您创建的局部变量分配不同的值,则局部变量将其命名为另一个对象。 Ruby 不 Call-by-Reference所以调用上下文中的变量不会改变。
如果我将一个变量传递给引用Integer的方法,那么一旦该方法退出,我实际上没有办法让该变量引用一个新的Integer?
变量从不传递。 变量将根据它们命名的对象进行评估,并传递这些对象。无论如何,我们知道:
因此:
x = 1
y.foo(x)
永远不会更改x
个名称,甚至不能更改对象x
名称的内容(因为它是,嗯,不可变)。即使x
命名的对象是可变的,方法也无法更改对象x
的名称:它只能有变异评估x
所产生的对象。
快乐的编码。
现在,Ruby Way - 在我的书中 - 将使用一个更好的返回值,包含所有新状态,并让调用者将它放在需要的位置: - )
当然,可变对象(包括简单数组)也是一种选择,但那是 ick 。而且,如果有足够的州一起旅行,它可能是一个单独的班级的候选人。
作为结束语:Ruby支持闭包的概念,因此可以以词法范围的方式:
x = 1; (lambda {|a| x = a}).call(2); x // => 2
(这是针对一个简单的lambda显示的,但是可以设计/制作一个类似的方法:在这样的所有愚蠢的反例中,外部变量本身需要是但是,因为lambda /方法没有办法使外部变量名称成为新对象。)