tutorial rails que entre ejemplos diferencia curso caracteristicas ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-4 rack

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.

Por ejemplo en rack :

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

Otro ejemplo en rieles :

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 .


Una explicación de por qué ve esta constante congelación de constantes en proyectos populares es que usan Rubocop , un analizador de código.

Es una rule estándar de Rubocop que las constantes no deben ser mutables, por las razones mencionadas anteriormente por @spickermann.