Transaktionale Try-Blöcke in ValueScript
Ausnahmen sind schwer richtig zu machen. Ein besonders kniffliges und leicht zu übersehendes Problem ist die Möglichkeit der Teilauswertung innerhalb von tryBlöcken.
Betrachten Sie das folgende JavaScript-Programm:
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 });
Eine andere Möglichkeit besteht darin, eine Kopie der Variablen zu speichern, die sich möglicherweise ändern, und sie wiederherzustellen unter 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 });
- Sie tun es vielleicht nicht, weil es wortreich ist und sich unnötig defensiv anfühlt
- Es muss eine
copyOperation definiert werden - Wenn die
copyOperation vorhanden ist, ist sie möglicherweise nicht effizient - Wenn
a.popNebenwirkungen auftreten, werden diese Nebenwirkungen nicht rückgängig gemacht
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 });
- Extrem wortreich
a.unPop(item)erfordert, dass wir verstehen, dass diese Operation erforderlich ist, wennb.push(item)sie fehlschlägt, was immer noch leicht zu übersehen ist
In ValueScript trysind Blöcke transaktional – sie werden entweder bis zum Ende ausgeführt oder zurückgesetzt.
Unser ursprüngliches Programm macht das, was wir wollten, ohne Änderungen:
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"],
}
- „Sie könnten es nicht tun“
– Der ValueScript-Compiler fügt die Anweisungen automatisch ein - „
copyVorgang erforderlich“
– ValueScript verwendet Wertsemantik, es verwendet nuraCopy = a, und dies entspricht dem Kopieren - „
copyMöglicherweise nicht effizient“
– ValueScript verwendet Copy-on-Write ganz nach unten, es ist ziemlich effizient - „Nebenwirkungen von
a.popwerden nicht rückgängig gemacht“
– ValueScript hat keine Nebeneffekte
* Einige großartige Fremdfunktionen könnten Wiederherstellungsoperationen enthalten, und diese würden automatisch aufgerufen
ValueScript ist ein Dialekt von TypeScript mit Wertsemantik. Es hat einen Online-Spielplatz, der eine Demonstration des Programms dieses Artikels enthält , und es ist Open Source .

![Was ist überhaupt eine verknüpfte Liste? [Teil 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































