¿Por qué se prefiere el operador shovel (<<) sobre plus-equals (+=) cuando se construye una cadena en Ruby?


Estoy trabajando a través de Ruby Koans.

El test_the_shovel_operator_modifies_the_original_string Koan en about_strings.rb incluye el siguiente comentario:

Los programadores de Ruby tienden a favorecer al operador de pala (

Mi conjetura es que implica velocidad, pero no entiendo la acción debajo del capó que haría que el operador de la pala sea más rápido.

¿Podría alguien explicar los detalles detrás esta preferencia?

Author: iCodez, 2011-01-13

6 answers

Prueba:

a = 'foo'
a.object_id #=> 2154889340
a << 'bar'
a.object_id #=> 2154889340
a += 'quux'
a.object_id #=> 2154742560

Así que << altera la cadena original en lugar de crear una nueva. La razón de esto es que en ruby a += b es una abreviatura sintáctica para a = a + b (lo mismo ocurre con los otros operadores <op>=) que es una asignación. Por otro lado << es un alias de concat() que altera el receptor en el lugar.

 236
Author: noodl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-13 22:54:34

Prueba de rendimiento:

#!/usr/bin/env ruby

require 'benchmark'

Benchmark.bmbm do |x|
  x.report('+= :') do
    s = ""
    10000.times { s += "something " }
  end
  x.report('<< :') do
    s = ""
    10000.times { s << "something " }
  end
end

# Rehearsal ----------------------------------------
# += :   0.450000   0.010000   0.460000 (  0.465936)
# << :   0.010000   0.000000   0.010000 (  0.009451)
# ------------------------------- total: 0.470000sec
# 
#            user     system      total        real
# += :   0.270000   0.010000   0.280000 (  0.277945)
# << :   0.000000   0.000000   0.000000 (  0.003043)
 78
Author: Nemo157,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-13 21:05:56

Un amigo que está aprendiendo Ruby como su primer lenguaje de programación me hizo esta misma pregunta mientras revisaba Cadenas en Ruby en la serie Ruby Koans. Se lo expliqué usando la siguiente analogía;

Tienes un vaso de agua medio lleno y necesitas rellenar el vaso.

La primera forma de hacerlo es tomar un vaso nuevo, llenarlo hasta la mitad con agua de un grifo y luego usar este segundo vaso medio lleno para rellenar el vaso. Haces esto cada vez que necesito rellenar el vaso.

La segunda forma es tomar el vaso medio lleno y rellenarlo con agua directamente del grifo.

Al final del día, tendrá más vasos para limpiar si elige elegir un vaso nuevo cada vez que necesite rellenarlo.

Lo mismo se aplica al operador de la pala y al operador más igual. Además, el operador igual elige un nuevo "vidrio" cada vez que necesita rellenar su vidrio, mientras que el operador de la pala solo toma el mismo vidrio y lo rellena. Al final del día, más colección de "vidrio" para el operador Más igual.

 64
Author: Kibet Yegon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-24 09:47:12

Esta es una vieja pregunta, pero acabo de cruzarla y no estoy completamente satisfecho con las respuestas existentes. Hay muchos puntos buenos sobre la pala

La respuesta aceptada de @noodl muestra que

Un caso muy común es que solo hay una referencia a la cadena. En este caso, la diferencia semántica no importa y es natural preferir

 9
Author: Tony,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-21 23:45:58

Debido a que es más rápido / no crea una copia de la cadena garbage collector no necesita ejecutarse.

 8
Author: grosser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-14 09:19:59

Aunque no es una respuesta directa a tu pregunta, ¿por qué La Papelera totalmente Invertida siempre ha sido uno de mis artículos favoritos de Ruby? También contiene información sobre cadenas en lo que respecta a la recolección de basura.

 2
Author: Michael Kohl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-13 23:08:03