Una visión general del contexto de ejecución de los bloques
En este artículo, vamos a explorar los siguientes temas:
- ámbitos y bloques
- guarda de ámbito plano en clase/módulo
Primero, siéntete libre de explorar el artículo Puertas de Ámbito en Ruby: Part II article.
Antes de empezar
Estoy encantado de compartir con vosotros nuestro último proyecto: Datos curiosos sobre Ruby – Volumen 1
¡Por favor, no dudes en difundirlo y compartir este enlace! 🙏
¡Gracias por tu tiempo!
En Ruby, un bloque puede acceder al ámbito externo
En este ejemplo, podemos acceder a la variable outer_scope_variable
dentro de nuestro bloque. Nuestro bloque tiene acceso a esta variable aunque la variable esté declarada en un ámbito de nivel main
. En este caso, decimos que el bloque aplana los ámbitos. Por eso llamamos comúnmente a este mecanismo Flat Scope.
Por otro lado, el bloque crea un ámbito aislado -aunque el valor de self
dentro del bloque sigue siendo el objeto main
.
Así que no podemos acceder a las variables locales definidas dentro del bloque
Aquí, no podemos acceder a la block_variable
desde el ámbito exterior. Ahora que estamos más familiarizados con la noción de ámbito plano en Ruby veamos si esta noción impacta en la definición de clases.
Clase, módulo y bloque
En Ruby, lo que comúnmente se llama clase es, detrás de la escena, una instancia de la clase Class
Aquí, creamos las clases Hello
y Greeting
de dos maneras diferentes:
- usando la palabra clave
class
- asignando una instancia de la clase
Class
a la constanteGreeting
Nota que estamos pasando un bloque al método Class.new
. Este bloque será interpretado como el contenido de la clase. Normalmente una clase no puede acceder a las variables definidas en el ámbito exterior – ya que la palabra clave class
cambia el valor de self
y crea un ámbito aislado.
Así que, como utilizamos un bloque para crear nuestra clase Greeting
entonces deberíamos poder utilizar el mecanismo de ámbito plano. ¿De verdad?
Aquí podemos ver que el valor de self
cambia cuando se utiliza class
o Class.new
.
Además, nuestro bloque Class#message
sigue aislado del objeto main
debido al uso de la palabra clave def
. De hecho, como nuestro bloque se ejecuta en el contexto del método entonces el bloque aplana el alcance dentro de este objeto dado – y no con un alcance superior como el objeto main
.
Es por eso que no tenemos acceso a outer_variable
dentro de message
.
Pero si usamos define_method
para definir message
entonces el ámbito se aplana
Aquí, como define_method(:message)
toma un bloque como argumento, el ámbito de este bloque se aplana y este método tiene acceso a outer_variable
.
¡Voilà!