Language Reference

For the JavaScript embedding API, see JS API documentation.

Builtins

Functions

if
Parameters:
  • cond
  • ifTrue (lazy)
  • ifFalse (lazy): defaults to nil if not provided

Conditional branching.

Evaluates condition; if truthy, evaluates true_expr, otherwise false_expr.

if (x > 0) "positive" "non-positive"
return
Parameters:
  • valueToReturn (any)
Returns: (never)

Return from a lambda. Only valid inside one (it's not defined outside of one).

[x] => (
    if (x == 0) (return "zero")
    # other code here that will be skipped if x == 0
)
print
Parameters:
  • values (rest any)
Returns: (nil)

Prints values to whatever is configured as the print hook (usually stdout or similar)

print "hello" "," " world" "!" # hello, world!
range
Parameters:
  • start (number)
  • stop (number)
  • step (number)
Returns: (list[number])

Create a list of numbers from start to stop separated by step

range 4 # => [0, 1, 2, 3]
range 1 6 # => [1, 2, 3, 4, 5]
range 0 10 2 # => [0, 2, 4, 6, 8]
error
Parameters:
  • message (string)
Returns: (never)

Throw an error with the specified message

error "Something went wrong with {x}!"
splat
Parameters:
  • value (list | roundblock)
Returns: (splat)

Force the value to be spliced into its callsite.

Values

nil
Type: nil

false
Type: number

true
Type: number

done
Type: done

Syntax

Raw String
Syntax:
  • 'text {text} text \text'

Raw string without escapes or interpolations processed

Normal String
Syntax:
  • "text {expression} \u{1F34}"

Double-quoted strings with interpolation and escapes

x := 0x123
# objects that have been processed use the default stringification method
"hello, {x + 0}" # => "hello, 291"
# objects that have not been processed remember how they were originally written
"hello, {x}" # => "hello, 0x123"
Merge Maps
Syntax:
  • map1 + map2

Merge maps (2nd map's keys take priority)

[1: 2, 2: 4] + [1: 3, 4: 5] # => [1: 3, 2: 4, 4: 5]
Index List
Syntax:
  • list -> number

Access list indices

x := [1, 2, 3]
x->1 # => 2
x->0 = 3 # now x == [3, 2, 3]
Query Map
Syntax:
  • map -> any

Access map keys

y := ["a": 1, "b": 2]
y->"b" # => 2
y->"c" = 3 # now y == ["a": 1, "b": 2, "c": 3]
Query Map String Key Shorthand
Syntax:
  • map.name

Dot-key shorthand for indexing with a name string.

["a": 1, "b": 2].b # => 2
Length
Syntax:
  • #collection

Length of string, list, or map

#"hello" # => 5
#[1, 2, 3] # => 3
#[1: 2] # => 1
Containment
Syntax:
  • item <: collection
  • collection :> item

Test if a collection contains an item

[1, 2, 3] :> 1 # => true
1 <: [1: 3, 2: 4] # => true
Ternary
Syntax:
  • cond ? ifTrue : ifFalse

C-style inline conditional. Equivalent to a call to if.

Logical NOT
Syntax:
  • (!any)

Exponentiation
Syntax:
  • number ** number

Multiplication
Syntax:
  • number * number

Division
Syntax:
  • number / number

Modulo
Syntax:
  • number % number

Add
Syntax:
  • number + number

Subtract
Syntax:
  • number - number

Unary negation
Syntax:
  • (-number)

Only valid at start of expression!

Logical OR
Syntax:
  • any || any

Logical AND
Syntax:
  • any && any

Bitwise Left Shift
Syntax:
  • number << number

Bitwise Right Shift
Syntax:
  • number >> number

Quote
Syntax:
  • `expression

Quote a value without evaluating it

`(thisvariabledoesnotexist + 1) # won't error
Bitwise OR
Syntax:
  • number | number

Bitwise AND
Syntax:
  • number & number

Bitwise XOR
Syntax:
  • number ^ number

Equality
Syntax:
  • number == number

Inequality
Syntax:
  • number != number

Greater than
Syntax:
  • number > number

Less than
Syntax:
  • number < number

Greater than or equal
Syntax:
  • number >= number

Less than or equal
Syntax:
  • number <= number

Quasiquote Templating
Syntax:
  • "{value value $interpolated {innerValue $$alsoInterpolated $notInterpolated}}"

Quasiquoting of values. Works exactly like Scheme's quasiquote and unquote. Currently there is no unquote-splicing.

Concatenate Strings
Syntax:
  • string + string

"hello, " + "world!" # => "hello, world!"
Declare Variable
Syntax:
  • name := value

Declare a variable in the current scope and bind it to a value

x := 10
x := 10 # errors, x is already defined
Assign Value
Syntax:
  • name = value
  • lvalue = value

Assign a new value to an existing variable

x := 10
x = 20 # ok
y = 20 # errors, y is not defined
x->1 = 20 # ok if x is indexable
Lambda
Syntax:
  • [params] => body

Define a lambda function

# simple parameters
[a b c] => [x] => a * x * x + b * x + c
# rest parameter
[values...] => nil
# lazy parameters for metaprogramming
or := [@first @second] => (
    temp = (first!)
    if temp (return temp)
    second!
)
Splat
Syntax:
  • ...list
  • ...roundblock

Expand the item by wrapping it in a call to splat.

List Literal
Syntax:
  • [item1, item2, ...]

List literal

Map Literal
Syntax:
  • [key: value, key2: value2, ...]

Key-value map literal (unordered)

["name": "Alice", "age": 30]
# use the quote operator to use a symbol as the key
[`name: "Alice", `age: 30]
# Shorthand for symbol key and value being that variable:
variable := 10
[`variable:] # => [`variable: 10]
Concatenate Lists
Syntax:
  • list1 + list2

Concatenate lists

[1, 2] + [3, 4] # => [1, 2, 3, 4]

FFI

Functions

JS_new
Parameters:
  • class (JSObjectRef): The class to construct
  • args (rest): constructor arguments
Returns: (JSObjectRef)

Construct the object (Javascript new operator)

Values

JS_GLOBAL
Type: JSObjectRef

A reference to the Javascript global object

Syntax

Subscript Object
Syntax:
  • object->"key"

Get the key on the JSObject

Assign to Object
Syntax:
  • object->"key" = value

Set the key on the JSObject