Saltar al contenido

Undo/Redo y Casos Avanzados

En esta página

Viaje en el tiempo: :undo / :redo / :history

Cada swap exitoso guarda un checkpoint en un ring buffer por módulo (predeterminado: 10 entradas). En el prompt de zolo dev puedes navegar ese historial sin reescribir el código manualmente.

Comandos disponibles en el prompt:

Comando Efecto
:undo Revierte el swap más reciente
:redo Reaplicó el último :undo
:history Lista checkpoints y contadores
:reload <modulo> Fuerza el swap de un módulo
:eval <expr> Compila y ejecuta una expresión en la VM viva
:stats Latencias p50/p95 y conteo de swaps

El estado vivo se preserva en ambas direcciones: un pub let count = 5 sigue siendo 5 tras :undo, aunque la versión antigua tuviera el literal 0. La pila de redo se limpia cuando ocurre un swap "fresco" después de un :undo.

Edita la fórmula varias veces; usa :undo/:redo para navegar entre las versiones.

formula.zolo
Playground
// Feature: a perfect target to experiment with :undo / :redo

// Syntax: edit the formula multiple times; navigate the history.

// When to use: compare variants of a function without rewriting

// each one by hand. The `ReloadHistory` keeps the source of

// previous versions and re-applies them via swap.


pub fn calc(x: int) -> int {
  // Edit this formula several times during the `dev` session.

  // Each save adds a checkpoint; :undo rolls back one step.

  return x * 2
}

Requiere la CLI o el host de Zolo; ábrelo en el playground o ejecútalo localmente.

main.zolo
Playground
// Feature: time-travel of hot-reloads — :undo / :redo / :history

// Syntax: commands at the `zolo dev` prompt (not Zolo words).

// When to use: experiment with variants of a function and roll

// back to a previous one quickly without editing by hand.


use formula::{calc}

fn main() {
  print("ENTER prints calc(10). Use :undo / :redo / :history at the prompt.")
  while true {
    let line = io::read("*l")
    if line is nil || line == "q" {
      break
    }
    print("calc(10) = {calc(10)}")
  }
}

Requiere la CLI o el host de Zolo; ábrelo en el playground o ejecútalo localmente.

Reload en bucle cerrado sin yield

El código que nunca cede el control (sin io::read, sin sleep) sigue recibiendo swaps: el hook de instrucción de la VM drena los reloads pendientes cada ~2000 instrucciones. El módulo worker.zolo puede editarse mientras el contador gira — la próxima llamada a tick ya usa la versión nueva.

Edita el mensaje en tick() mientras el bucle corre — ninguna acción manual necesaria.

worker.zolo
Playground
// Edit this while the demo is running. Save with Ctrl+S — the next

// `tick` call uses the new code with no manual intervention.


pub fn tick(i) {
  print("tick {i}: still on V1 — edit me!")
}

Requiere la CLI o el host de Zolo; ábrelo en el playground o ejecútalo localmente.

main.zolo
Playground
// Demo 02 — Hot-reload during a TIGHT CPU LOOP.

//

//   zolo dev examples/zolo_live/02_tight_loop/main.zolo

//

// This script has NO `io::read` or any other yield point. It just busies

// itself spinning a counter. Yet edits to `worker.zolo` take effect

// within milliseconds — the VM instruction hook drains pending swaps

// every ~2000 instructions, transparently to the user.

//

// While running, edit `worker.zolo` (e.g. change the message format)

// and watch the output update LIVE without any user action.


use worker::{tick}

fn main() {
  let i = 0
  let last_print = 0
  while true {
    i = i + 1
    if i - last_print > 5_000_000 {
      tick(i)
      last_print = i
    }
  }
}

Requiere la CLI o el host de Zolo; ábrelo en el playground o ejecútalo localmente.

Closures capturadas fuera del live-binding

Cuando una referencia de función se copia directamente en una lista o estructura de datos (sin pasar por el thunk), el runtime igualmente actualiza esa referencia. Al hacer el swap, el recolector recorre el heap y reemplaza cada puntero a la función antigua por la nueva. El demo 09-closure-escape muestra esto con un fn_queue que acumula referencias a greeter.greet antes de cualquier edición:

Las referencias capturadas directamente también se actualizan en el swap.

greeter.zolo
Playground
// Edit me — the queued function references in main.zolo update too,

// thanks to closure-correct hot-reload.


pub fn greet(who) {
  print("V1: hi {who}")
}

Requiere la CLI o el host de Zolo; ábrelo en el playground o ejecútalo localmente.

main.zolo
Playground
// Demo 04 — Closure-correct hot-reload.

//

//   zolo dev examples/zolo_live/04_closure_escape/main.zolo

//

// The script captures a function reference into a queue (`fn_queue`),

// then iterates and calls them. Even though the function value escapes

// the live-binding thunk, edits to greeter.zolo still take effect on

// next call: the closure registry walks the heap and patches every

// reference to the old function value with the new one.

//

// This is the deeper guarantee — works no matter how the function got

// captured.


mod greeter

fn main() {
  let fn_queue = []
  // Capture the function value DIRECTLY (no live-binding thunk):

  fn_queue.push(greeter.greet)
  fn_queue.push(greeter.greet)
  fn_queue.push(greeter.greet)

  print("Press ENTER to flush the queue — or 'q' to quit.")
  print("Edit greeter.zolo while waiting; queued fn refs update too.")
  while true {
    let line = io::read("*l")
    if line is nil || line == "q" {
      break
    }
    for f in fn_queue {
      f("queued")
    }
  }
}

Requiere la CLI o el host de Zolo; ábrelo en el playground o ejecútalo localmente.

Buscar en Zolo

9 resultados

enespt-br