¿Cuál es la función del símbolo en ruby? ¿Cuál es la diferencia entre cadena y símbolo? ¿Por qué no es una buena idea crear dinámicamente muchos símbolos?¿Por qué no es una buena idea crear dinámicamente muchos símbolos en ruby?
Respuesta
Los símbolos son como cadenas pero son inmutables, no se pueden modificar.
Se ponen solo en la memoria una vez, lo que los hace muy eficientes para usar cosas como las claves en hash, pero se quedan en la memoria hasta que el programa finaliza. Esto los convierte en un cerdo de memoria si los malgastas.
Si crea dinámicamente muchos símbolos, está asignando una gran cantidad de memoria que no se puede liberar hasta que finalice su programa. Sólo debe crear dinámicamente símbolos (utilizando string.to_sym
) si sabe que va a:
- necesidad de acceder repetidamente el símbolo
- no necesita modificarlos
Como he dicho antes, son útiles para cosas como hash, donde más le importa la identidad de la variable que su valor. Los símbolos, cuando se usan correctamente, son una forma legible y eficiente de pasar la identidad.
Explicaré lo que quiero decir sobre la inmutabilidad de los símbolos RE su comentario.
Las cadenas son como arreglos; se pueden modificar en su lugar:
12:17:44 ~$ irb
irb(main):001:0> string = "Hello World!"
=> "Hello World!"
irb(main):002:0> string[5] = 'z'
=> "z"
irb(main):003:0> string
=> "HellozWorld!"
irb(main):004:0>
Los símbolos son más como números; que no se pueden editar en su lugar:
irb(main):011:0> symbol = :Hello_World
=> :Hello_World
irb(main):012:0> symbol[5] = 'z'
NoMethodError: undefined method `[]=' for :Hello_World:Symbol
from (irb):12
from :0
Un símbolo es el mismo objeto y la misma asignación de memoria, no importa donde se utiliza:
>> :hello.object_id
=> 331068
>> a = :hello
=> :hello
>> a.object_id
=> 331068
>> b = :hello
=> :hello
>> b.object_id
=> 331068
>> a = "hello"
=> "hello"
>> a.object_id
=> 2149256980
>> b = "hello"
=> "hello"
>> b.object_id
=> 2149235120
>> b = "hell" + "o"
Dos cadenas que son 'lo mismo' en el sentido de que contienen los mismos caracteres, puede que no hagan referencia a la misma memoria, lo que puede ser ineficiente si usa cadenas para, por ejemplo, hashes.
Por lo tanto, los símbolos pueden ser útiles para reducir la sobrecarga de memoria. Sin embargo, son una pérdida de memoria que está por ocurrir, ya que los símbolos no se pueden recolectar como basura una vez creados. Crear miles y miles de símbolos asignaría la memoria y no sería recuperable. ¡Ay!
Entonces, ¿cómo usar la recolección de basura manualmente? – Ikbear
No puede recoger símbolos de basura por lo que yo sé. Puede iniciar la recolección de basura en cualquier momento con 'GC.start'. Aquí hay un buen artículo sobre el tema: http://viewsourcecode.org/why/hacking/theFullyUpturnedBin.html – stef
bien, ¡gracias por su ayuda! – Ikbear
Puede ser particularmente malo crear símbolos a partir de la entrada del usuario sin validar la entrada con algún tipo de lista blanca (por ejemplo, para los parámetros de cadena de consulta en RoR). Si la entrada del usuario se convierte en símbolos sin validación, un usuario malintencionado puede hacer que el programa consuma grandes cantidades de memoria que nunca serán basura.
Bad (se crea un símbolo independientemente de la entrada del usuario):
name = params[:name].to_sym
Buena (un símbolo sólo se crea si se permite la entrada de usuario):
whitelist = ['allowed_value', 'another_allowed_value']
raise ArgumentError unless whitelist.include?(params[:name])
name = params[:name].to_sym
Si está utilizando Rubí 2.2.0 o posterior, generalmente debería estar bien crear dinámicamente una gran cantidad de símbolos, ya que serán basura recolectada según el Ruby 2.2.0-preview1 announcement, que tiene un enlace al more details about the new symbol GC. Sin embargo, si pasa sus símbolos dinámicos a algún tipo de código que lo convierta en una ID (un concepto interno de implementación de Ruby utilizado en el código fuente C), en ese caso se fijará y nunca se recolectará la basura. No estoy seguro de qué tan comúnmente eso sucede.
Puede pensar en símbolos como el nombre de algo y cadenas (más o menos) como una secuencia de caracteres. En muchos casos podría usar un símbolo o una cadena, o podría usar una mezcla de los dos. Los símbolos son inmutables, lo que significa que no se pueden cambiar después de haber sido creados. La forma en que se implementan los símbolos es muy eficiente para comparar dos símbolos para ver si son iguales, por lo que usarlos como claves para los hashes debería ser un poco más rápido que usar cadenas. Los símbolos no tienen mucho que ver con los métodos que hacen las cadenas, como , por lo que tendría que usar to_s
para convertir el símbolo en una cadena antes de llamar a esos métodos.
se puede leer más acerca de los símbolos aquí en la documentación:
Starting Ruby 2.2 y por encima de Symbols son automáticamente recolector de basura y lo que esto no debería ser un problema.
- 1. Django: ¿Es una buena idea generar JS dinámicamente?
- 2. Lanzar/no-lanzar una excepción basada en un parámetro: ¿por qué no es una buena idea?
- 3. ¿Cuándo no es una buena idea pasar por referencia?
- 4. ¿Por qué Ruby expone símbolos?
- 5. ¿Por qué es MD5'ing un UUID no es una buena idea?
- 6. ¿Es una buena idea usar una función CreateUUID() como sal?
- 7. ¿Es una buena idea cambiar dinámicamente los nombres de los subprocesos de procesamiento en Java?
- 8. sqlite e hibernate - es una buena idea?
- 9. ¿Es una buena idea usar símbolos Unicode como identificadores de Java?
- 10. ¿Es correcto (VERDADERO) una buena idea en C?
- 11. Implementar una clase "LazyProperty": ¿es esta una buena idea?
- 12. ¿Campos multivalorados una buena idea?
- 13. ¿Es una buena idea hornear procesos en PHP/Apache?
- 14. ¿Por qué no es una buena idea usar SOAP para comunicarse con la interfaz (es decir, el navegador web)?
- 15. ¿Es una buena idea poner db/schema.rb en .gitignore list ??
- 16. internacionalización con nibs. ¿Es realmente una buena idea?
- 17. ¿Es una buena idea una clase de "preferencias maestras"?
- 18. ¿Por qué es una mala idea permitir esto en JavaScript ==,! =, ++, -
- 19. ¿Los símbolos de Ruby no son basura? Entonces, ¿no es mejor usar una Cadena?
- 20. ¿Es una buena idea ejecutar `... par.map (` en listas grandes directamente?
- 21. Es una buena idea guardar gráficos en MySQL?
- 22. ¿Es una buena idea usar ruby para la programación de socket?
- 23. ¿Por qué continuar en un ciclo es una mala idea?
- 24. Por qué usar XML para crear GUI es una buena práctica en Android
- 25. ¿Por qué no hay más proyectos que utilicen símbolos de Ruby en lugar de cadenas?
- 26. ¿Es una buena idea devolver "const char *" de una función?
- 27. activerecord como modelo, ¿es esta una buena idea?
- 28. REST Servicios web usando MVC, ¿es una buena idea?
- 29. ¿En qué situaciones es una buena idea preferir GDI en lugar de DirectX/OpenGL
- 30. ¿Cuándo es una buena idea la herencia virtual?
¿Estaba trabajando a través de los [EdgeCase Ruby koans] (http://rubykoans.com/) también? –