Lesson 3.4

Built-in Functions

The 40+ functions available in every Monk program without importing anything.

monk c 15 min read

Functions that come with the house.

Every Monk program has access to a set of functions without importing anything. No import, no require, no setup. They just exist.

These built-in functions are implemented in C as part of the runtime library. When you write show(42) in Monk, the code generator emits monk_show(monk_int(42)) in C. No magic dispatch, no reflection, no function pointer lookup. It's a direct C function call.

Built-in functions are just C functions. When you write show(42) in Monk, the code generator emits monk_show(monk_int(42)) in C. No magic dispatch, no reflection.

Output.

One function: show(). It prints any MonkValue to stdout. Integers print as numbers, strings print without quotes, arrays print with brackets, records print as key-value pairs. It handles every tag.

show(42)              // 42
show("hello")         // hello
show([1, 2, 3])       // [1, 2, 3]
show(true)            // true
show(none)            // none

Type conversion and checking.

Two categories: functions that convert between types, and functions that tell you what type a value is.

Function
Purpose
Example
typeof(v)
Returns the type as a string
typeof(42) -> "int"
to_string(v)
Converts any value to string
to_string(42) -> "42"
to_int(v)
Converts to integer
to_int("42") -> 42
to_float(v)
Converts to float
to_float("3.14") -> 3.14

Type checks return booleans:

is_number(42)         // true
is_string("hello")    // true
is_boolean(false)     // true
is_number("hello")    // false

Math: 17 functions.

All the standard math operations. These map directly to C standard library math functions.

Rounding

abs(x)

floor(x)

ceil(x)

round(x)

Powers & Logs

sqrt(x)

pow(x, y)

log(x)

log10(x)

exp(x)

Trigonometry

sin(x), cos(x), tan(x)

asin(x), acos(x), atan(x)

min(x, y)

max(x, y)

let hypotenuse = sqrt(pow(3, 2) + pow(4, 2))
show(hypotenuse)      // 5

String operations.

Function
Example
length(s)
length("hello") -> 5
substring(s, start, end)
substring("hello", 1, 3) -> "el"
index_of(s, sub)
index_of("hello", "ll") -> 2
split(s, sep)
split("a,b,c", ",") -> ["a", "b", "c"]
trim(s)
trim(" hi ") -> "hi"
to_upper_case(s)
to_upper_case("hello") -> "HELLO"
to_lower_case(s)
to_lower_case("HELLO") -> "hello"

Note: length() counts UTF-8 codepoints, not bytes. This is an O(n) operation. The runtime walks the string to count characters.

Array operations: always new arrays.

Every array operation returns a new array. This is value semantics in action. The original array is never modified.

Function
Behavior
append(arr, val)
Returns new array with val added at end
prepend(arr, val)
Returns new array with val added at start
pop(arr)
Returns new array without the last element
drop(arr, n)
Returns new array without the first n elements
take(arr, n)
Returns new array with only the first n elements
slice(arr, start, end)
Returns a sub-array from start to end
range(start, end)
Creates a new array [start, start+1, ..., end-1]
let nums = [1, 2, 3]
let more = append(nums, 4)
show(nums)            // [1, 2, 3] -- untouched
show(more)            // [1, 2, 3, 4]

Monk arrays are homogeneous: all elements must be the same type. No mixing integers and strings in one array. Use records for mixed data.

Graceful on reads, strict on operations.

Monk applies a consistent philosophy to edge cases:

R

Reading out-of-bounds returns none.

Accessing index 10 of a 3-element array gives you none. No crash. Graceful degradation.

W

Writing out-of-bounds is an error.

Trying to assign to index 10 of a 3-element array throws an error. Operations that modify data must be explicit about what they're doing.

This shows up across the built-ins. Missing record fields return none. index_of() returns -1 when not found (graceful). But to_int("abc") throws (strict -- you asked for a conversion that can't work).

File I/O and environment.

A small set of functions for interacting with the outside world:

file_read(path) Read entire file as string
file_write(path, content) Write string to file (creates or overwrites)
file_exists(path) Check if file exists (returns bool)
env_get(key) Read an environment variable
args() Get command-line arguments as string array
exit(code) Terminate with exit code
let content = file_read("config.txt")
if content != none {
    show(content)
}

Key takeaways

1

Built-in functions are C functions in the runtime, called directly by the generated code. No indirection.

2

All array operations return new arrays. The original is never modified (value semantics).

3

Reading missing data is graceful (returns none). Operating on invalid data is strict (throws an error).

4

40+ functions across output, types, math, strings, arrays, files, and environment. All available without imports.