Este curso explora otra característica avanzada.
Quiero mostrarte cómo podemos transformar
la pila de ejecución en un objeto, bajo demanda.
El objetivo es darte herramientas intuitivas. sin entrar en detalles.
Podemos manipular y navega por la pila,
y modificarla, pero nos centraremos en navegar.
Hay dos capítulos que puedes leer sobre este tema.
Son los capítulos en bloques
y excepciones en el libro Deep into Pharo .
Vale la pena leerlos ya que dan explicaciones claras.
En Pharo, la clase Context también representa la pila.
Asi que,
usaremos un escenario eso ya está en tu depurador.
Aquí, no se encuentra un mensaje que envió. porque no lo definiste,
mientras ejecutas una prueba unitaria.
En el depurador, respondes que deseas crear un método.
Lo compila y lo instala en la clase.
Luego lo vuelve a ejecutar.
Este método genera una excepción. ¡ya que el sistema no es mágico!
Te envía el mensaje shouldBeImplemented
diciéndote que edites el método en el depurador.
Implementas el método,
lo recompilas sobre la marcha, y luego seleccionas "continuar"
para reanudar el programa.
Hay dos puntos clave en este escenario.
En primer lugar, recompilamos el método sobre la marcha.
Varias veces, pero ese es el trabajo del compilador.
En segundo lugar, y lo más importante, modificamos la pila de ejecución
para inyectar nuevos trozos de pila,
que nos permiten continuar el programa después de un error
No es solo una cuestión de reificación de la pila o convertirla en un objeto.
No es solo un ejercicio formal, puede mejorar la experiencia del usuario
y crear nuevas herramientas.
También se usa en Seaside para aplicaciones web.
Pharo generalmente tiene una pila C, la propia pila de la máquina virtual.
Bajo demanda, podemos convertir esto en un objeto vivo.
Lo que es interesante es que podemos navegar y modificar este objeto.
Por modificar, quiero decir que cuando cambiamos este objeto Pharo,
cambiará la pila C implícita, por lo que es muy poderoso.
También es compatible con todas las excepciones, así que recomiendo leer esos capítulos.
Navegamos la pila por excepciones
para buscar bloques de capturas,
conocidos como manipuladores de excepciones.
Además, esta habilidad transformar la pila en un objeto
nos permite crear continuaciones
y servidores web, como para los lenguajes funcionales como Scheme.
Para explicar cómo funciona esto, podemos ver la variable
llamado thisContext, una de las tres pseudovariables de Pharo.
Estas son self, super y thisContext.
Cuando pides el valor de thisContext, devuelve la pila de ejecución.
Eso es lo que ves cuando abres el depurador.
Se muestra la pila de ejecución, basado en thisContext.
Como ejercicio, puedes definir un método
en el que insertes "halt".
El depurador aparecerá, pero también puedes escribir "thisContext"
y un inspector se abrirá en la pila de ejecución en sí.
Ahora les mostraré dos ejemplos
de cómo usamos thisContext.
El primero es la deprecación, se usa cuando queremos cambiar la API.
Como programador, editamos el método y use el mensaje "deprecated:on:in:"
como expliqué en el curso de las excepciones.
Aquí queremos expresar el mensaje "Usar bar".
¿Y qué mostrará la deprecación?
Se mostrará al usuario el mensaje
"Mensaje foo está en desuso en Pharo".
Es importante tener en cuenta que, como usuario,
no declaré el método utilizado,
pero el sistema identificó a foo como el método que llama.
Como puede ver, no usamos foo en los argumentos de deprecación
o en el método de llamada.
Entonces, ¿cómo se implementa esto?
El mensaje "deprecated"
es una excepción, "Deprecation".
El sistema toma los argumentos, anExplanationString, y así sucesivamente,
y agrega la expresión "thisContext sender method".
ThisContext es la pila en el momento de ejecución del método en desuso.
Ahora, usando el emisor podemos acceder al método que llama.
Eso nos dará foo, que fue nuestro ejemplo.
Luego le pedimos el método.
"thisContext sender method" devuelve el método compilado,
que es un objeto,
llamado A>>#foo.
Entonces, la excepción usa lo que necesita. para poder extraer
el selector y crear un mensaje más claro.
Se usa para hacer mensajes más fácil para que los usuarios entiendan,
sin forzar al programador a fijar el emisor del mensaje.
Ahora te voy a mostrar otra función muy poderosa.
Frecuentemente cuando se depura, queremos insertar un punto de interrupción
en un método que es muy usado.
Es posible que simplemente desee depurar tu versión del programa
sin detener todo el sistema.
Condiciones como "detener una vez" interrumpirá el sistema una vez,
pero lo que quieres es detener la ejecución solo si el método
ha sido llamado por otro método.
¿Cómo lo expresa un programador?
Expresamos que solo queremos detener si foo ha sido llamado
por el método testSetInitialized.
¿Cómo implementamos esto?
Por lo general, este método no debe detenerse.
Puedes abrir el código en Pharo para ver cómo se implementa.
Entonces, halt lanza una excepción.
mostrando el mensaje "Si:".
Tenemos varias opciones de argumento.
En un caso que involucra un símbolo, planteamos una consulta para confirmar que es verdad.
Miramos para ver si la cadena de llamadas contiene el simbolo.
Vamos a revisar.
Veamos el método que surge.
Supongamos que tenemos una prueba que se llama
testSetInitialized.
Es un parametro aquí.
Primero, el método recuperará la pila de ejecución, o contexto,
que es sinónimo de pila de ejecución.
Entonces usamos Context para acceder a la pila, luego agregamos whileFalse.
Tenga en cuenta que no estamos en la parte superior de la pila de ejecución,
donde no hay emisores invocándonos.
En la parte superior de la pila, el emisor es nil.
En un caso donde el emisor no es nil,
nos movemos entre secciones de la pila.
Podemos imaginar las áreas de pila como esta,
y viajamos hacia arriba usando el emisor,
cada vez.
Ahora tenemos que ver si el selector ...
En algún lugar de esta área, deberíamos ver la prueba
haciendo la pregunta
si el símbolo de la llamada de esta pila coincide con el que pretendemos para detenernos.
Le preguntamos si nos han llamado desde testSet.
Si es así, paramos y enviamos un "signal" porque la clase es una excepción.
Es importante entender que esto es difícil de implementar
en un lenguaje que no reifica la pila.
Aquí lo ves en cinco líneas, incluso si parece difícil de entender.
Es compacto y potente, y solo es posible a través de la reificación.
ThisContext raramente se usa ya que es una función avanzada.
Pero es muy importante para nuevas innovaciones,
tales como herramientas, como lo demuestran estas pruebas,
que son facilitadas en este lenguaje.
También se usa para representar continuaciones
El creador de Seaside lo usó en el antepasado de Pharo
manipular la pila para representar continuaciones.
Esta es la base del mecanismo de call-answer en Seaside.
Aquí tienes una función avanzada de Pharo para jugar.