estableciendo un global dentro de un proc

He estado trabajando para tratar de entender mejor a Ruby y aquí hay algo con lo que tengo problemas:

$SAFE = 1 puts $SAFE # 1 proc { $SAFE = 2 puts $SAFE # 2 }.call puts $SAFE # 1 

El código anterior se toma parcialmente de la fuente de eRB reescrita para resaltar mejor el ejemplo. Básicamente, dentro del proceso, se puede establecer el valor de $SAFE en el valor que se desee y después del proceso, el valor de SAFE vuelve a ser el valor anterior al proceso.

Si en lugar de usar la palabra $SAFE , la cambio por una palabra diferente, como $DOOR :

 $DOOR = 1 puts $DOOR proc { $DOOR = 2 puts $DOOR }.call puts $DOOR 

entonces el valor de $DOOR después del proceso es 2 y no 1. ¿Por qué la diferencia entre los dos ejemplos?

En realidad, es bastante simple: la razón por la que $SAFE no se comporta como cabría esperar de una variable global es porque no es una variable global. Es una cosa mágica del unicornio amajiggy.

Hay bastantes de esos objetos mágicos de unicornio en Ruby, y desafortunadamente no están muy bien documentados (de hecho, no están documentados), ya que los desarrolladores de las implementaciones alternativas de Ruby descubrieron el camino difícil. Todos estos objetos se comportan de manera diferente y (aparentemente) inconsistente, y prácticamente las únicas dos cosas que tienen en común es que parecen variables globales pero no se comportan como ellas.

Algunos tienen scope local. Algunos tienen scope de subproceso local. Algunos cambian mágicamente sin que nadie se los asigne. Algunos tienen un significado mágico para el intérprete y cambian el comportamiento del idioma. Algunos tienen otras semánticas extrañas asociadas a ellos.

$SAFE tiene casi todo lo anterior: es un subproceso local, lo que significa que si lo cambia en un subproceso, no afecta a otros subprocesos. Es local, lo que significa que si lo cambia en un ámbito local (como una clase, un módulo, un método o un bloque), no afecta al ámbito externo (como ha descubierto). Tiene un significado mágico para el intérprete, ya que establecerlo en un valor diferente de 0 hace que ciertas cosas no funcionen. Y tiene una semántica extraña adicional, ya que solo puedes boost su valor, nunca disminuirlo .

No sé exactamente por qué $ SAFE funciona de esa manera, pero sí sé que es una variable global predefinida con un significado mágico relacionado con los datos y subprocesos externos contaminados.

Así que no lo uses como un objeto de progtwig.

Consulte http://ruby-doc.org/docs/ProgrammingRuby/html/taint.html

Se supone que, por cierto, no es posible reducir el valor de $ SAFE con una asignación, pero se adjunta al contexto de ejecución y un progtwig de multiproceso, por ejemplo, puede tener múltiples valores de $ SAFE en diferentes subprocesos …

El valor de $DOOR debe ser 2. porque la variable global $DOOR ha sido reinicializada de 1 a 2. Más detalles sobre las variables globales .

Niveles seguros de $SAFE estableciendo la variable $SAFE . De forma predeterminada, se establece en cero.

y $SAFE dentro del proceso estará allí en la memoria hasta el final del scope. Por lo tanto, está mostrando el valor establecido previamente, es decir, 1. consulte más aquí y también docs.