Una expresión en Verse puede ser inmediata o asíncrona. Describe el tiempo que puede tardar una expresión en evaluar respecto a las actualizaciones de las simulaciones.
Piensa en una actualización de la simulación como el momento en que se muestra un nuevo fotograma.
Hay casos en los que pueden producirse múltiples actualizaciones de la simulación antes de un nuevo fotograma, por ejemplo, si una partida en línea se desincroniza con el servidor.
| expresión inmediata | expresión asíncrona |
|---|---|
Una expresión inmediata se evalúa sin retraso, lo que significa que la evaluación se completará dentro de la actualización de la simulación actual. | Una expresión asíncrona puede tardar en evaluarse, pero no tiene por qué hacerlo. Asimismo, esta puede o no completarse en la actualización de la simulación actual, o en una posterior. |
Contextos asíncronos
Las expresiones asíncronas pueden utilizarse en cualquier código de Verse que tenga un contexto asíncrono.
Un contexto asíncrono es el cuerpo de una función que tiene el especificador de efecto suspends. El efecto suspends indica que las funciones asíncronas pueden suspender y transferir cooperativamente el control a otras expresiones simultáneas en varios puntos a lo largo de varias actualizaciones de la simulación antes de que se completen.
La función OnBegin() en un dispositivo de Verse es una función asíncrona común utilizada como punto de partida para el código asíncrono.
Llamar a una función asíncrona tiene la misma sintaxis que llamar a una función inmediata:
OnBegin<override>()<suspends> : void =
HideAllPlatforms()
HideAllPlatforms()<suspends> : void =
for (Platform : Platforms):
Platform.Hide()
Sleep(Delay)Como cualquier otra expresión, una expresión asíncrona puede tener un resultado. El resultado de una expresión asíncrona solo está disponible una vez que se ha completado.
# Npc is undefined until it is bound after MoveToNearestNPC() completes which may be several frames into the future
Npc := Player.MoveToNearestNPC()
#Only called after MoveToNearestNPC() completes
Print("Moved to {Npc}")Cualquier bloque de código que esté dentro de un contexto asíncrono (dentro del cuerpo de una función asíncrona) puede tener cualquier mezcla de expresiones inmediatas y asíncronas.
Si alguna expresión de un bloque de código es asíncrona, se considera que todo el bloque de código es asíncrono.
Si todas las expresiones de un bloque de código son inmediatas, se considera que todo el bloque de código es inmediato.
Todas las expresiones del ejemplo siguiente son expresiones asíncronas, por lo que el bloque de código general es asíncrono:
Sleep(2.0) # waits 2 seconds
Boss.TauntEmote() # waits until TauntEmote() completes
Player.MoveToNearestNPC() # waits until MoveToNearestNPC() completesTodas las expresiones del ejemplo siguiente son expresiones inmediatas, por lo que todo el bloque de código es inmediato:
Print("Reset after explosion")
Platform.Show()
set SecondsUntilExplosion = 12.0Las expresiones del ejemplo siguiente son una mezcla de expresiones asíncronas e inmediatas, por lo que el bloque de código general es asíncrono:
Print("Started")
var Seconds := 1.0
Sleep(Seconds)
Print("Waited {Second} seconds")
set Second += 1.0
Sleep(Seconds)
Print("Waited {Second} seconds")
set Second += 1.0
Las expresiones inmediatas se pegan solas. Todas las expresiones inmediatas adyacentes (no asíncronas) se consideran atómicas: se garantiza que su código se ejecuta sin interrupción dentro de la misma actualización y sin tanteos ni cambios de contexto. Es como si dicho código tuviera una forma primitiva de exclusión mutua automática que lo envuelve.
Así que desde el ejemplo de código anterior, estas expresiones inmediatas se tratan atómicamente:
# These two expressions are always kept together
Print("Started")
var Seconds := 1.0
Sleep(Seconds)
# These two expressions are always kept together
Print("Waited {Second} seconds")
set Second += 1.0
Como cualquier otro bloque de código, la última expresión de un bloque de código asíncrono se utiliza como resultado.
Expresiones de simultaneidad
Verse utiliza expresiones de simultaneidad para determinar si las expresiones se ejecutan simultáneamente (al mismo tiempo), o en secuencia, una tras otra. Una expresión asíncrona se ejecuta o invoca a lo largo del tiempo, por lo que estas expresiones de simultaneidad pueden ser especialmente útiles cuando utilizas expresiones asíncronas.
Simultaneidad estructurada
Una expresión asíncrona bloqueará la ejecución de otras expresiones si tarda mucho en ejecutarse. Por ejemplo, utilizar Sleep(90.0) hará que el programa espere 90 segundos, bloqueando la siguiente expresión hasta que Sleep(90.0) se ejecute por completo.
Las expresiones de simultaneidad estructurada se utilizan para especificar el flujo de tiempo asíncrono, y para modificar la naturaleza de bloqueo de las expresiones asíncronas con una duración que se limita a un ámbito de contexto asíncrono específico (como el cuerpo de una función asíncrona).
Es similar a los flujos de control estructurados como block, if, for y loop que se limitan a su ámbito asociado.
Las expresiones asíncronas de Verse no utilizan las formas primitivas yield y await utilizadas por las implementaciones de corrutinas en otros lenguajes. Se logran los mismos mecanismos utilizando las expresiones de simultaneidad de Verse y los mecanismos internos.
Para más información sobre la simultaneidad estructurada, consulta Sync, Race, Rush y Branch.
Simultaneidad no estructurada
Solo hay una expresión de simultaneidad no estructurada: spawn. Esta expresión tiene una duración que no está lógicamente limitada a un ámbito de contexto asíncrono específico, sino que potencialmente puede extenderse más allá del ámbito en el que se ejecutó.
La simultaneidad no estructurada es como una escotilla de emergencia: no debes utilizarla de forma habitual, aunque a veces será tu mejor y única opción.
Las expresiones de simultaneidad estructurada (sync, race, rush y branch) deben usarse antes que las expresiones simultaneidad no estructurada (spawn) siempre que sea posible.
Para más información sobre la simultaneidad no estructurada, consulta Spawn.
Tareas de seguimiento de expresiones asíncronas en ejecución
Una expresión asíncrona tiene asociada una tarea.
Una tarea es un objeto que representa una función asíncrona que ha empezado a ejecutarse, pero se ha suspendido para permitir que otra tarea se complete.
La tarea puede utilizarse para comprobar el estado de una expresión asíncrona y para cancelar la expresión asíncrona, si se desea.
Para más información sobre las tareas, consulta Tareas.