Skip to content

Bindings

Hem’s let is TypeScript’s const; let mut is TypeScript’s let. In core Hem, writing const is an error with an editor quick fix to replace it with let:

let name = "hem"
let mut count = 0
count += 1

Destructuring works as in TS: let { id, name } = user, let [head, ...rest] = items. Annotations are TypeScript’s type language, verbatim: let port: number = 8080. One deliberate divergence: object-type literals you write in Hem are readonly by default, and a per-field mut opts back into mutability, matching let and class fields.

Shadowing is legal: each new binding can have a different type. Here port goes from ?string to string to number:

port.hemhem
let readPort = (env: Env): number => {
  let port = env.PORT
  let Some(port) = port else return 8080
  let port = Number.parseInt(port, 10)
  if Number.isNaN(port) { 8080 } else { port }
}
port.ts — generatedts
const readPort = (env: Env): number => {
  const port = env.PORT;
  const _hemValue = port;
  if (_hemValue === null || _hemValue === undefined) {
    return 8080;
  }
  const port$1 = _hemValue;
  const port$2 = Number.parseInt(port$1, 10);
  return Number.isNaN(port$2) ? 8080 : port$2;
};

For same-type steps, chaining or |> is usually clearer.

Shadowing creates a new binding; it does not mutate the old one. A closure keeps the binding it captured, so this logs 5:

capture.hemhem
let x = 5
let printX = () => console.log(x)
let x = 6
printX()
capture.ts — generatedts
const x = 5;
const printX = () => console.log(x);
const x$1 = 6;
printX();
Navigation

Type to search…

↑↓ navigate↵ selectEsc close