Everyday VCL
This chapter mirrors TS Handbook “Everyday Types,” but in VCL’s indent-first, dot-terminated style.
Blocks, indentation, trailing dots
- Indentation defines scope; tabs are disallowed. Use spaces consistently.
- Statements end with a trailing dot (
.). Missing dots are a common error. - Example:
text
define greet.
let message = "hi".
log message.
Values and literals
- Primitives:
number,string,boolean,none. - Records:
{ name: "ada", age: 36 }(keys are identifiers; strings allowed via quotes). - Variants (sum types):
Ok(value)/Err(reason)pattern; pattern matching is planned—today treat as tagged data. - Arrays:
[1, 2, 3].
Bindings
letintroduces a binding in the current scope.- Reassignment is allowed with
let x = ...again in the same scope; shadowing is permitted in nested scopes.
Control flow
when <condition>.introduces a block. Useelse.for alternate branch.
text
when user.is_admin.
log "admin".
else.
log "user".
ensure/validate/expectare semantic checks (see Effects chapter for failure semantics).
Functions / handlers
- Define named handlers with
define name.. Handlers take a single implicitctxrecord; additional params are pattern fields insidectx(common convention). Example:
text
define add_user.
let { name, email } = ctx.
store { path: "users", value: { name, email } }.
return { status: "ok" }.
Types (lightweight)
- VCL is structurally typed; most code is inferred. Explicit type annotations are currently minimal; use the spec for edge cases.
- Truthiness: only
noneis falsy.
Common pitfalls
- Missing trailing dots.
- Mixed tabs/spaces in indent.
- Forgetting to return a value from handlers that the runtime expects.
See also: Language Spec for formal grammar and Stdlib for available helpers.