Pular para o conteúdo

Sinais e derivados

Preguiçoso, memorizado, e com as dependências descobertas executando a fórmula.

O derivado é preguiçoso e memorizado#

Ele só recalcula quando alguém lê e alguma dependência mudou. Recalcular na escrita faria uma cadeia de dez derivados rodar dez vezes por mudança — e a maioria deles nunca é lida.

dataforge
contas := {"n": 0}

action calcular():
    contas["n"] := contas["n"] + 1
    yield itens.ler()

steady quantos := R.derivado(calcular)

quantos.ler()
quantos.ler()
quantos.ler()
assert contas["n"] is 1      // tres leituras, uma conta so

As dependências são descobertas, não declaradas#

Não há lista para escrever: o derivado roda, e todo sinal lido durante a execução entra. Uma lista escrita à mão envelhece na primeira condição nova dentro da fórmula, e o sintoma é um valor que para de atualizar.

dataforge
action calcular_frete():
    given subtotal.ler() bigger 100.0:
        yield 0.0
    yield 20.0 - cupom.ler()

steady frete := R.derivado(calcular_frete)

Abaixo de 100 o frete leu o cupom, e mexer no cupom o invalida. Acima de 100 a fórmula toma o outro ramo e não lê mais: a partir daí, mexer no cupom não mexe em nada. As fontes que sumiram param de notificar — sem isso, uma fórmula com given acumularia as dependências dos dois ramos e recalcularia por mudanças que ela nem lê mais.

Escrever o mesmo valor não notifica#

Um sinal que avisa sobre x := x faz uma cadeia recalcular por nada e um efeito de rede disparar duas vezes. A comparação pode ser trocada: R.sinal(v, iguais := minha_comparacao).

Ler sem depender#

.valor() devolve o valor sem registrar a dependência — o untracked dos outros frameworks. Sem ele, um derivado que lê um contador de depuração passaria a recalcular a cada incremento dele.

Um ciclo é recusado, com o caminho#

text
// erro: o derivado 'a' depende de si mesmo.
//   nota: a cadeia: a → b → a
//   dica: quebre o ciclo: um dos dois precisa ser um sinal

Dizer apenas "há um ciclo" manda procurar em toda a fórmula; a cadeia é o que o torna quebrável.