ruby - paso - tipos de amarres de sogas
¿Por qué el operador de pala(<<) se prefiere sobre el de más y más(+=) al construir una cuerda en Ruby? (6)
Esta es una vieja pregunta, pero la encontré y no estoy completamente satisfecho con las respuestas existentes. Hay muchos puntos buenos sobre la pala << siendo más rápido que la concatenación + =, pero también hay una consideración semántica.
La respuesta aceptada de @noodl muestra que << modifica el objeto existente en su lugar, mientras que + = crea un nuevo objeto. Por lo tanto, debe considerar si desea que todas las referencias a la cadena reflejen el nuevo valor, o si desea dejar las referencias existentes solo y crear un nuevo valor de cadena para usar localmente. Si necesita todas las referencias para reflejar el valor actualizado, entonces necesita usar <<. Si quiere dejar otras referencias solo, entonces necesita usar + =.
Un caso muy común es que solo hay una referencia única a la cadena. En este caso, la diferencia semántica no importa y es natural preferir << por su velocidad.
Estoy trabajando con 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 (<<) sobre el operador de igual a igual (+ =) al construir cuerdas. ¿Por qué?
Supongo 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.
¿Alguien podría explicar los detalles de esta preferencia?
Porque es más rápido / no crea una copia de la cadena <-> el recolector de basura no necesita ejecutarse.
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)
Prueba:
a = ''foo''
a.object_id #=> 2154889340
a << ''bar''
a.object_id #=> 2154889340
a += ''quux''
a.object_id #=> 2154742560
Entonces <<
altera la cadena original en lugar de crear una nueva. La razón de esto es que en ruby a += b
es una taquigrafía sintáctica para a = a + b
(lo mismo vale para los otros <op>=
operadores) que es una asignación. Por otro lado, <<
es un alias de concat()
que altera el receptor in situ.
Si bien no es una respuesta directa a su pregunta, ¿por qué The Bin Upturned siempre ha sido uno de mis artículos favoritos de Ruby? También contiene algo de información sobre cadenas en lo que respecta a la recolección de basura.
Un amigo que está aprendiendo Ruby como su primer lenguaje de programación me hizo esta misma pregunta al pasar por Strings in Ruby en la serie Ruby Koans. Le expliqué usando la siguiente analogía;
Tienes un vaso de agua medio lleno y necesitas volver a llenar tu vaso.
Primero, hazlo tomando un vaso nuevo, llenándolo hasta la mitad con agua de un grifo y luego usando este segundo vaso medio lleno para volver a llenar tu vaso. Haz esto cada vez que necesites rellenar tu vaso.
La segunda forma de tomar su vaso medio lleno y simplemente rellenarlo con agua directamente desde el grifo.
Al final del día, tendrá que limpiar más vasos si elige recoger un vaso nuevo cada vez que necesita volver a llenar el vaso.
Lo mismo aplica para el operador de pala y el operador más igual. Además, el operador igual toma un nuevo "vaso" cada vez que necesita rellenar su vaso, mientras que el operador de la pala toma el mismo vaso y lo vuelve a llenar. Al final del día, más colección de ''vidrio'' para el operador Plus igual.