¿Ruby pasa por referencia o por valor?


248
@user.update_languages(params[:language][:language1], 
                       params[:language][:language2], 
                       params[:language][:language3])
lang_errors = @user.errors
logger.debug "--------------------LANG_ERRORS----------101-------------" 
                + lang_errors.full_messages.inspect

if params[:user]
  @user.state = params[:user][:state]
  success = success & @user.save
end
logger.debug "--------------------LANG_ERRORS-------------102----------" 
                + lang_errors.full_messages.inspect

if lang_errors.full_messages.empty?

@userEl objeto agrega errores a la lang_errorsvariable en el update_lanugagesmétodo. cuando guardo el @userobjeto pierdo los errores que se almacenaron inicialmente en la lang_errorsvariable.

Aunque lo que intento hacer sería más un truco (que no parece estar funcionando). Me gustaría entender por qué se borran los valores de las variables. Entiendo pasar por referencia, así que me gustaría saber cómo se puede mantener el valor en esa variable sin ser eliminado.


También noto que soy capaz de retener ese valor en un objeto clonado
Sid

1
Deberías mirar la respuesta de Abe Voelker. Pero después de correr alrededor del bloque en esto, así es como lo diría. cuando pasa un objeto Foo a un procedimiento, se pasa una copia de la referencia al objeto, barra, Pasar por valor. no puede cambiar el objeto al que apunta Foo, pero puede cambiar el contenido del objeto al que apunta. Entonces, si pasa una matriz, el contenido de la matriz se puede cambiar, pero no puede cambiar a qué matriz se hace referencia. Es bueno poder utilizar los métodos de Foo sin tener que preocuparse por estropear otras dependencias de Foo.
bobbdelsol

Respuestas:


244

En la terminología tradicional, Ruby es estrictamente paso por valor . Pero eso no es realmente lo que estás preguntando aquí.

Ruby no tiene ningún concepto de valor puro, sin referencia, por lo que ciertamente no puede pasar uno a un método. Las variables son siempre referencias a objetos. Para obtener un objeto que no cambie debajo de usted, debe duplicar o clonar el objeto que le pasó, dando así un objeto al que nadie más tiene referencia. (Aunque esto no es a prueba de balas, ambos métodos de clonación estándar hacen una copia superficial, por lo que las variables de instancia del clon todavía apuntan a los mismos objetos que los originales. Si los objetos a los que hace referencia el ivars mutan, eso todavía aparece en la copia, ya que hace referencia a los mismos objetos).


88
Ruby es paso por valor . No si. Sin peros. Sin excepciones. Si desea saber si Ruby (o cualquier otro idioma) es pasar por referencia o pasan por valor , simplemente probarlo: def foo(bar) bar = 'reference' end; baz = 'value'; foo(baz); puts "Ruby is pass-by-#{baz}".
Jörg W Mittag

95
@ JörgWMittag: Sí, pero la confusión del OP no es en realidad pasar por valor o pasar por referencia en el estricto sentido CS de las palabras. Lo que le faltaba es que los "valores" que está pasando son referencias. Sentí que solo decir "Es un paso por valor" sería pedante y perjudicaría al OP, ya que eso no es realmente lo que quiso decir. Pero gracias por la aclaración, porque es importante para futuros lectores y debería haberla incluido. (Siempre estoy dividido entre incluir más información y no confundir a las personas.)
Chuck

16
No estoy de acuerdo con @Jorg. Ruby se pasa por referencia, solo cambia la referencia. Intente esto en su lugar: def foo (bar) bar.replace 'reference' end; baz = 'valor'; foo (baz); pone "Ruby is pass-by - # {baz}"
pguardiario

15
@pguardiario: Creo que en realidad es solo una cuestión de definiciones. Está utilizando una definición de "paso por referencia" que ha ideado personalmente, mientras que Jörg está utilizando la definición tradicional de informática. Por supuesto, no es de mi incumbencia decirle cómo usar las palabras, solo creo que es importante explicar qué significa normalmente el término . En la terminología tradicional, Ruby es paso por valor, pero los valores en sí mismos son referencias. Entiendo totalmente por qué a usted y al OP les gusta pensar en esto como una referencia, simplemente no es el significado tradicional del término.
Chuck

77
Todo en Ruby es un objeto, por lo que Ruby no es pasar por valor ni pasar por referencia, al menos en el sentido de que esos términos se usan en C ++. "pasar por referencia de objeto" podría ser una mejor manera de describir lo que hace Ruby. Al final, sin embargo, la mejor opción podría ser no dar demasiado significado a ninguno de estos términos, y simplemente obtener una buena comprensión del comportamiento que realmente sucede.
David Winiecki

424

Las otras respuestas son correctas, pero un amigo me pidió que le explicara esto y lo que realmente se reduce a cómo Ruby maneja las variables, por lo que pensé que compartiría algunas imágenes / explicaciones simples que escribí para él (disculpas por la longitud y probablemente alguna simplificación excesiva):


P1: ¿Qué sucede cuando asigna una nueva variable stra un valor de 'foo'?

str = 'foo'
str.object_id # => 2000

ingrese la descripción de la imagen aquí

R: Se strcrea una etiqueta llamada que apunta al objeto 'foo', que para el estado de este intérprete de Ruby se encuentra en la ubicación de la memoria 2000.


P2: ¿Qué sucede cuando asigna la variable existente stra un nuevo objeto usando =?

str = 'bar'.tap{|b| puts "bar: #{b.object_id}"} # bar: 2002
str.object_id # => 2002

ingrese la descripción de la imagen aquí

A: La etiqueta strahora apunta a un objeto diferente.


P3: ¿Qué sucede cuando asigna una nueva variable =a str?

str2 = str
str2.object_id # => 2002

ingrese la descripción de la imagen aquí

R: Se str2crea una nueva etiqueta llamada que apunta al mismo objeto que str.


P4: ¿Qué sucede si el objeto al que hace referencia stry str2se cambia?

str2.replace 'baz'
str2 # => 'baz'
str  # => 'baz'
str.object_id # => 2002
str2.object_id # => 2002

ingrese la descripción de la imagen aquí

R: Ambas etiquetas todavía apuntan al mismo objeto, pero ese objeto en sí mismo ha mutado (su contenido ha cambiado para ser otra cosa).


¿Cómo se relaciona esto con la pregunta original?

Básicamente es lo mismo que sucede en Q3 / Q4; el método obtiene su propia copia privada de la variable / etiqueta ( str2) que se le pasa ( str). No puede cambiar a qué objeto str apunta la etiqueta , pero puede cambiar el contenido del objeto al que ambos hacen referencia para contener:

str = 'foo'

def mutate(str2)
  puts "str2: #{str2.object_id}"
  str2.replace 'bar'
  str2 = 'baz'
  puts "str2: #{str2.object_id}"
end

str.object_id # => 2004
mutate(str) # str2: 2004, str2: 2006
str # => "bar"
str.object_id # => 2004

1
Robert Heaton también blogueó sobre esto últimamente: robertheaton.com/2014/07/22/…
Michael Renner

48

Ruby usa "pasar por referencia de objeto"

(Usando la terminología de Python).

Decir que Ruby usa "pasar por valor" o "pasar por referencia" no es realmente lo suficientemente descriptivo como para ser útil. Creo que, como la mayoría de la gente lo sabe en estos días, esa terminología ("valor" vs "referencia") proviene de C ++.

En C ++, "pasar por valor" significa que la función obtiene una copia de la variable y cualquier cambio en la copia no cambia el original. Eso también es cierto para los objetos. Si pasa una variable de objeto por valor, se copia todo el objeto (incluidos todos sus miembros) y cualquier cambio en los miembros no cambia esos miembros en el objeto original. (Es diferente si pasa un puntero por valor, pero Ruby no tiene punteros de todos modos, AFAIK).

class A {
  public:
    int x;
};

void inc(A arg) {
  arg.x++;
  printf("in inc: %d\n", arg.x); // => 6
}

void inc(A* arg) {
  arg->x++;
  printf("in inc: %d\n", arg->x); // => 1
}

int main() {
  A a;
  a.x = 5;
  inc(a);
  printf("in main: %d\n", a.x); // => 5

  A* b = new A;
  b->x = 0;
  inc(b);
  printf("in main: %d\n", b->x); // => 1

  return 0;
}

Salida:

in inc: 6
in main: 5
in inc: 1
in main: 1

En C ++, "pasar por referencia" significa que la función obtiene acceso a la variable original. Puede asignar un entero literal completamente nuevo y la variable original también tendrá ese valor.

void replace(A &arg) {
  A newA;
  newA.x = 10;
  arg = newA;
  printf("in replace: %d\n", arg.x);
}

int main() {
  A a;
  a.x = 5;
  replace(a);
  printf("in main: %d\n", a.x);

  return 0;
}

Salida:

in replace: 10
in main: 10

Ruby usa pasar por valor (en el sentido de C ++) si el argumento no es un objeto. Pero en Ruby todo es un objeto, por lo que realmente no hay un paso por valor en el sentido de C ++ en Ruby.

En Ruby, se usa "pasar por referencia de objeto" (para usar la terminología de Python):

  • Dentro de la función, cualquiera de los miembros del objeto puede tener nuevos valores asignados y estos cambios persistirán después de que la función regrese. *
  • Dentro de la función, la asignación de un objeto completamente nuevo a la variable hace que la variable deje de hacer referencia al objeto antiguo. Pero después de que la función regrese, la variable original seguirá haciendo referencia al objeto antiguo.

Por lo tanto, Ruby no usa "pasar por referencia" en el sentido de C ++. Si lo hiciera, la asignación de un nuevo objeto a una variable dentro de una función haría que el objeto antiguo se olvidara después de que la función regresara.

class A
  attr_accessor :x
end

def inc(arg)
  arg.x += 1
  puts arg.x
end

def replace(arg)
  arg = A.new
  arg.x = 3
  puts arg.x
end

a = A.new
a.x = 1
puts a.x  # 1

inc a     # 2
puts a.x  # 2

replace a # 3
puts a.x  # 2

puts ''

def inc_var(arg)
  arg += 1
  puts arg
end

b = 1     # Even integers are objects in Ruby
puts b    # 1
inc_var b # 2
puts b    # 1

Salida:

1
2
2
3
2

1
2
1

* Esta es la razón por la cual, en Ruby, si desea modificar un objeto dentro de una función pero olvida esos cambios cuando la función regresa, debe hacer explícitamente una copia del objeto antes de realizar sus cambios temporales en la copia.


Tu respuesta es la mejor. También quiero publicar un ejemplo simple def ch(str) str.reverse! end; str="abc"; ch(str); puts str #=> "cba"
fangxing el

¡Esta es la respuesta correcta! Esto también se explica muy bien aquí: robertheaton.com/2014/07/22/… . Pero lo que todavía no entiendo es la siguiente: def foo(bar) bar = 'reference' end; baz = 'value'; foo(baz); puts "Ruby is pass-by-#{baz}". Esto imprime "Ruby es paso por valor". Pero la variable dentro foose reasigna. Si barfuera una matriz, la reasignación no tendría efecto baz. ¿Por qué?
Haffla

No entiendo tu pregunta. Creo que deberías hacer una pregunta completamente nueva en lugar de hacer comentarios aquí.
David Winiecki

42

¿Ruby pasa por referencia o por valor?

Ruby es paso por valor. Siempre. Sin excepciones. No si. Sin peros.

Aquí hay un programa simple que demuestra ese hecho:

def foo(bar)
  bar = 'reference'
end

baz = 'value'

foo(baz)

puts "Ruby is pass-by-#{baz}"
# Ruby is pass-by-value

15
@DavidJ .: "El error aquí es que el parámetro local es reasignado (apuntado a un nuevo lugar en la memoria)" - Eso no es un error, esa es la definición de paso por valor . Si Ruby fuera paso por referencia, la reasignación al enlace del argumento del método local en el destinatario también habría reasignado el enlace de la variable local en el llamador. Lo cual no fue así. Ergo, Ruby es paso por valor. El hecho de que si cambia un valor mutable, el valor cambia es completamente irrelevante, así es como funciona el estado mutable. Ruby no es un lenguaje funcional puro.
Jörg W Mittag

55
Gracias a Jörg por defender la verdadera definición de "paso por valor". Claramente está derritiendo nuestro cerebro cuando el valor es de hecho una referencia, aunque ruby ​​siempre pasa por valor.
Douglas

99
Esto es sofisma. La distinción práctica entre "pasar por valor" y "pasar por referencia" es semántica, no sintáctica. ¿Diría que las matrices C son pasadas por valor? Por supuesto que no, aunque cuando pasa el nombre de una matriz a una función, está pasando un puntero inmutable, y solo los datos a los que se refiere el puntero pueden mutarse. Claramente, los tipos de valor en Ruby se pasan por valor, y los tipos de referencia se pasan por referencia.
dodgethesteamroller

3
@dodgethesteamroller: tanto Ruby como C son pases por valor. Siempre. Sin excepciones, no si no hay peros. La distinción entre pasar por valor y pasar por referencia es si pasa el valor al que apunta la referencia o pasa la referencia. C siempre pasa el valor, nunca la referencia. El valor puede o no ser un puntero, pero lo que el valor es irrelevante es si se pasa en primer lugar. Ruby también siempre pasa el valor, nunca la referencia. Ese valor siempre es un puntero, pero de nuevo, eso es irrelevante.
Jörg W Mittag

44
Esta respuesta, aunque estrictamente hablando es cierta , no es muy útil . El hecho de que el valor que se pasa siempre sea un puntero no es irrelevante. Es una fuente de confusión para las personas que están tratando de aprender, y su respuesta no hace absolutamente nada para ayudar con esa confusión.

20

Ruby es paso por valor en sentido estricto, PERO los valores son referencias.

Esto podría llamarse " referencia de paso por valor ". Este artículo tiene la mejor explicación que he leído: http://robertheaton.com/2014/07/22/is-ruby-pass-by-reference-or-pass-by-value/

La referencia de paso por valor podría explicarse brevemente de la siguiente manera:

Una función recibe una referencia (y accederá) al mismo objeto en la memoria utilizado por la persona que llama. Sin embargo, no recibe el cuadro en el que la persona que llama está almacenando este objeto; como en pass-value-by-value, la función proporciona su propio cuadro y crea una nueva variable para sí misma.

El comportamiento resultante es en realidad una combinación de las definiciones clásicas de paso por referencia y paso por valor.


"pasar referencia por valor" es la misma frase que uso para describir el argumento de Ruby. Creo que es la frase más precisa y sucinta.
Wayne Conrad

16

Ya hay algunas respuestas excelentes, pero quiero publicar la definición de un par de autoridades sobre el tema, pero también esperando que alguien pueda explicar lo que dijeron las autoridades Matz (creador de Ruby) y David Flanagan en su excelente libro O'Reilly, El lenguaje de programación Ruby .

[desde 3.8.1: Referencias de objetos]

Cuando pasa un objeto a un método en Ruby, es una referencia de objeto que se pasa al método. No es el objeto en sí mismo, y no es una referencia a la referencia al objeto. Otra forma de decir esto es que los argumentos del método se pasan por valor en lugar de por referencia , pero que los valores pasados ​​son referencias de objeto.

Debido a que las referencias de objetos se pasan a métodos, los métodos pueden usar esas referencias para modificar el objeto subyacente. Estas modificaciones son visibles cuando el método regresa.

Todo esto tiene sentido para mí hasta el último párrafo, y especialmente esa última oración. Esto es, en el mejor de los casos, engañoso y, en el peor, confuso. ¿Cómo, de alguna manera, las modificaciones a esa referencia pasada por valor podrían cambiar el objeto subyacente?


1
Porque la referencia no se está modificando; El objeto subyacente es.
dodgethesteamroller

1
Porque el objeto es mutable. Ruby no es un lenguaje puramente funcional. Esto es completamente ortogonal a paso por referencia frente a paso por valor (excepto por el hecho de que en un lenguaje puramente funcional, paso por valor y paso por referencia siempre producen los mismos resultados, por lo que el lenguaje podría use uno o ambos sin que usted lo sepa).
Jörg W Mittag

Un buen ejemplo sería si, en lugar de una asignación variable en una función, observa el caso de pasar un hash a una función y hacer una fusión. en el hash pasado. El hash original termina modificado.
elc

16

¿Ruby pasa por referencia o por valor?

Ruby es paso por referencia. Siempre. Sin excepciones. No si. Sin peros.

Aquí hay un programa simple que demuestra ese hecho:

def foo(bar)
  bar.object_id
end

baz = 'value'

puts "#{baz.object_id} Ruby is pass-by-reference #{foo(baz)} because object_id's (memory addresses) are always the same ;)"

=> 2279146940 Ruby es una referencia de paso 2279146940 porque los object_id (direcciones de memoria) son siempre iguales;)

def bar(babar)
  babar.replace("reference")
end

bar(baz)

puts "some people don't realize it's reference because local assignment can take precedence, but it's clearly pass-by-#{baz}"

=> algunas personas no se dan cuenta de que es referencia porque la asignación local puede tener prioridad, pero es claramente una referencia


Esta es la única respuesta correcta y presenta algunos buenos trucos: prueba a = 'foobar'; b = a; b [5] = 'z', tanto a como b se modificarán.
Martijn

2
@ Martijn: su argumento no es del todo válido. Repasemos su código declaración por declaración. a = 'foobar' crea una nueva referencia que apunta a 'foobar'. b = a crea una segunda referencia a los mismos datos que a. b [5] = 'z' cambia el sexto carácter del valor referenciado por b a 'z' (el valor al que también hace referencia casualmente se modifica). Es por eso que "ambos se modifican" en sus términos, o más precisamente, por qué "el valor referenciado por ambas variables se modifica".
Lukas_Skywalker

2
No está haciendo nada con la referencia en su barmétodo. Simplemente está modificando el objeto al que apunta la referencia , pero no la referencia en sí. La única forma de modificar referencias en Ruby es por asignación. No puede modificar referencias llamando a métodos en Ruby porque los métodos solo se pueden invocar en objetos y las referencias no son objetos en Ruby. Su ejemplo de código demuestra que Ruby ha compartido un estado mutable (que no se está discutiendo aquí), sin embargo, no hace nada para iluminar la distinción entre pasar por valor y pasar por referencia.
Jörg W Mittag

1
Cuando alguien pregunta si un idioma es "paso por referencia", generalmente quiere saber cuándo pasa algo a una función y la función lo modifica, ¿se modificará fuera de la función? Para Ruby, la respuesta es "sí". Esta respuesta es útil para demostrar que la respuesta de @ JörgWMittag es extremadamente inútil.
Toby 1 Kenobi

@ Toby1Kenobi: Por supuesto, puede usar su propia definición personal del término "pasar por valor", que es diferente de la definición común y ampliamente utilizada. Sin embargo, si lo hace, debe estar preparado para que las personas se confundan, especialmente si descuida revelar el hecho de que está hablando de una noción muy diferente, en algunos aspectos, incluso opuesta a la de todos los demás. En particular, "pasar por referencia" no se refiere a si el "algo" que se pasa puede o no modificarse, sino más bien a qué es ese "algo", en particular, si es la referencia ...
Jörg W Mittag

8

Los parámetros son una copia de la referencia original. Por lo tanto, puede cambiar los valores, pero no puede cambiar la referencia original.


2

Prueba esto:--

1.object_id
#=> 3

2.object_id
#=> 5

a = 1
#=> 1
a.object_id
#=> 3

b = 2
#=> 2
b.object_id
#=> 5

el identificador a contiene object_id 3 para el objeto de valor 1 y el identificador b contiene object_id 5 para el objeto de valor 2.

Ahora hacer esto:--

a.object_id = 5
#=> error

a = b
#value(object_id) at b copies itself as value(object_id) at a. value object 2 has object_id 5
#=> 2

a.object_id 
#=> 5

Ahora, a y b contienen el mismo object_id 5 que se refiere al objeto de valor 2. Entonces, la variable Ruby contiene object_ids para referirse a los objetos de valor.

Hacer lo siguiente también da error: -

c
#=> error

pero hacer esto no dará error: -

5.object_id
#=> 11

c = 5
#=> value object 5 provides return type for variable c and saves 5.object_id i.e. 11 at c
#=> 5
c.object_id
#=> 11 

a = c.object_id
#=> object_id of c as a value object changes value at a
#=> 11
11.object_id
#=> 23
a.object_id == 11.object_id
#=> true

a
#=> Value at a
#=> 11

Aquí el identificador a devuelve el objeto de valor 11 cuyo id de objeto es 23, es decir, object_id 23 está en el identificador a, ahora vemos un ejemplo utilizando el método.

def foo(arg)
  p arg
  p arg.object_id
end
#=> nil
11.object_id
#=> 23
x = 11
#=> 11
x.object_id
#=> 23
foo(x)
#=> 11
#=> 23

arg en foo se asigna con el valor de retorno de x. Muestra claramente que el argumento es pasado por el valor 11, y siendo el valor 11 un objeto en sí mismo, tiene un ID de objeto único 23.

Ahora vea esto también: -

def foo(arg)
  p arg
  p arg.object_id
  arg = 12
  p arg
  p arg.object_id
end

#=> nil
11.object_id
#=> 23
x = 11
#=> 11
x.object_id
#=> 23
foo(x)
#=> 11
#=> 23
#=> 12
#=> 25
x
#=> 11
x.object_id
#=> 23

Aquí, el identificador arg primero contiene object_id 23 para referir 11 y después de la asignación interna con el objeto de valor 12, contiene object_id 25. Pero no cambia el valor al que hace referencia el identificador x utilizado en el método de llamada.

Por lo tanto, Ruby es pasar por valor y las variables de Ruby no contienen valores, pero contienen referencias al objeto de valor.


1

Ruby es interpretado. Las variables son referencias a datos, pero no los datos en sí. Esto facilita el uso de la misma variable para datos de diferentes tipos.

La asignación de lhs = rhs luego copia la referencia en la rhs, no los datos. Esto difiere en otros lenguajes, como C, donde la asignación hace una copia de datos a lhs de rhs.

Entonces, para la llamada a la función, la variable pasada, digamos x, se copia en una variable local en la función, pero x es una referencia. Luego habrá dos copias de la referencia, ambas haciendo referencia a los mismos datos. Uno estará en la persona que llama, uno en la función.

La asignación en la función luego copiaría una nueva referencia a la versión de la función de x. Después de esto, la versión de x de la persona que llama permanece sin cambios. Sigue siendo una referencia a los datos originales.

Por el contrario, usar el método .replace en x hará que ruby ​​haga una copia de datos. Si se usa el reemplazo antes de cualquier nueva asignación, entonces la persona que llama verá el cambio de datos en su versión también.

Del mismo modo, siempre que la referencia original esté intacta para la variable pasada, las variables de instancia serán las mismas que ve la persona que llama. Dentro del marco de un objeto, las variables de instancia siempre tienen los valores de referencia más actualizados, ya sean proporcionados por el llamador o establecidos en la función a la que se pasó la clase.

La 'llamada por valor' o 'llamada por referencia' se confunde aquí debido a la confusión sobre '=' En idiomas compilados '=' es una copia de datos. Aquí en este lenguaje interpretado '=' hay una copia de referencia. En el ejemplo, se pasa la referencia seguida de una copia de referencia aunque '=' que identifica el original pasado como referencia, y luego las personas que hablan de ello como si '=' fuera una copia de datos.

Para ser coherente con las definiciones, debemos mantener '.replace', ya que es una copia de datos. Desde la perspectiva de '.replace' vemos que esto es realmente pasar por referencia. Además, si pasamos por el depurador, vemos que se pasan referencias, ya que las variables son referencias.

Sin embargo, si debemos mantener '=' como marco de referencia, entonces sí podemos ver los datos pasados ​​hasta una asignación, y luego no podemos verlos más después de la asignación mientras los datos de la persona que llama permanecen sin cambios. A nivel de comportamiento, esto es pasar por valor siempre que no consideremos que el valor pasado sea compuesto, ya que no podremos mantener parte de él mientras cambiamos la otra parte en una sola asignación (como esa asignación cambia la referencia y el original queda fuera de alcance). También habrá una verruga, en ese caso, las variables en los objetos serán referencias, como lo son todas las variables. Por lo tanto, nos veremos obligados a hablar sobre pasar 'referencias por valor' y a usar locuciones relacionadas.


1

Cabe señalar que ni siquiera tiene que usar el método "reemplazar" para cambiar el valor del valor original. Si asigna uno de los valores hash para un hash, está cambiando el valor original.

def my_foo(a_hash)
  a_hash["test"]="reference"
end;

hash = {"test"=>"value"}
my_foo(hash)
puts "Ruby is pass-by-#{hash["test"]}"

Otra cosa que encontré. Si está pasando un tipo numérico, todos los tipos numéricos son inmutables y, por lo tanto, SON pasados ​​por valor. La función de reemplazo que funcionó con la cadena anterior, NO funciona para ninguno de los tipos numéricos.
Don Carr

1
Two references refer to same object as long as there is no reassignment. 

Cualquier actualización en el mismo objeto no hará referencias a la nueva memoria ya que todavía está en la misma memoria. Aquí hay algunos ejemplos:

    a = "first string"
    b = a



    b.upcase! 
    => FIRST STRING
    a
    => FIRST STRING

    b = "second string"


a
    => FIRST STRING
    hash = {first_sub_hash: {first_key: "first_value"}}
first_sub_hash = hash[:first_sub_hash]
first_sub_hash[:second_key] = "second_value"

    hash
    => {first_sub_hash: {first_key: "first_value", second_key: "second_value"}}

    def change(first_sub_hash)
    first_sub_hash[:third_key] = "third_value"
    end

    change(first_sub_hash)

    hash
    =>  {first_sub_hash: {first_key: "first_value", second_key: "second_value", third_key: "third_value"}}

0

Sí, pero ....

Ruby pasa una referencia a un objeto y dado que todo en ruby ​​es un objeto, se podría decir que se pasa por referencia.

No estoy de acuerdo con las publicaciones aquí que afirman que es pasar por valor, eso me parece juegos pedantes y simétricos.

Sin embargo, en efecto, "oculta" el comportamiento porque la mayoría de las operaciones que Ruby proporciona "fuera de la caja", por ejemplo, las operaciones de cadena, producen una copia del objeto:

> astringobject = "lowercase"

> bstringobject = astringobject.upcase
> # bstringobject is a new object created by String.upcase

> puts astringobject
lowercase

> puts bstringobject
LOWERCASE

Esto significa que la mayor parte del tiempo, el objeto original se deja sin cambios dando la apariencia de que el rubí es "pasar por valor".

Por supuesto, al diseñar sus propias clases, comprender los detalles de este comportamiento es importante tanto para el comportamiento funcional como para la eficiencia de la memoria y el rendimiento.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.