Dans ce qui suit, input_1
change:
def method_2(a) a = ["new value"] end input_2 = [] method_2(input_2) input_2 #=> []
Dans ce qui suit, input_2
ne change pas:
def method_1(a) a << "new value" end input_1 = [] method_1(input_1) input_1 #=> ["new value"]
Pourquoi input_1
change-t-il alors que input_2
ne change pas?
3 Réponses :
Avec un peu de simplification, nous pouvons dire qu'une variable dans Ruby est une référence à une valeur. Dans votre cas, la variable a
contient une référence à un tableau.
a (
a.append
) modifie la valeur stocké dans la variable a
. La référence n'est pas modifiée, mais la valeur l'a fait. C'est le cas de method_1
def method_2(a) a = ["new value"] end input = [] method_2(a)
L'affectation =
change la référence stockée dans une variable - elle commence à pointer vers un valeur différente. Les références sont copiées lorsqu'elles sont transmises à une méthode. Pour cette raison, lorsque vous appelez
def method_1(a) a << "new value" end
Vous ne modifiez qu'une référence stockée dans a
qui est locale à la méthode, sans aucune modification de la référence stockée dans input
ni à la valeur (et au tableau de []
) qui est pointé par cette référence.
Notez que si l'appel était changé en input_2 = method_2 (input_2)
, la nouvelle référence générée par method_2
serait affectée à input_2
depuis les méthodes Ruby renvoie le résultat de leur dernière évaluation.
Cela se résume à Ruby en utilisant "pass-reference-by-value".
Le cas exact que vous rencontrez est décrit dans cet excellent article de blog .
Dans method_1
, vous modifiez la valeur d'un objet vers lequel pointent deux variables différentes ( input_1
et a
). p>
Dans method_2
, vous réaffectez un objet complètement nouveau à l'une des deux variables ( a
).
Pourquoi
input_1
change alors queinput_2
ne change pas?
La réponse très simple à cette question est que votre prémisse est fausse. input_1
ne change pas. L'objet auquel input_1
fait référence change, mais c'est quelque chose de complètement différent de input_1
. Le nom d'une chose n'est pas identique à la chose elle-même. (En dehors de la sorcellerie.)
Quelle est votre question exactement? Vous vous attendez à ce que la valeur de l'entrée soit
['new value']
les deux fois?Pourquoi change input_1 alors que input_2 ne change pas?
le concept est appelé «mutabilité».
method_2
assigne simplement une nouvelle variable avec le même nom que l'autre.