参数是通过引用还是值传递给方法的?

[英]Are arguments passed to methods by reference or value?


Can anyone expand upon, correct, or verify what I feel is happening when you pass arguments to a method in Ruby. Are any of these points wrong? Am I missing any pieces?

当你将参数传递给Ruby中的方法时,任何人都可以扩展,纠正或验证我的感受。这些点中的任何一个都错了吗?我错过任何一件作品吗?

  • Everything in Ruby is an object.
  • Ruby中的所有东西都是一个对象。
  • Variables are references to objects
  • 变量是对象的引用
  • (When passing in a variable into a method): The parameter in the method that catches the variable is a local variable to that method. The parameter (local variable) now also has a reference to the same object.
  • (将变量传入方法时):捕获变量的方法中的参数是该方法的局部变量。参数(局部变量)现在也具有对同一对象的引用。
  • I could alter the object (in place) and this alteration will hold when the method scope is exited. Any variables referencing this object outside the method scope will reflect that the object has been altered.
  • 我可以改变对象(就地),当退出方法范围时,这种改变将成立。在方法范围之外引用此对象的任何变量都将反映该对象已被更改。
  • A new assignment to that parameter (local variable) does not change the original object, thus any references to it when the method leaves scope will remain unchanged.
  • 对该参数的新赋值(局部变量)不会更改原始对象,因此当方法离开作用域时对它的任何引用都将保持不变。
  • If I am passing a variable into the method that references an Integer there is effectively no way that once that method exits I could have that variable referencing a new Integer.
  • 如果我将一个变量传递给引用Integer的方法,那么一旦该方法退出,我就无法使该变量引用一个新的Integer。

Is there any way to have a method that takes as one of its parameters an Integer, does some stuff, and maybe as a side effect changes the value, having that change reflected once the method exits. Maybe I am just not thinking "the Ruby way".

有没有办法让一个方法作为其参数之一的整数,做一些东西,并可能作为副作用更改值,一旦方法退出反映了该变化。也许我只是不想“Ruby方式”。

1 个解决方案

#1


20  

Everything in Ruby is an object.

Ruby中的所有东西都是一个对象。

Close enough.

足够近。

Variables are references to objects

变量是对象的引用

No. A variable "names" an object: when a variable is evaluated, it evaluates to the object that it currently "names". Internally this is done by "storing a pointer" (or equivalent mechanism) to an object. (Although an implementation does not need to always use pointers: in Ruby MRI, for instance, Fixnum values actually exist without a real object.)

否。变量“命名”一个对象:当一个变量被评估时,它会计算出它当前“命名”的对象。在内部,这是通过“存储指针”(或等效机制)到对象来完成的。 (虽然实现不需要总是使用指针:例如,在Ruby MRI中,Fixnum值实际上没有真实对象。)

(When passing in a variable into a method): The parameter in the method that catches the variable is a local variable to that method. The parameter (local variable) now also has a reference to the same object.

(将变量传入方法时):捕获变量的方法中的参数是该方法的局部变量。参数(局部变量)现在也具有对同一对象的引用。

No. See above. However, both variables now name (or "evaluate to") the same object. The parameters are passed internally using Call-by-Value -- that is, internally, the pointers to the objects are passed -- although Ruby has Call-by-Object-Sharing semantics, which is a term I try to promote as I find it succinctly describes the behavior.

不,见上文。但是,这两个变量现在都命名(或“评估为”)同一个对象。参数在内部使用Call-by-Value传递 - 也就是说,在内部传递指向对象的指针 - 虽然Ruby具有Call-by-Object-Sharing语义,这是我试图提升的术语,因为我发现它简洁地描述了这种行为。

I could alter the object (in place) and this alteration will hold when the method scope is exited. Any variables referencing this object outside the method scope will reflect that the object has been altered.

我可以改变对象(就地),当退出方法范围时,这种改变将成立。在方法范围之外引用此对象的任何变量都将反映该对象已被更改。

Yes, an object is itself. If you mutate that object, you mutate that object everywhere. But note: none of the variables are changed. Both the inside and the outside variables will still name (or "evaluate to") the same object.

是的,一个对象本身。如果您改变该对象,则会在任何地方改变该对象。但请注意:没有变量发生变化。内部和外部变量仍然会命名(或“评估”)同一个对象。

A new assignment to that parameter (local variable) does not change the original object, thus any references to it when the method leaves scope will remain unchanged.

对该参数的新赋值(局部变量)不会更改原始对象,因此当方法离开作用域时对它的任何引用都将保持不变。

Correct. If you assign a different value to the local variable you make it, the local variable, name a different object. Ruby is not Call-by-Reference so the variable in the calling context is not altered.

正确。如果为您创建的局部变量分配不同的值,则局部变量将其命名为另一个对象。 Ruby不是Call-by-Reference,因此调用上下文中的变量不会改变。

If I am passing a variable into the method that references an Integer there is effectively no way that once that method exits I could have that variable referencing a new Integer?

如果我将一个变量传递给引用Integer的方法,那么一旦该方法退出,我实际上没有办法让该变量引用一个新的Integer?

Variables are never passed. Variables are evaluated to the objects they name and those objects are passed. Anyway, we know that:

变量永远不会传递。变量将根据它们命名的对象进行计算,并传递这些对象。无论如何,我们知道:

  1. Ruby is not Call-by-Reference and;
  2. Ruby不是Call-by-Reference;
  3. Integers (Fixnums) are immutable
  4. 整数(Fixnums)是不可变的

Thus:

从而:

x = 1
y.foo(x)

can never change what x names, nor can it even change the contents of the object x names (because it's, well, immutable). Even if the object that x named was mutable, the method could not have changed what object x names: it could only have mutated the object that resulted from the evaluation of x.

永远不能改变什么x名称,甚至不能改变对象x名称的内容(因为它是,嗯,不可变)。即使x命名的对象是可变的,该方法也不能改变对象x名称:它只能改变由x的评估产生的对象。

Happy coding.

快乐的编码。


Now, The Ruby Way -- in my book -- would be to use a better return value that compassed all the new state, and let the caller put it where it needs to go :-)

现在,Ruby Way - 在我的书中 - 将使用更好的返回值来包含所有新状态,并让调用者将它放在需要去的地方:-)

Of course, mutable objects (including simple arrays) are also an option, but that's ick. And, if there is enough state that travels together, it might be a candidate for a separate class.

当然,可变对象(包括简单数组)也是一种选择,但那就是ick。而且,如果有足够的州一起旅行,它可能是一个单独的班级的候选人。


As a closing note: Ruby supports a concept of closures, so it is possible in a lexically-scoped manner:

作为结束语:Ruby支持闭包的概念,因此可以以词法范围的方式:

x = 1; (lamb­da {|a| x = a}).c­all(2); x  // => 2

(This was shown for a simple lambda, but it is possible to design/craft a method to work similarly: in all the silly counter-examples like this, the outside variable itself needs to be known, however, as there is no way for the lambda/method of make an outside variable name a new object otherwise.)

(这是针对一个简单的lambda显示的,但是可以设计/制作一个类似的方法:在这样的所有愚蠢的反例中,外部变量本身需要知道,但是,因为没有办法lambda /方法使外部变量名称成为新对象。)


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.itdaan.com/blog/2012/01/06/ab83f3605deb29e3263471123be3d62.html



 
© 2014-2018 ITdaan.com 粤ICP备14056181号