ilusm.dev
Reference

Types

ilusm is dynamically typed. Every value has one of eight types. Use typ(x) to check the type of any value at runtime.

The eight types

Type nameDescriptionLiteral / example
numNumber - integer or floating point42, 3.14, 0xFF
strString - UTF-8 text"hello", $"hi {name}"
lstList - ordered collection of any values[1, "two", tru]
objObject - key/value record, keys are strings{x: 1, name: "ibot"}
bolBooleantru, fls
nilNull / absence of valuenil
funUser-defined functionadd(a, b) = a + b
bifBuilt-in functionprn, len, typ

num - numbers

All numbers are the same type whether integer or float. Hex literals are supported.

x = 42
y = 3.14
z = 0xFF       # 255

prn typ(x)     # num
prn typ(y)     # num

Convert a string to a number with int(s):

n = int("42")  # 42

str - strings

Plain strings use "...". Interpolated strings use $"..." with {expr} inside.

name = "ibot"
greeting = $"hello {name}"   # "hello ibot"
sum_str  = $"1 + 2 = {1+2}"  # "1 + 2 = 3"

Convert any value to string with str(x):

s = str(42)    # "42"
s = str(tru)   # "tru"

Strings are indexed by Unicode rune position. See the strings guide for the full txt module API.

lst - lists

Ordered collections. Items can be any type. Zero-indexed.

xs = [1, "two", tru, nil]
prn xs[0]      # 1
prn xs[2]      # tru
prn len(xs)    # 4

xs[1] = 999    # mutate in place

See the lists guide for the full trl module API.

obj - objects

Key/value records. Keys are always strings. Values can be any type. Fields can be added at any time.

cfg = {host: "localhost", port: 8080}
prn cfg.host   # "localhost"
prn cfg.port   # 8080

cfg.port = 9000        # update existing field
cfg.debug = tru        # add new field

Nested objects work naturally:

usr = {info: {name: "ibot", age: 30}}
prn usr.info.name      # "ibot"

Use optional chaining to safely access fields that might be nil:

prn usr?.info?.email   # nil (no crash)

bol - booleans

Two values: tru and fls. Note - not true/false.

ok = tru
bad = fls
prn typ(ok)    # bol

nil - null

Represents the absence of a value. Accessing a missing object field returns nil.

x = nil
prn typ(x)     # nil

cfg = {host: "localhost"}
prn cfg.port   # nil (field doesn't exist)

fun and bif - functions

User-defined functions have type fun. Built-in functions (like prn, len) have type bif. Both are first-class values - you can pass them around.

add(a, b) = a + b
prn typ(add)   # fun
prn typ(prn)   # bif

apply(f, x) = f(x)
prn apply(\(n) n * 2, 5)   # 10

Checking types

typ(x) returns the type name as a string:

check(x) =
    t = typ(x)
    if t == "num": prn "it's a number"
    | if t == "str": prn "it's a string"
    | if t == "lst": prn "it's a list"
    | prn $"it's a {t}"

check(42)       # it's a number
check("hello")  # it's a string
check([1,2])    # it's a list

Truthiness

These values are falsy: fls, nil, 0, "", [].

Everything else is truthy - including {}, non-zero numbers, non-empty strings and lists.

if nil:  prn "no"   # skipped
if 0:    prn "no"   # skipped
if "":   prn "no"   # skipped
if []:   prn "no"   # skipped

if {}:   prn "yes"  # runs - empty object is truthy
if [0]:  prn "yes"  # runs - non-empty list is truthy

Use or for default values:

name = user_input or "anonymous"
port = cfg.port or 8080