ruby-on-rails - que - ruby on rails tutorial
¿Por qué hay constantes congeladas en todas partes? (3)
Podemos encontrar fácilmente este estilo en muchos repositorios famosos, como bastidores, rieles, etc.
PATH_INFO = ''PATH_INFO''.freeze
REQUEST_METHOD = ''REQUEST_METHOD''.freeze
SCRIPT_NAME = ''SCRIPT_NAME''.freeze
QUERY_STRING = ''QUERY_STRING''.freeze
CACHE_CONTROL = ''Cache-Control''.freeze
CONTENT_LENGTH = ''Content-Length''.freeze
CONTENT_TYPE = ''Content-Type''.freeze
HTTP_IF_MODIFIED_SINCE = ''HTTP_IF_MODIFIED_SINCE''.freeze
HTTP_IF_NONE_MATCH = ''HTTP_IF_NONE_MATCH''.freeze
HTTP_IF_NONE_MATCH = ''HTTP_IF_NONE_MATCH''.freeze
Me pregunto por qué estas cadenas constantes están congeladas. Como todas son constantes, solo debe haber una instancia. Por supuesto, podemos poner "foo".freeze
algún lugar para hacer referencia a la misma instancia de singleton, sin embargo las personas usualmente escriben nombres de variables literales como HTTP_IF_MODIFIED_SINCE
.
En mi opinión, no hace ninguna diferencia a pesar de usar #freeze
, ¿por qué las personas congelan las constantes?
Es correcto que Ruby imprima una advertencia cuando reasigna un valor a una constante ya inicializada:
> FOO = ''foo''
> FOO = ''bar''
# :2: warning: already initialized constant FOO
# :1: warning: previous definition of FOO was here
> FOO
# => "bar"
Pero no hay protección contra el cambio del valor en la constante. Ejemplo sin freeze
:
> FOO = ''foo''
> FOO[1] = ''-''
> FOO
# => "f-o"
Pero la freeze
permite proteger el valor de las constantes para que no se cambien. Ejemplo con freeze
:
> FOO = ''foo''.freeze
> FOO[1] = ''-''
# => RuntimeError: can''t modify frozen String
Normalmente Rubyist congela los literales de cadena para hacer la ejecución más rápida. Si hay alguna llamada a la función, por ejemplo, como a continuación en algún controlador, cada solicitud llamará a esa función.
log("debug")
lo que sucede es que ruby define un nuevo objeto de cadena de basura cada vez. La asignación de objetos no es gratuita. consume memoria y CPU. La basura estará allí hasta que GC los recoja.
pero si los literales están congelados
log("debug".freeze)
Ruby asigna una vez y la almacena en caché para su uso posterior. Además, el objeto de cadena será inmutable y seguro para su uso en el entorno de multiproceso.
Desde Ruby 3.0, Ruby congelará todas las cuerdas, según Matz.
actualizar:
Si agrega el siguiente comentario al comienzo del archivo ruby, cada cadena literal en el archivo completo será inmutable. Esto es bastante útil cuando intenta optimizar su aplicación para el entorno de subprocesos múltiples.
# frozen_string_literal: true
o incluso puedes iniciar tu proceso Ruby con el interruptor --enable-frozen-string-literal
.