Coming From Another Language: JavaScript
● Beginner6 minBefore this: Coming From Another Language
From JavaScript: types checked before the program runs, == that compares contents, no null or undefined, and tasks instead of async.
Here is one small program twice: in JavaScript as you would write it, then in Kavach. Orders with a quantity and a price, a total that refuses an order with no quantity, and discount codes that may be missing. Both print the same three lines.
class Order {
constructor(item, qty, cents) {
this.item = item;
this.qty = qty;
this.cents = cents;
}
cost() {
return this.qty * this.cents;
}
}
class BadQty extends Error {
constructor(item) {
super(`no quantity for ${item}`);
this.item = item;
}
}
function total(orders) {
for (const o of orders) {
if (o.qty <= 0) {
throw new BadQty(o.item);
}
}
return orders.reduce((sum, o) => sum + o.cost(), 0);
}
const codes = new Map([["SPRING", 10], ["VIP", 25]]);
const orders = [new Order("pen", 3, 150), new Order("cup", 1, 900)];
let sum;
try {
sum = total(orders);
} catch {
sum = 0;
}
const off = codes.get("SPRING") ?? 0;
console.log(`total ${sum}, with ${off}% off ${Math.trunc((sum * (100 - off)) / 100)}`);
console.log(`WINTER gives ${codes.get("WINTER") ?? 0}%`);
const broken = [new Order("kite", 0, 500)];
try {
console.log(`total ${total(broken)}`);
} catch (e) {
if (!(e instanceof BadQty)) throw e;
console.log(`refused: no quantity for ${e.item}`);
}type Order {
item: String
qty: Int
cents: Int
fn cost(self) -> Int {
self.qty * self.cents
}
}
type OrderError = BadQty(item: String)
fn total(orders: [Order]) -> Int ! OrderError {
for o in orders {
if o.qty <= 0 {
fail OrderError.BadQty(item: o.item)
}
}
orders.sum(o => o.cost())
}
fn main() {
const codes = ["SPRING": 10, "VIP": 25]
const orders = [Order(item: "pen", qty: 3, cents: 150), Order(item: "cup", qty: 1, cents: 900)]
const sum = total(orders) catch _ => 0
const off = codes["SPRING"] ?? 0
print("total {sum}, with {off}% off {sum * (100 - off) / 100}")
print("WINTER gives {codes["WINTER"] ?? 0}%")
const broken = [Order(item: "kite", qty: 0, cents: 500)]
match total(broken) {
ok(t) => print("total {t}"),
err(OrderError.BadQty(item)) => print("refused: no quantity for {item}"),
}
}The program ran and printed:
kavach run orders.kav
total 1350, with 10% off 1215WINTER gives 0%refused: no quantity for kite
What changes
| In JavaScript | In Kavach | Learn it |
|---|---|---|
class Order with a constructor | type Order { … }: Order(item: "pen", qty: 3, cents: 150) makes one | Records |
extends | no inheritance: a field, or an interface | Classes and Inheritance |
throw anything, then catch | fail with an error of the type the signature names, ! OrderError | Errors |
null and undefined | none, only in a type that ends in ? | Optionals |
a === b | a == b, which compares contents | Comparison |
new Map([["SPRING", 10]]) | ["SPRING": 10] | Making a map |
template strings, ${x} | "total {x}": every string can hold values | Interpolation |
orders.reduce((s, o) => s + o.cost(), 0) | orders.sum(o => o.cost()) | map, filter, sum |
every number is a float, and Math.trunc | Int for whole numbers, whose / gives a whole number; Decimal for exact amounts | Data Types |
| objects and arrays shared by reference | values: b = a copies | Values, Not References |
async, await and promises | spawn and .wait(), with no async and no await | Tasks |
npm and package.json | kavach.toml, and kavach add | Packages |
| types only with TypeScript | every type checked before the program runs | Data Types |
Habits from other languages get a clear error that says what to write instead: see Habits from other languages.