Blocos Try Transacionais em ValueScript
Exceções são difíceis de acertar. Um problema particularmente complicado que é fácil de ignorar é a possibilidade de avaliação parcial dentro trydos blocos.
Considere o seguinte programa JavaScript:
let a = new SmallQueue(["item1"]);
let b = new SmallQueue(["item2", "item3", "item4"]);
try {
const item = a.pop();
b.push(item);
} catch (e) {
console.error("Failed to move item from a to b", e);
}
console.log({ a, b });
{
a: [],
b: ["item2", "item3", "item4", "item1"],
}
{
a: [],
b: ["item2", "item3", "item4"],
}
let a = new SmallQueue(["item1"]);
let b = new SmallQueue(["item2", "item3", "item4"]);
try {
if (b.isFull()) {
throw new Error("b is full");
}
const item = a.pop();
b.push(item);
} catch (e) {
console.error("Failed to move item from a to b", e);
}
console.log({ a, b });
Outra opção é salvar uma cópia das variáveis que podem ser alteradas e restaurá-las em catch:
let a = new SmallQueue(["item1"]);
let b = new SmallQueue(["item2", "item3", "item4"]);
const aCopy = a.copy();
const bCopy = b.copy();
try {
const item = a.pop();
b.push(item);
} catch (e) {
a = aCopy;
b = bCopy;
console.error("Failed to move item from a to b", e);
}
console.log({ a, b });
- Você pode não fazer isso porque é prolixo e parece desnecessariamente defensivo
- Requer uma
copyoperação a ser definida - Se a
copyoperação existir, pode não ser eficiente - Se
a.poptiver efeitos colaterais, esses efeitos colaterais não serão revertidos
let a = new SmallQueue(["item1"]);
let b = new SmallQueue(["item2", "item3", "item4"]);
let item;
try {
item = a.pop();
} catch (e) {
console.error("Failed to move item from a to b", e);
console.log({ a, b });
return;
}
try {
b.push(item);
} catch (e) {
a.unPop(item);
console.error("Failed to move item from a to b", e);
}
console.log({ a, b });
- Extremamente prolixo
a.unPop(item)exige que entendamos que esta operação é necessária quandob.push(item)falha, o que ainda é fácil de perder
No ValueScript, tryos blocos são transacionais — eles são executados até a conclusão ou são revertidos.
Nosso programa original faz o que queríamos sem nenhuma modificação:
let a = new SmallQueue(["item1"]);
let b = new SmallQueue(["item2", "item3", "item4"]);
try {
const item = a.pop();
b.push(item);
} catch (e) {
console.error("Failed to move item from a to b", e);
}
console.log({ a, b });
{
a: ["item1"],
b: ["item2", "item3", "item4"],
}
- “Você pode não fazer isso”
— O compilador ValueScript insere as instruções automaticamente - “Requer
copyoperação”
— ValueScript usa semântica de valor, apenas usaaCopy = a, e isso é equivalente a copiar - “
copypode não ser eficiente”
— ValueScript usa copy-on-write até o final, é bastante eficiente - “Efeitos colaterais
a.popnão serão revertidos”
— ValueScript não tem efeitos colaterais
* algumas funções estrangeiras impressionantes podem incluir operações de reversão e estas seriam chamadas automaticamente
ValueScript é um dialeto do TypeScript com semântica de valor. Ele tem um playground online que inclui uma demonstração do programa deste artigo e é de código aberto .





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)