Вопрос

This prints 1:

def sum(i)
  i=i+[2]
end

$x=[1]
sum($x)
print $x

This prints 12:

def sum(i)
  i.push(2)
end

$x=[1]
sum($x)
print $x

The latter is modifying the global variable $x. Why is it modified in the second example and not in the first one? Will this will happen with any method (not only push) of the class Array?

Это было полезно?

Решение

Variable scope is irrelevant here.

In the first code, you are only assigning to a variable i using the assignment operator =, whereas in the second code, you are modifying $x (also referred to as i) using a destructive method push. Assignment never modifies any object. It just provides a name to refer to an object. Methods are either destructive or non-destructive. Destructive methods like Array#push, String#concat modify the receiver object. Non-destructive methods like Array#+, String#+ do not modify the receiver object, but create a new object and return that, or return an already existing object.

Answer to your comment

Whether or not you can modify the receiver depends on the class of the receiver object. For arrays, hashes, and strings, etc., which are said to be mutable, it is possible to modify the receiver. For numerals, etc, which are said to be immutable, it is impossible to do that.

Другие советы

In the first snippet, you assign new local variable to hold result of $x + [2] operation which is returned, but it doesn't change $x (because + method doesn't modify receiver object). In your second snipped, you use Array#push method, which modifies an object (in this case, object assigned to $x global var and passed as i into your sum method) on which it's called.

i.push(2) appends 2 to the array pointed by i. Since this is the same array pointed by $x, $x gets 2 appended to it as well.

i=i+[2] creates a new array and set i to it - and now this is a different array than the one pointed by $x.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top