mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
Improve tutorial
This commit is contained in:
@@ -5,6 +5,8 @@ const files: Record<string, string | nil> = {
|
||||
...pick(raw, [
|
||||
'/tutorial/hello.ts',
|
||||
'/tutorial/valueSemantics.ts',
|
||||
'/tutorial/cantMutateCaptures.ts',
|
||||
'/tutorial/classBehavior.ts',
|
||||
'/tutorial/revertOnCatch.ts',
|
||||
'/tutorial/binaryTree.ts',
|
||||
]),
|
||||
|
||||
@@ -11,6 +11,6 @@ export default Object.fromEntries(await Promise.all(
|
||||
entries.map(async ([path, module]) => {
|
||||
const prefix = './root';
|
||||
assert(path.startsWith(prefix));
|
||||
return [path.slice('./root'.length), await module()];
|
||||
return [path.slice('./root'.length), (await module()).trim()];
|
||||
}),
|
||||
));
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
export default function main() {
|
||||
let idGen = new IdGenerator();
|
||||
|
||||
return [
|
||||
idGen.generate(),
|
||||
idGen.generate(),
|
||||
idGen.generate(),
|
||||
];
|
||||
}
|
||||
|
||||
class IdGenerator {
|
||||
nextId: number;
|
||||
|
||||
constructor() {
|
||||
this.nextId = 1;
|
||||
}
|
||||
|
||||
generate() {
|
||||
const result = this.nextId;
|
||||
this.nextId++;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
export default function main() {
|
||||
let nextId = 1;
|
||||
|
||||
function generateId() {
|
||||
const result = nextId;
|
||||
nextId++;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return [
|
||||
generateId(),
|
||||
generateId(),
|
||||
generateId(),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// ValueScript is like TypeScript without side effects. We achieve this by
|
||||
// deviating from JavaScript in three key ways.
|
||||
//
|
||||
// 2. Captured variables cannot be mutated
|
||||
|
||||
export default function main() {
|
||||
let counter = 0;
|
||||
|
||||
const next = () => {
|
||||
counter++;
|
||||
return counter;
|
||||
};
|
||||
|
||||
return [next(), next(), next()];
|
||||
// JavaScript: [1, 2, 3]
|
||||
// ValueScript: Compilation error
|
||||
}
|
||||
|
||||
// Both JavaScript and ValueScript allow:
|
||||
// - Mutating variables
|
||||
// - Capturing variables
|
||||
//
|
||||
// But in ValueScript you can only do one or the other.
|
||||
//
|
||||
// By allowing both, JavaScript allows the `next` function to return different
|
||||
// values each time it is called. This is a side effect.
|
||||
//
|
||||
// However, you can get this kind of behavior in ValueScript by using a class...
|
||||
33
website/src/playground/files/root/tutorial/classBehavior.ts
Normal file
33
website/src/playground/files/root/tutorial/classBehavior.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
// ValueScript is like TypeScript without side effects. We achieve this by
|
||||
// deviating from JavaScript in three key ways.
|
||||
//
|
||||
// 3. When `this` changes inside `counter.next()`, the updated `this` value is
|
||||
// used to mutate `counter` when the method returns.
|
||||
|
||||
export default function main() {
|
||||
let counter = new Counter();
|
||||
|
||||
return [counter.next(), counter.next(), counter.next()];
|
||||
// JavaScript: [1, 2, 3]
|
||||
// ValueScript: [1, 2, 3]
|
||||
}
|
||||
|
||||
class Counter {
|
||||
value = 0;
|
||||
|
||||
next() {
|
||||
this.value++;
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
// This difference is more subtle - the program as a whole behaves the same but
|
||||
// the implementation is different.
|
||||
//
|
||||
// In JavaScript, when `this.value++` updates `this`, it is doing that directly
|
||||
// on the `counter` object.
|
||||
//
|
||||
// In ValueScript, `this` is just a variable, and variable mutation is always
|
||||
// local. Instead, methods have an implicit extra output for `this` (similar to
|
||||
// `this` being an implicit input in both languages). That extra output is used
|
||||
// to mutate the variable on the left side of the dot when the method returns.
|
||||
@@ -1,12 +1,13 @@
|
||||
// Welcome to the ValueScript playground!
|
||||
//
|
||||
// This playground also acts as a tutorial by describing a variety of
|
||||
// examples. All examples are editable with live updates to their outputs.
|
||||
//
|
||||
// Keeping with tradition, here is the hello world program.
|
||||
// ValueScript is a dialect of TypeScript. We use the same syntax and many
|
||||
// simple programs work exactly the same way:
|
||||
|
||||
export default function main() {
|
||||
return "Hello world!";
|
||||
}
|
||||
|
||||
// When you're ready to continue, click next below.
|
||||
// You can freely edit these examples and their outputs will update in
|
||||
// real-time.
|
||||
//
|
||||
// When you're ready, click next below to see a bit more complexity.
|
||||
@@ -1,3 +1,7 @@
|
||||
// We also deviate from JavaScript in a few other ways:
|
||||
//
|
||||
// - Try blocks are transactional
|
||||
|
||||
export default function () {
|
||||
let x = 0;
|
||||
|
||||
@@ -7,12 +11,16 @@ export default function () {
|
||||
} catch {}
|
||||
|
||||
return x;
|
||||
// TypeScript: 1
|
||||
// JavaScript: 1
|
||||
// ValueScript: 0
|
||||
}
|
||||
|
||||
// In ValueScript, a try block is a transaction - it either runs to
|
||||
// completion, or it is reverted. This is impractical in TypeScript,
|
||||
// but in ValueScript all we have to do is snapshot the variables and
|
||||
// restore from them on catch. This works because all mutation is
|
||||
// local - nothing else can be affected.
|
||||
// When the exception is thrown above, the value of `x` is reverted to the
|
||||
// value before the `try` block. Value semantics is very important here. Without
|
||||
// it, you'd need to do something much more heavy like snapshot the entire
|
||||
// virtual machine. In ValueScript, we just take a snapshot of each variable
|
||||
// that is mutated inside the `try` block and restore it on `catch`. You can see
|
||||
// this in the assembly as `%snap_x`.
|
||||
//
|
||||
// Note: Method calls don't yet generate snapshots. This should be fixed soon.
|
||||
// In the meantime you can workaround it by adding `myClass = myClass;`.
|
||||
@@ -1,15 +1,20 @@
|
||||
// ValueScript is like TypeScript without side effects. We achieve this by
|
||||
// deviating from JavaScript in three key ways.
|
||||
//
|
||||
// 1. Value semantics
|
||||
|
||||
export default function main() {
|
||||
const leftBowl = ["apple", "mango"];
|
||||
|
||||
const rightBowl = leftBowl;
|
||||
let rightBowl = leftBowl;
|
||||
rightBowl.push("peach");
|
||||
|
||||
return leftBowl.includes("peach");
|
||||
// TypeScript: true
|
||||
// JavaScript: true
|
||||
// ValueScript: false
|
||||
}
|
||||
|
||||
// In TypeScript, `leftBowl` and `rightBowl` are the same object, and that
|
||||
// In JavaScript, `leftBowl` and `rightBowl` are the same object, and that
|
||||
// object changes. In ValueScript, objects are just data, they don't change.
|
||||
// When you change `rightBowl`, you are changing the *variable* and therefore
|
||||
// `leftBowl` doesn't change.
|
||||
Reference in New Issue
Block a user