mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-21 05:50:55 +08:00
84 lines
3.1 KiB
TypeScript
84 lines
3.1 KiB
TypeScript
// find / some / every with JS-exact semantics: the length is read once up
|
|
// front, callbacks run left-to-right, and all three short-circuit — no
|
|
// callback runs past the deciding element. find's miss is undefined,
|
|
// narrowed through the T | undefined union like a Map get-miss.
|
|
const nums = [3, 8, 15, 4, 42];
|
|
|
|
const firstBig = nums.find((x) => x > 10);
|
|
if (firstBig !== undefined) console.log("firstBig", firstBig, firstBig + 1);
|
|
const missing = nums.find((x) => x > 100);
|
|
console.log(missing === undefined, missing !== undefined);
|
|
|
|
// Short-circuit: the callback stops at the first hit.
|
|
let findCalls = 0;
|
|
nums.find((x) => {
|
|
findCalls += 1;
|
|
return x === 15;
|
|
});
|
|
console.log("findCalls", findCalls);
|
|
|
|
// some / every over numbers, strings, booleans.
|
|
console.log(nums.some((x) => x > 40), nums.some((x) => x > 100));
|
|
console.log(nums.every((x) => x > 0), nums.every((x) => x % 2 === 0));
|
|
console.log(["a", "bc", ""].some((s) => s.length === 0));
|
|
console.log(["a", "bc"].every((s) => s.length > 0));
|
|
console.log([true, true].every((b) => b), [false, false].some((b) => b));
|
|
|
|
// Short-circuit counts for both.
|
|
let someCalls = 0;
|
|
nums.some((x) => {
|
|
someCalls += 1;
|
|
return x === 8;
|
|
});
|
|
let everyCalls = 0;
|
|
nums.every((x) => {
|
|
everyCalls += 1;
|
|
return x < 10;
|
|
});
|
|
console.log("calls", someCalls, everyCalls);
|
|
|
|
// Empty arrays: some is false, every is (vacuously) true, find misses.
|
|
const empty: number[] = [];
|
|
console.log(empty.some((x) => x > 0), empty.every((x) => x > 0));
|
|
console.log(empty.find((x) => x > 0) === undefined);
|
|
|
|
// Index and array parameters: JS passes (element, index, array).
|
|
const bytes = [80, 75, 3, 4];
|
|
const prefix = [80, 75];
|
|
console.log(prefix.every((byte, index) => bytes[index] === byte));
|
|
console.log(prefix.some((byte, index) => bytes[index] !== byte));
|
|
console.log(nums.some((x, i, arr) => i === arr.length - 1 && x === 42));
|
|
const atIndex = nums.find((_x, i) => i === 3);
|
|
if (atIndex !== undefined) console.log("atIndex", atIndex);
|
|
|
|
// find over record elements: the hit aliases the stored record (mutating
|
|
// the found record mutates the array's element, like JS), the miss is the
|
|
// undefined arm of a REF union.
|
|
const people = [
|
|
{ id: "a", age: 30 },
|
|
{ id: "b", age: 40 },
|
|
];
|
|
const b = people.find((p) => p.id === "b");
|
|
if (b !== undefined) {
|
|
console.log("found", b.id, b.age);
|
|
b.age = 41;
|
|
}
|
|
console.log(people[1]!.age);
|
|
const nobody = people.find((p) => p.id === "z");
|
|
console.log(nobody === undefined);
|
|
|
|
// some/every on record and string-array elements.
|
|
console.log(people.some((p) => p.age > 35), people.every((p) => p.age > 35));
|
|
const models = ["gpt-x", "claude-y"];
|
|
console.log(models.every((m) => !m.startsWith("gemini")));
|
|
console.log(models.some((m) => m === "claude-y"));
|
|
|
|
// find over string elements, and unions with an undefined arm already in
|
|
// the element type (result union == element union).
|
|
const words = ["alpha", "beta", "gamma"];
|
|
const g = words.find((w) => w.startsWith("g"));
|
|
if (g !== undefined) console.log(g, g.length);
|
|
const maybe: (string | undefined)[] = ["x", undefined, "y"];
|
|
const present = maybe.find((w) => w !== undefined);
|
|
if (present !== undefined) console.log("present", present);
|