Functions
This page aims to concisely document all in-built Rad functions.
How to Read This Document¶
Function Signatures¶
You'll see notation like this for function signatures (below are not real functions in Rad; just examples):
greet(name: str, times: int = 10) -> string
This means the function greet
takes one required string argument name
, and an optional int argument times
which
defaults to 10 if not specified. It returns a string.
greet_many(names: list[string] | ...string) -> none
This means that greet_many
can be called in two ways: either with a single argument that is a list of strings, or |
a variable number of string arguments.
In both cases, the function returns nothing.
do_something(input: any, log: string?) -> any, error?!
This means the function do_something
takes a required argument input
which can be of any type.
It also has an optional argument log
which will default to null
if left unspecified.
The values it returns depends on how the function is called. If it's being assigned to two variables e.g.
foo, bar = do_something(myvar)
then it will return some any
value for foo
, and it returns a nullable error
for bar
.
The exclamation point !
signifies that, if the call is only assigned to one variable e.g.
foo = do_something(myvar)
and the function fails i.e. would return a non-null
error
value, then it will instead panic and exit the script
with said error.
error
¶
error
may be referenced as a return type for some functions. error
is really a map
with the following keys:
code: string
- An error code indicating the type of error.msg: string
- A description of the error.
Lastly, you may also see number
referenced as a type -- this just means int | float
, i.e. any numeric type.
Output¶
print¶
Prints zero or more items to stdout, separated by a delimiter.
print(*_items: any, *, sep: str = " ", end: str = "\n") -> void
print("Hello!") // -> Hello!
print() // -> (just newline)
print("Hello", "world") // -> Hello world
print(1, 2, 3, sep=", ") // -> 1, 2, 3
print("No newline", end="") // -> No newline
print_err¶
Behaves like print
but outputs to stderr instead of stdout.
print_err(*_items: any, *, sep: str = " ", end: str = "\n") -> void
pprint¶
Pretty prints data in JSON format with indentation and colors.
pprint(_item: any?) -> void
item = { "name": "Alice", "age": 30 }
pprint(item)
// Output:
// {
// "name": "Alice",
// "age": 30
// }
debug¶
Behaves like print
but only outputs when debug mode is enabled via --debug
flag.
debug(*_items: any, *, sep: str = " ", end: str = "\n") -> void
Misc¶
sleep¶
Pauses execution for the specified duration.
sleep(_duration: int|float|str, *, title: str?) -> void
Integer and float values are treated as seconds. String values support Go duration format like "2h45m", "1.5s", "500ms".
If title
is provided, it's printed before sleeping.
Duration string suffixes:
Suffix | Description |
---|---|
h |
Hours |
m |
Minutes |
s |
Seconds |
ms |
Milliseconds |
us or µs |
Microseconds |
ns |
Nanoseconds |
Examples:
sleep(2.5) // -> Sleep for 2.5 seconds
sleep("1h30m") // -> Sleep for 1 hour 30 minutes
sleep("500ms") // -> Sleep for 500 milliseconds
sleep(5, title="Waiting...") // -> Prints "Waiting..." then sleeps 5 seconds
len¶
Returns the length of a string, list, or map.
len(input: str|list|map) -> int
len("hello") // -> 5
len([1, 2, 3, 4]) // -> 4
len({"a": 1, "b": 2}) // -> 2
range¶
Generates a list of numbers in a specified range. Useful in for loops.
range(_arg1: float|int, _arg2: float?|int?, _step: float|int = 1) -> list[float|int]
Single argument generates 0 to _arg1
(exclusive). Two arguments generate _arg1
to _arg2
(exclusive). Step cannot
be zero. Returns float list if any argument is float, otherwise int list.
Examples:
range(5) // -> [0, 1, 2, 3, 4]
range(2, 5) // -> [2, 3, 4]
range(0.5, 3) // -> [0.5, 1.5, 2.5]
range(10, 5, -2) // -> [10, 8, 6]
join¶
Joins a list into a string with separator, prefix, and suffix.
join(_list: list, *, sep: str = "", prefix: str = "", suffix: str = "") -> str
join([1, 2, 3], sep=", ") // -> "1, 2, 3"
join(["a", "b"], prefix="[", suffix="]") // -> "[ab]"
join(["x", "y", "z"], sep="-", prefix="(", suffix=")") // -> "(x-y-z)"
zip¶
Combines multiple lists into a list of lists, pairing elements by index.
zip(*lists: list, *, strict: bool = false, fill: any?) -> list[list]|error
Parameters:
Parameter | Type | Description |
---|---|---|
*lists |
list |
Variable number of lists to zip together |
strict |
bool = false |
If true, error on different list lengths |
fill |
any? |
Value to fill shorter lists (optional) |
- By default, truncates to the shortest list length
- Cannot use
strict=true
withfill
parameter (mutually exclusive) - Returns error if
strict=true
and lists have different lengths
Examples:
// Basic usage
zip([1, 2, 3], ["a", "b", "c"]) // -> [[1, "a"], [2, "b"], [3, "c"]]
zip([1, 2, 3, 4], ["a", "b"]) // -> [[1, "a"], [2, "b"]]
// With fill value for unequal lengths
zip([1, 2, 3, 4], ["a", "b"], fill="-") // -> [[1, "a"], [2, "b"], [3, "-"], [4, "-"]]
// Strict mode (errors on length mismatch)
zip([1, 2, 3], ["a", "b"], strict=true) // -> Error: Lists must have the same length
unique¶
Returns a list with duplicate values removed, preserving first occurrence order.
unique(_list: list[any]) -> list[any]
unique([2, 1, 2, 3, 1, 3, 4]) // -> [2, 1, 3, 4]
unique(["a", "b", "a", "c"]) // -> ["a", "b", "c"]
sort¶
Sorts a list or string. When multiple lists are provided, performs parallel sorting where additional lists are reordered to match the primary list's sort permutation.
sort(_primary: list|str) -> list|str
sort(_primary: list|str, *_others: list, *, reverse: bool = false) -> list[list]
Parameters:
Parameter | Type | Description |
---|---|---|
_primary |
list\|str |
Primary data to sort (determines sort order) |
*_others |
list |
Additional lists to reorder in parallel |
reverse |
bool = false |
Sort in descending order |
Parallel Sorting Behavior:
- The first list (
_primary
) determines the sort order - All other lists are reordered to match the same permutation
- All lists must be the same length
- Returns a list containing all sorted lists:
[sorted_primary, sorted_other1, sorted_other2, ...]
Examples:
// Basic sorting
sort([3, 4, 2, 1]) // -> [1, 2, 3, 4]
sort([3, 4, 2, 1], reverse=true) // -> [4, 3, 2, 1]
sort([3, 4, "2", 1, true]) // -> [true, 1, 3, 4, "2"]
sort("hello") // -> "ehllo"
// Parallel sorting
numbers = [2, 1, 4, 3]
letters = ["a", "b", "c", "d"]
bools = [true, false, true, false]
sorted_nums, sorted_letters, sorted_bools = sort(numbers, letters, bools)
// -> [1, 2, 3, 4], ["b", "a", "d", "c"], [false, true, false, true]
type_of¶
Returns the type of a value as a string.
type_of(_var: any) -> str
type_of("hi") // -> "str"
type_of([2]) // -> "list"
type_of(42) // -> "int"
type_of(3.14) // -> "float"
type_of({"a": 1}) // -> "map"
str¶
Converts any value to a string representation.
str(_var: any) -> str
str(42) // -> "42"
str(3.14) // -> "3.14"
str([1, 2]) // -> "[1, 2]"
str(true) // -> "true"
int¶
Converts a value to an integer. Does not work on strings - use parse_int
for string parsing.
int(_var: any) -> int|error
int(3.14) // -> 3
int(true) // -> 1
int(false) // -> 0
int("42") // -> Error: cannot convert string
float¶
Converts a value to a float. Does not work on strings - use parse_float
for string parsing.
float(_var: any) -> float|error
float(42) // -> 42.0
float(true) // -> 1.0
float(false) // -> 0.0
float("3.14") // -> Error: cannot convert string
is_defined¶
Checks if a variable with the given name exists in the current scope.
is_defined(_var: str) -> bool
name = "Alice"
is_defined("name") // -> true
is_defined("age") // -> false
map¶
Applies a function to every element of a list or entry of a map.
map(_coll: list|map, _fn: fn(any) -> any | fn(any, any) -> any) -> list|map
For lists, function receives fn(value)
. For maps, function receives fn(key, value)
.
Examples:
map([1, 2, 3], fn(x) x * 2) // -> [2, 4, 6]
map({"a": 1, "b": 2}, fn(k, v) v * 10) // -> {"a": 10, "b": 20}
filter¶
Applies a predicate function to filter elements of a list or map. Keeps only elements where the function returns true.
filter(_coll: list|map, _fn: fn(any) -> bool | fn(any, any) -> bool) -> list|map
For lists, function receives fn(value)
. For maps, function receives fn(key, value)
.
Examples:
filter([1, 2, 3, 4], fn(x) x % 2 == 0) // -> [2, 4]
filter({"a": 1, "b": 2}, fn(k, v) v > 1) // -> {"b": 2}
load¶
Loads a value into a map using lazy evaluation. If key exists, returns cached value; otherwise runs loader function.
load(_map: map, _key: any, _loader: fn() -> any) -> any|error
load(_map: map, _key: any, _loader: fn() -> any, *, reload: bool = false) -> any|error
load(_map: map, _key: any, _loader: fn() -> any, *, override: any?) -> any|error
Parameters:
Parameter | Type | Description |
---|---|---|
_map |
map |
Map to store/retrieve cached values |
_key |
any |
Key to lookup in the map |
_loader |
fn() -> any |
Function to call if key doesn't exist |
reload |
bool = false |
Force reload even if key exists |
override |
any? |
Use this value instead of calling loader |
If key doesn't exist, _loader
is called and result is cached. Cannot use reload=true
with override
(mutually
exclusive).
Examples:
cache = {}
load(cache, "data", fn() expensive_calculation()) // -> Runs loader, caches result
load(cache, "data", fn() expensive_calculation()) // -> Returns cached value
// Force reload
load(cache, "data", fn() new_calculation(), reload=true)
// Override with specific value
load(cache, "data", fn() ignored(), override="forced")
Input¶
input¶
Gets a line of text input from the user with optional prompt, default, hint, and secret mode.
input(prompt: str = "> ") -> str|error
input(prompt: str = "> ", *, hint: str = "", default: str = "", secret: bool = false) -> str|error
Parameters:
Parameter | Type | Description |
---|---|---|
prompt |
str = "> " |
The text prompt to display to the user |
hint |
str = "" |
Placeholder text shown in input field |
default |
str = "" |
Default value if user doesn't enter anything |
secret |
bool = false |
If true, hides input (useful for passwords) |
If secret
is true, input is hidden (useful for passwords). The hint
parameter has no effect when secret
is
enabled.
Examples:
// Basic input
name = input("What's your name? ") // -> Prompts and waits for input
// With default value
color = input("Favorite color? ", default="blue") // -> Returns "blue" if user presses enter
// With hint text
email = input("Email: ", hint="user@example.com") // -> Shows placeholder text
// Hidden input for passwords
password = input("Password: ", secret=true) // -> Hides typed characters
confirm¶
Gets a boolean confirmation from the user (y/n prompt).
confirm(prompt: str = "Confirm? [y/n] > ") -> bool|error
if confirm(): // -> Uses default "Confirm? [y/n] > " prompt
print("Confirmed!")
if confirm("Delete file? [y/n] "): // -> Custom prompt
print("File deleted")
Parsing¶
parse_int¶
Parses a string to an integer.
parse_int(_str: str) -> int|error
parse_int("42") // -> 42
parse_int("3.14") // -> Error: invalid syntax
parse_int("abc") // -> Error: invalid syntax
parse_float¶
Parses a string to a float.
parse_float(_str: str) -> float|error
parse_float("3.14") // -> 3.14
parse_float("42") // -> 42.0
parse_float("abc") // -> Error: invalid syntax
parse_json¶
Parses a JSON string into Rad data structures.
parse_json(_str: str) -> any|error
parse_json('{"name": "Alice", "age": 30}') // -> {"name": "Alice", "age": 30}
parse_json('[1, 2, 3]') // -> [1, 2, 3]
parse_json('invalid json') // -> Error: invalid JSON
Text¶
upper¶
Converts a string to uppercase. Preserves color attributes.
upper(_val: str) -> str
upper("hello") // -> "HELLO"
upper("Hello World") // -> "HELLO WORLD"
lower¶
Converts a string to lowercase. Preserves color attributes.
lower(_val: str) -> str
lower("HELLO") // -> "hello"
lower("Hello World") // -> "hello world"
replace¶
Replaces text using regex patterns. Does not preserve string color attributes.
replace(_original: str, _find: str, _replace: str) -> str
The _find
parameter is a regex pattern. The _replace
parameter can use regex capture groups like $1
.
Examples:
replace("hello world", "world", "Rad") // -> "hello Rad"
replace("Name: Charlie Brown", "Charlie (.*)", "Alice $1") // -> "Name: Alice Brown"
replace("abc123def", "\\d+", "XXX") // -> "abcXXXdef"
starts_with¶
Checks if a string starts with a given substring.
starts_with(_val: str, _start: str) -> bool
starts_with("hello world", "hello") // -> true
starts_with("hello world", "world") // -> false
ends_with¶
Checks if a string ends with a given substring.
ends_with(_val: str, _end: str) -> bool
ends_with("hello world", "world") // -> true
ends_with("hello world", "hello") // -> false
truncate¶
Truncates a string to a maximum length. Returns error if length is negative.
truncate(_str: str, _len: int) -> str|error
truncate("hello world", 5) // -> "hello"
truncate("short", 10) // -> "short"
truncate("test", -1) // -> Error: Requires a non-negative int
split¶
Splits a string using regex pattern as delimiter. Does not preserve string color attributes.
split(_val: str, _sep: str) -> list[str]
The _sep
parameter is treated as a regex pattern if valid, otherwise as literal string.
split("a,b,c", ",") // -> ["a", "b", "c"]
split("word1 word2", "\\s+") // -> ["word1", "word2"]
split("abc123def", "\\d+") // -> ["abc", "def"]
count¶
Counts the number of non-overlapping instances of substring in string.
count(_str: str, _substr: str) -> int
count("hello world", "l") // -> 3
count("banana", "na") // -> 2
count("test", "xyz") // -> 0
trim¶
Trims characters from both the start and end of a string.
trim(_subject: str, _to_trim: str = " \t\n") -> str
trim(" hello ") // -> "hello"
trim("***hello***", "*") // -> "hello"
trim("abcHELLOabc", "abc") // -> "HELLO"
trim_prefix¶
Trims characters from only the start of a string.
trim_prefix(_subject: str, _to_trim: str = " \t\n") -> str
trim_prefix(" hello ") // -> "hello "
trim_prefix("***hello***", "*") // -> "hello***"
trim_suffix¶
Trims characters from only the end of a string.
trim_suffix(_subject: str, _to_trim: str = " \t\n") -> str
trim_suffix(" hello ") // -> " hello"
trim_suffix("***hello***", "*") // -> "***hello"
reverse¶
Reverses a string or list.
reverse(_val: str|list) -> str|list
reverse("hello") // -> "olleh"
reverse([1, 2, 3, 4]) // -> [4, 3, 2, 1]
reverse("racecar") // -> "racecar"
hyperlink¶
Creates a clickable hyperlink in supporting terminals.
hyperlink(_val: any, _link: str) -> str
Converts text into a terminal hyperlink that can be clicked in supported terminals.
hyperlink("Visit Google", "https://google.com") // -> Clickable "Visit Google" link
hyperlink("localhost", "http://localhost:3000") // -> Clickable "localhost" link
hyperlink(42, "https://example.com") // -> Clickable "42" link
Colors & Attributes¶
Rad offers several functions to format text with colors and style attributes. All functions follow the same pattern:
color_or_style(_item: any) -> str
red("Hello") // -> "Hello" (in red)
blue(42) // -> "42" (in blue)
bold("Important") // -> "Important" (in bold)
Available colors:
plain
,black
,red
,green
,yellow
,blue
,magenta
,cyan
,white
,orange
,pink
Available style attributes:
bold
,italic
,underline
color_rgb¶
Applies RGB coloring to input text. RGB values must be in range [0, 255]. Not all terminals support this.
color_rgb(_val: any, *, red: int, green: int, blue: int) -> str|error
Parameters:
Parameter | Type | Description |
---|---|---|
_val |
any |
Value to apply color to |
red |
int |
Red component (0-255) |
green |
int |
Green component (0-255) |
blue |
int |
Blue component (0-255) |
RGB values must be in range [0, 255]. Not all terminals support this.
color_rgb("Hello", red=255, green=0, blue=0) // -> "Hello" (in bright red)
color_rgb(42, red=0, green=255, blue=128) // -> "42" (in green-cyan)
color_rgb("test", red=300, green=0, blue=0) // -> Error: RGB values must be [0, 255]
colorize¶
Assigns consistent colors to values from a set of possible values. The same value always gets the same color within the same set.
colorize(_val: str, _enum: str[], *, skip_if_single: bool = false) -> str
Parameters:
Parameter | Type | Description |
---|---|---|
_val |
str |
Value to colorize |
_enum |
str[] |
Set of possible values for consistent coloring |
skip_if_single |
bool = false |
Don't colorize if only one value in set |
Useful for automatically coloring table data or distinguishing values in lists.
Examples:
names = ["Alice", "Bob", "Charlie"]
colorize("Alice", names) // -> "Alice" (in consistent color)
colorize("Bob", names) // -> "Bob" (in different consistent color)
// In display blocks
names = ["Alice", "Bob", "Charlie", "David"]
display:
fields names
names:
map fn(n) colorize(n, names)
Maps¶
keys¶
Returns all keys from a map as a list.
keys(_map: map) -> list[any]
keys({"a": 1, "b": 2, "c": 3}) // -> ["a", "b", "c"]
keys({}) // -> []
values¶
Returns all values from a map as a list.
values(_map: map) -> list[any]
values({"a": 1, "b": 2, "c": 3}) // -> [1, 2, 3]
values({}) // -> []
get_default¶
Gets the value for a key in a map, or returns the default value if the key doesn't exist.
get_default(_map: map, key: any, default: any) -> any
data = {"name": "Alice", "age": 30}
get_default(data, "name", "Unknown") // -> "Alice"
get_default(data, "city", "Unknown") // -> "Unknown"
get_default(data, "age", 0) // -> 30
Random¶
rand¶
Returns a random float between 0.0 (inclusive) and 1.0 (exclusive).
rand() -> float
rand() // -> 0.7394832
rand() // -> 0.2847293
rand_int¶
Returns a random integer in a specified range.
rand_int(_arg1: int = 9223372036854775807, _arg2: int?) -> int
With one argument, returns random int from 0 to _arg1
(exclusive). With two arguments, returns random int from _arg1
to _arg2
(exclusive). Min must be less than max.
rand_int(10) // -> Random int from 0-9
rand_int(5, 15) // -> Random int from 5-14
rand_int(10, 5) // -> Error: min (10) must be less than max (5)
seed_random¶
Seeds the random number generator used by rand
and rand_int
.
seed_random(_seed: int) -> void
seed_random(42)
rand() // -> Same sequence every time with seed 42
rand_int(10) // -> Same sequence every time with seed 42
uuid_v4¶
Generates a random V4 UUID.
uuid_v4() -> str
uuid_v4() // -> "f47ac10b-58cc-4372-a567-0e02b2c3d479"
uuid_v7¶
Generates a random V7 UUID (time-ordered).
uuid_v7() -> str
uuid_v7() // -> "01234567-89ab-7def-8123-456789abcdef"
gen_fid¶
Generates a random flex ID (fid) - a time-ordered, URL-safe identifier.
gen_fid() -> str|error
gen_fid(*, alphabet: str?, tick_size_ms: int?, num_random_chars: int?) -> str|error
Parameters:
Parameter | Type | Description |
---|---|---|
alphabet |
str? = "[0-9][A-Z][a-z]" |
Characters to use (base-62 by default) |
tick_size_ms |
int? = 100 |
Time precision in milliseconds |
num_random_chars |
int? = 5 |
Number of random characters to append |
Defaults: alphabet
is base-62 ([0-9][A-Z][a-z]
), tick_size_ms
is 100ms, num_random_chars
is 5.
gen_fid() // -> "1a2b3c4d5e"
gen_fid(alphabet="0123456789") // -> "1234567890"
gen_fid(num_random_chars=3) // -> "1a2b3c"
Picking¶
pick¶
Presents an interactive menu for selecting from a list of options.
pick(_options: list[str], _filter: str?|list[str]?, *, prompt: str = "Pick an option") -> str
Shows a fuzzy-searchable menu. Filter can be a string or list of strings to pre-filter options.
pick(["apple", "banana", "cherry"]) // -> Interactive menu
pick(["red", "green", "blue"], "r") // -> Pre-filtered to "red", "green"
pick(["one", "two", "three"], prompt="Choose:") // -> Custom prompt
pick_kv¶
Presents an interactive menu showing keys but returns corresponding values.
pick_kv(keys: list[str], values: list[any], _filter: str?|list[str]?, *, prompt: str = "Pick an option") -> any
Displays keys in the menu but returns the value at the same index when selected.
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
pick_kv(names, ages) // -> Shows names, returns age
pick_kv(["Red", "Green"], ["#ff0000", "#00ff00"]) // -> Shows colors, returns hex
pick_from_resource¶
Loads options from a resource file and presents an interactive menu.
pick_from_resource(path: str, _filter: str?, *, prompt: str = "Pick an option") -> any
Loads data from a JSON/YAML file and presents it as selectable options. Returns the selected item(s).
pick_from_resource("servers.json") // -> Menu from file
pick_from_resource("configs.yaml", "prod") // -> Pre-filtered options
pick_from_resource("data.json", prompt="Select:") // -> Custom prompt
HTTP¶
Rad provides functions for all HTTP methods. All functions have identical signatures and return the same response format.
HTTP Functions¶
Available methods:
http_get
,http_post
,http_put
,http_patch
,http_delete
http_head
,http_options
,http_trace
,http_connect
http_method(url: str, *, body: any?, json: any?, headers: map?) -> map
Parameters:
Parameter | Type | Description |
---|---|---|
url |
str |
The target URL |
body |
any? |
Request body content (sent as-is) |
json |
any? |
Request body content (JSON-serialized) |
headers |
map? |
Map of HTTP headers - optional. Values can be strings or lists of strings |
- Body vs JSON: The
body
parameter sends content as-is using string representation, whilejson
automatically JSON-serializes the content and setsContent-Type: application/json
header only if noheaders
are provided at all. - Mutually exclusive: Cannot use both
body
andjson
parameters together - you must choose one or the other.
Response map contains:
success: bool
- Whether request succeededduration_seconds: float
- Request durationstatus_code?: int
- HTTP status code (if response received)body?: any
- Response body parsed as JSON if possible (if present)error?: str
- Error message (if request failed)
Examples:
// Simple GET request
response = http_get("https://api.example.com/users")
if response.success:
users = response.body
// POST with JSON body (automatic serialization and Content-Type header)
data = {"name": "Alice", "email": "alice@example.com"}
response = http_post("https://api.example.com/users", json=data)
// POST with raw body content (sent as-is)
response = http_post("https://api.example.com/webhook", body="raw text data")
// With custom headers
headers = {"Authorization": "Bearer token123"}
response = http_get("https://api.example.com/data", headers=headers)
// JSON with custom headers (Content-Type automatically added)
response = http_post("https://api.example.com/users", json=data, headers={"Authorization": "Bearer token123"})
// Error handling
response = http_get("https://invalid-url")
if not response.success:
print("Request failed:", response.error)
// Cannot use both body and json together - this will error:
// response = http_post("url", body="data", json={"key": "value"}) // -> Error
Math¶
abs¶
Returns the absolute value of a number.
abs(_num: int|float) -> int|float
abs(-5) // -> 5
abs(3.14) // -> 3.14
abs(-2.7) // -> 2.7
sum¶
Sums all numbers in a list.
sum(_nums: list[float]) -> float|error
sum([1, 2, 3, 4]) // -> 10.0
sum([1.5, 2.5, 3.0]) // -> 7.0
sum([]) // -> 0.0
sum([1, "text", 3]) // -> Error: requires list of numbers
round¶
Rounds a number to the specified decimal precision.
round(_num: float, _decimals: int = 0) -> int|float|error
Parameters:
Parameter | Type | Description |
---|---|---|
_num |
float |
Number to round |
_decimals |
int = 0 |
Number of decimal places (must be non-negative) |
With precision 0, returns an integer. With precision > 0, returns a float. Precision must be non-negative.
round(3.14159) // -> 3 (integer)
round(3.14159, 2) // -> 3.14 (float)
round(2.7) // -> 3 (integer)
round(3.14, -1) // -> Error: precision must be non-negative
floor¶
Rounds a number down to the next integer.
floor(_num: float) -> int
floor(1.89) // -> 1
floor(-1.2) // -> -2
floor(5.0) // -> 5
ceil¶
Rounds a number up to the next integer.
ceil(_num: float) -> int
ceil(1.21) // -> 2
ceil(-1.8) // -> -1
ceil(5.0) // -> 5
min¶
Returns the minimum value from a list of numbers.
min(_nums: list[float]) -> float|error
min([1, 2, 3, 4]) // -> 1.0
min([5.5, 2.1, 8.9]) // -> 2.1
min([]) // -> Error: cannot find minimum of empty list
min([1, "text"]) // -> Error: requires list of numbers
max¶
Returns the maximum value from a list of numbers.
max(_nums: list[float]) -> float|error
max([1, 2, 3, 4]) // -> 4.0
max([5.5, 2.1, 8.9]) // -> 8.9
max([]) // -> Error: cannot find maximum of empty list
max([1, "text"]) // -> Error: requires list of numbers
clamp¶
Constrains a value between minimum and maximum bounds.
clamp(val: float, min: float, max: float) -> float|error
Parameters:
Parameter | Type | Description |
---|---|---|
val |
float |
Value to constrain |
min |
float |
Minimum bound |
max |
float |
Maximum bound |
Returns val
if between min and max, otherwise returns the nearest bound. Min must be ≤ max.
clamp(25, 20, 30) // -> 25.0
clamp(10, 20, 30) // -> 20.0
clamp(40, 20, 30) // -> 30.0
clamp(15, 30, 20) // -> Error: min must be <= max
pow¶
Raises base
to the power of exponent
. Useful for exponentiation, square roots, and cube roots.
pow(base: float, exponent: float) -> float
pow(2, 3) // -> 8
pow(4, 0.5) // -> 2.0 (square root)
pow(8, 1/3) // -> 2.0 (cube root)
pow(2, -2) // -> 0.25
pow(-2, 3) // -> -8
Hashing & Encode/Decode¶
hash¶
Generates a hash of the input text using various algorithms.
hash(_val: str) -> str
hash(_val: str, *, algo: ["sha1", "sha256", "sha512", "md5"] = "sha1") -> str
Parameters:
Parameter | Type | Description |
---|---|---|
_val |
str |
Text to hash |
algo |
["sha1", "sha256", "sha512", "md5"] = "sha1" |
Hashing algorithm to use |
The default sha1
is not cryptographically secure. Use sha256
or sha512
for security.
hash("hello world") // -> "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
hash("hello world", algo="sha256") // -> "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
hash("sensitive data", algo="sha512") // -> Long SHA-512 hash
encode_base64¶
Encodes text to Base64 format.
encode_base64(_content: str) -> str
encode_base64(_content: str, *, url_safe: bool = false, padding: bool = true) -> str
Parameters:
Parameter | Type | Description |
---|---|---|
_content |
str |
Text to encode |
url_safe |
bool = false |
Replace +/ with -_ for URL-safe encoding |
padding |
bool = true |
Include = padding characters |
Use url_safe=true
to replace +/
with -_
for URL-safe encoding. Use padding=false
to omit =
padding.
encode_base64("Hello World") // -> "SGVsbG8gV29ybGQ="
encode_base64("Hello World", url_safe=true) // -> URL-safe version
encode_base64("Hello World", padding=false) // -> "SGVsbG8gV29ybGQ"
decode_base64¶
Decodes Base64 text back to original string.
decode_base64(_content: str) -> str|error
decode_base64(_content: str, *, url_safe: bool = false, padding: bool = true) -> str|error
Parameters:
Parameter | Type | Description |
---|---|---|
_content |
str |
Base64 text to decode |
url_safe |
bool = false |
Expect URL-safe encoding (-_ instead of +/ ) |
padding |
bool = true |
Expect padding characters (= ) |
Settings must match those used for encoding.
encoded = encode_base64("Hello World")
decoded = decode_base64(encoded) // -> "Hello World"
// URL-safe decoding
url_encoded = encode_base64("test", url_safe=true)
decoded = decode_base64(url_encoded, url_safe=true)
// Error handling
result = decode_base64("invalid base64!")
if result.error:
print("Decode failed:", result.error)
encode_base16¶
Encodes text to Base16 (hexadecimal) format.
encode_base16(_content: str) -> str
encode_base16("Hello") // -> "48656c6c6f"
encode_base16("ABC") // -> "414243"
decode_base16¶
Decodes Base16 (hexadecimal) text back to original string.
decode_base16(_content: str) -> str|error
decode_base16("48656c6c6f") // -> "Hello"
decode_base16("414243") // -> "ABC"
// Error handling
result = decode_base16("invalid hex")
if result.error:
print("Invalid hex string")
System & Files¶
exit¶
Exits the script with the given exit code.
exit(_code: int|bool = 0) -> void
exit() // -> Exits with code 0
exit(1) // -> Exits with code 1
exit(true) // -> Exits with code 1 (bool conversion)
exit(false) // -> Exits with code 0 (bool conversion)
read_file¶
Reads the contents of a file.
read_file(_path: str, *, mode: ["text", "bytes"] = "text") -> map|error
Parameters:
Parameter | Type | Description |
---|---|---|
_path |
str |
Path to the file to read |
mode |
["text", "bytes"] = "text" |
Read as UTF-8 text or raw bytes |
In text mode, decodes as UTF-8 and returns a string. In bytes mode, returns a list of integers.
Return map contains:
size_bytes: int
- File size in bytescontent: str|list[int]
- File contents (type depends on mode)
Examples:
// Read text file
result = read_file("config.txt")
if result.success:
content = result.content // -> string
// Read binary file
result = read_file("image.png", mode="bytes")
if result.success:
bytes = result.content // -> list[int]
// Handle errors
result = read_file("missing.txt")
if not result.success:
print("Error:", result.error)
write_file¶
Writes content to a file. Creates the file if it doesn't exist.
write_file(_path: str, _content: str, *, append: bool = false) -> map|error
Parameters:
Parameter | Type | Description |
---|---|---|
_path |
str |
Path where to write the file |
_content |
str |
Content to write |
append |
bool = false |
Append to existing content instead of overwriting |
By default overwrites the file. Use append=true
to append to existing content.
Return map contains:
bytes_written: int
- Number of bytes writtenpath: str
- Full path to the written file
Examples:
// Write new file
result = write_file("output.txt", "Hello world")
print("Wrote", result.bytes_written, "bytes")
// Append to existing file
write_file("log.txt", "\nNew entry", append=true)
// Error handling
result, err = write_file("/readonly/file.txt", "data")
if err:
print("Write failed:", err.msg)
get_path¶
Gets information about a file or directory path.
get_path(_path: str) -> map
Always returns:
exists: bool
- Whether the path existsfull_path: str
- Absolute path
When path exists, also returns:
base_name?: str
- File/directory namepermissions?: str
- Permission string (e.g., "rwxr-xr-x")type?: str
- Either "file" or "dir"size_bytes?: int
- File size (only for files)
Examples:
info = get_path("config.txt")
if info.exists:
print("File size:", info.size_bytes, "bytes")
print("Type:", info.type)
else:
print("File not found")
find_paths¶
Returns a list of all paths under a directory.
find_paths(_path: str) -> list[str]|error
find_paths(_path: str, *, depth: int = -1, relative: ["target", "cwd", "absolute"] = "target") -> list[str]|error
Parameters:
Parameter | Type | Description |
---|---|---|
_path |
str |
Directory to search |
depth |
int = -1 |
Max depth to search (-1 for unlimited) |
relative |
["target", "cwd", "absolute"] = "target" |
How to format returned paths |
"target"
- Relative to input path (default)"cwd"
- Relative to current directory"absolute"
- Full absolute paths
Examples:
// Find all files in directory
paths = find_paths("src/")
for path in paths:
print(path) // -> "file1.txt", "subdir/file2.txt", etc.
// Limit depth
paths = find_paths("src/", depth=1) // -> Only direct children
// Get absolute paths
paths = find_paths("src/", relative="absolute")
get_env¶
Retrieves the value of an environment variable.
get_env(_var: str) -> str
Returns the environment variable value, or empty string if not set.
home_dir = get_env("HOME") // -> "/Users/username"
api_key = get_env("API_KEY") or "default" // -> Uses default if not set
missing = get_env("NONEXISTENT") // -> ""
delete_path¶
Deletes a file or directory at the specified path.
delete_path(_path: str) -> bool
Returns true
if the path was successfully deleted, false
if it didn't exist or couldn't be deleted.
delete_path("temp.txt") // -> true (if file existed and was deleted)
delete_path("missing.txt") // -> false (file didn't exist)
delete_path("directory/") // -> true (if directory existed and was deleted)
get_rad_home¶
Returns Rad's home directory.
get_rad_home() -> str
home = get_rad_home() // -> "/Users/username/.rad" or $RAD_HOME
get_args¶
Returns the raw command-line arguments passed to the script.
get_args() -> list[str]
Returns all arguments after the script name. Unlike parsed args, this gives you raw access to all arguments.
// If script was called: rad myscript.rad arg1 arg2 --flag
args = get_args() // -> ["./myscript.rad", "arg1", "arg2", "--flag"]
error¶
Creates an error object with the given message.
error(_msg: str) -> error
err = error("Something went wrong")
return err // -> Script will exit with this error message
Home & Stash¶
get_rad_home
¶
Returns the path to rad's home folder on the user's machine.
get_rad_home() -> string
Return Values
Defaults to $HOME/.rad
, or $RAD_HOME
if it's defined.
get_stash_dir
¶
Returns the full path to the script's stash directory, with the given subpath if specified.
Requires a stash ID to have been defined.
get_stash_dir(subpath: string?) -> string
Return Values
- Without subpath defined:
<rad home>/stashes/<stash id>
- With subpath defined:
<rad home>/stashes/<stash id>/<subpath>
load_state
¶
Loads the script's stashed state. Creates it if it doesn't already exist.
Requires a stash ID to have been defined.
load_state() -> map, bool
Return Values
map
containing the saved state. Starts empty, before anything is saved to it.bool
representing if the state existed before the load, or if it was just created.
save_state¶
Saves the script's state to persistent stash storage.
save_state(_state: map) -> error?
state = {"counter": 42, "last_run": now().date}
save_state(state)
print("State saved")
load_stash_file¶
Loads a file from the script's stash directory, creating it with default content if it doesn't exist.
load_stash_file(_path: str, _default: str = "") -> map|error
Return map contains:
full_path: str
- Full path to the filecreated: bool
- Whether the file was just createdcontent?: str
- File contents (if successfully loaded)
result = load_stash_file("config.txt", "default config")
if result.success:
if result.created:
print("Created new config file")
content = result.content
write_stash_file¶
Writes content to a file in the script's stash directory.
write_stash_file(_path: str, _content: str) -> error?
write_stash_file("log.txt", "Script executed at " + now().time)
write_stash_file("data/results.json", json_data)
print("Data saved to stash")
Time¶
now¶
Returns the current time with various accessible formats.
now(*, tz: str = "local") -> map|error
Parameters:
Parameter | Type | Description |
---|---|---|
tz |
str = "local" |
Timezone (e.g., "UTC", "America/Chicago") |
Map values:
Accessor | Description | Type | Example |
---|---|---|---|
.date |
Current date YYYY-MM-DD | string | 2019-12-13 |
.year |
Current calendar year | int | 2019 |
.month |
Current calendar month | int | 12 |
.day |
Current calendar day | int | 13 |
.hour |
Current clock hour (24h) | int | 14 |
.minute |
Current minute of the hour | int | 15 |
.second |
Current second of the minute | int | 16 |
.time |
Current time in "hh:mm:ss" format | string | 14:15:16 |
.epoch.seconds |
Seconds since 1970-01-01 00:00:00 UTC | int | 1576246516 |
.epoch.millis |
Millis since 1970-01-01 00:00:00 UTC | int | 1576246516123 |
.epoch.nanos |
Nanos since 1970-01-01 00:00:00 UTC | int | 1576246516123456789 |
Examples:
time = now()
print("Current date:", time.date) // -> "2024-04-05"
print("Current time:", time.time) // -> "14:30:25"
print("Year:", time.year) // -> 2024
// Use epoch for timestamps
timestamp = now().epoch.seconds
print("Timestamp:", timestamp) // -> 1712345678
// Different timezone
utc_time = now(tz="UTC")
print("UTC time:", utc_time.time) // -> Time in UTC
parse_epoch¶
Parses a Unix epoch timestamp into various time formats.
parse_epoch(_epoch: int) -> map|error
parse_epoch(_epoch: int, *, tz: str = "local") -> map|error
parse_epoch(_epoch: int, *, unit: ["auto", "seconds", "milliseconds", "microseconds", "nanoseconds"] = "auto") -> map|error
parse_epoch(_epoch: int, *, tz: str = "local", unit: ["auto", "seconds", "milliseconds", "microseconds", "nanoseconds"] = "auto") -> map|error
Parameters:
Parameter | Type | Description |
---|---|---|
_epoch |
int |
Unix epoch timestamp |
tz |
str = "local" |
Timezone (e.g., "UTC", "America/Chicago") |
unit |
["auto", "seconds", "milliseconds", "microseconds", "nanoseconds"] = "auto" |
Timestamp unit (auto-detects by default) |
Converts an epoch timestamp to the same format as now()
. Auto-detects units from digit count, or specify
explicitly.
Examples:
// Parse seconds epoch (auto-detected)
time = parse_epoch(1712345678)
print(time.date, time.time) // -> "2024-04-05 22:01:18"
// Parse milliseconds with timezone
time = parse_epoch(1712345678123, tz="America/Chicago")
print(time.hour) // -> Hour in Chicago timezone
// Explicit unit specification
time = parse_epoch(1712345678000, unit="milliseconds")
// Error handling
time, err = parse_epoch(1712345678, tz="Invalid/Timezone")
if err:
print("Invalid timezone:", err.msg)