Examples on this page may reference functions from other stdlib
modules without showing explicit (import ...) statements.
In the REPL or your own code, you will need to import non-prelude
modules before using their exports — see Importing modules.
Special forms are expressions with evaluation rules
that differ from normal function calls – for example, if
does not evaluate all its arguments, and define binds a
name rather than passing it as a value. They are handled directly by the
compiler and cannot be redefined or passed as values.
quote – Return expr
without evaluating it. The shorthand 'expr is
equivalent.if – Evaluate then or
else based on test truthiness.define – Bind a
name in the current lexical environment.set! – Update an
existing binding in the current environment chain.lambda – Create an
anonymous function with lexical scope.begin – Evaluate
expressions in sequence and return the final result.defmacro – Define
a macro that transforms code before evaluation.quasiquote –
Build code/data templates with selective evaluation. The shorthand
`expr is equivalent.unquote – Evaluate
expr inside a quasiquote template. Within a template, the shorthand
,expr is equivalent.unquote-splicing
– Splice list elements into a quasiquoted list. Within a quasiquote
template, the shorthand ,@expr is equivalent.and – Short-circuit
logical conjunction.or – Short-circuit
logical disjunction.while – Repeatedly
evaluate body while condition remains truthy.delay – Create a
promise that delays evaluation of expr until forced.import – Load a
module and bind it as a first-class value. By default,
(import name) binds the module environment to the symbol
name for qualified access via name/sym. Use
:refer to bring specific exports (or all exports) into
scope unqualified. Use :as to alias the module
binding.module – Define a
module with explicit exports. A named module registers itself in the
module registry. A nameless module derives its name from the source
file. export-all exports all non-private definitions; add
:re-export to also re-export imported symbols.Anything not in this list is a function or macro, whether built-in, standard library, user-defined, or inherited from R. Unlike special forms, these are ordinary values and can be passed around, stored in variables, and so on.
Certain built-in functions are implemented in R (R/engine.R)
rather than in Arl source modules. These are low-level primitives that
need direct access to engine internals — cons-cell operations, the macro
expander, the evaluator, promise handling, and documentation helpers.
They are always available, even when the stdlib modules are not loaded
(Engine$new(load_prelude = FALSE)).
| Category | Functions |
|---|---|
| Arithmetic | +, *, -, / |
| Comparison | <, <=, >, >=, =, ==, !=, not |
| List and Pair Predicates | pair? |
| List Operations | car, cdr, cons |
| Evaluation | eval, read, write, load, r-eval |
| Documentation | help, doc!, doc |
| Macro Utilities | capture, gensym, macro?, macroexpand |
| Promises (Lazy Evaluation) | promise?, force, promise-expr |
| Environment Introspection | toplevel-env,
builtins-env, current-env |
| Module Introspection | module-ref, module?, namespace?, module-exports, module-name |
These builtins are documented alongside the stdlib functions they relate to in the individual reference pages below.
Because Arl compiles to R and its environment chain ultimately
parents to R’s baseenv(), every function in base R is
available in Arl without any import or special syntax. This is not just
interop glue — many common operations you will use day-to-day come
directly from R rather than from Arl’s own builtins or stdlib.
When you write (max 1 2 3) in Arl, the compiler emits an
R call to max(). There is no Arl wrapper — R’s own
max function runs directly. The same is true for hundreds
of base R functions. They work because R’s baseenv() sits
at the bottom of the environment chain, so any name not shadowed by an
Arl builtin, stdlib export, or user definition resolves to R’s
version.
Here are some examples of base R functions that are used routinely in Arl code and are not redefined — R’s own implementations run directly:
| Category | Examples |
|---|---|
| Math | max, min, sum,
prod |
| Vectors | c, length, seq,
seq_len, seq_along, rep,
rev, unique, which |
| Predicates | is.null, is.na, is.numeric,
is.character, is.logical,
is.function, is.list,
is.environment |
| Coercion | as.numeric, as.character,
as.logical, as.integer,
as.double, as.list |
| Strings | paste, paste0, sprintf,
nchar, substr, sub,
gsub, grepl, toupper,
tolower, trimws, strsplit |
| Data structures | list, vector, matrix,
data.frame, names, attr,
attributes |
| Accessors | $, [, [[, @ |
| Apply family | lapply, sapply, vapply,
mapply, tapply, do.call |
| I/O | cat, message, warning,
stop, readLines, writeLines,
readRDS, saveRDS |
| Environment | environment, new.env,
parent.env, exists, assign,
ls, rm |
This is far from exhaustive — any function in R’s base package works in Arl the same way.
Arl intentionally redefines some R names with its own versions. The most important are the operators:
+, -,
*, /): Arl’s versions are variadic, so
(+ 1 2 3 4) works. R’s + is binary.<, <=,
>, >=): Arl’s versions chain, so
(< 1 2 3) means “1 < 2 and 2 < 3”. R’s
< compares two vectors.=, ==,
!=): Arl’s versions are NULL-safe and variadic. R’s
= is assignment, not comparison.!): Arl uses not
and the special forms and/or.if, while,
for): These are Arl special forms or macros with Lisp-style
syntax.The stdlib also shadows some base R function names with Lisp-flavored versions:
abs, sqrt,
exp, log, floor,
ceiling, round): Arl’s versions are thin
wrappers that add documentation and integrate with the help system;
behavior is the same.append,
sort, reverse): Arl’s versions work on both R
lists and cons-cell pair lists, with Lisp-style semantics.print,
format, system): Arl’s versions add Lisp-style
formatting or Arl-specific behavior.get, identity,
subset, transform, try): Arl
provides its own implementations of these with Arl-specific
semantics.When you need R’s original, use the base:: namespace
prefix:
(base::sort (c 3 1 2)) ; R's vector sort, not Arl's list sort
(base::identity (list 1 2)) ; R's identity, not Arl's
Arl’s environment chain parents to R’s baseenv(),
not to .GlobalEnv. But R’s default
packages — stats, utils,
grDevices, graphics, datasets,
and methods — are also attached at engine startup. Their
exports are copied into a chain of environments between
builtins_env and baseenv(), mirroring how R
itself structures its search path.
This means functions like median, head,
lm, plot, rgb, and data like
iris and mtcars work without any prefix:
(median (c 1 2 3 4 5))
(head mtcars 3)
(lm (~ mpg cyl) :data mtcars)
The set of attached packages is controlled by R’s
defaultPackages option (see ?options). Users
can customize it by setting the R_DEFAULT_PACKAGES
environment variable before starting R — for example,
R_DEFAULT_PACKAGES="" disables all default packages,
leaving only baseenv().
For packages not in the default set, use the
:: prefix:
(jsonlite::fromJSON "{\"a\": 1}")
(httr::GET "https://example.com")
See R Interop and Data Workflows for
more on calling R functions, using keyword arguments, formulas, and
r-eval.
In addition to built-in functions, Arl has a standard
library written in Arl (inst/arl/*.arl). These
stdlib modules provide various features: list operations, math, strings,
control flow, and everything else. Modules are loaded in dependency
order (each module declares its dependencies with
(import ...) and is loaded after the modules it
imports).
For the full, per-function reference, see the individual stdlib reference pages:
Prelude modules are loaded automatically by
Engine$new(). Non-prelude modules (like math,
looping, sort, strings,
dict, set, io, etc.) require
explicit (import ...). The import form is also
needed inside your own modules (where you start with an empty scope) and
when working with a bare engine
(Engine$new(load_prelude = FALSE)):
; Import non-prelude modules
(import math) ; inc/dec/abs/min/max/floor/ceiling/round/square/...
(import looping) ; do-list/loop/recur/until
(import sort) ; sort/sort-by
(import strings) ; str/string-join/string-split/...
From R, you can create an engine with the stdlib already loaded:
Evaluation, macro utilities, R interop helpers, and assertions.
license, error, warn, identity, values, values?, call-with-values,
funcall, r-call, get, unbind-variable,
run, macroexpand-1, macroexpand-all,
suppressWarnings,
suppressMessages,
with, within, subset, transform, substitute, assert, assert-equal, assert-true, assert-false, assert-eq, assert-error, assert-no-error,
+, *, -, /, <, <=, >, >=, =, ==, !=, not, eval, read, write, help, load, capture, gensym, macro?, macroexpand, promise?, force, promise-expr, r-eval, toplevel-env, builtins-env, current-env, doc!, doc, module-ref, module?, namespace?, module-exports, module-name
Modules: core.arl,
r-interop.arl,
assert.arl,
and builtins
Type predicates, numeric type hierarchy, structural and identity equality, S3-style dispatch, and type conversions.
list?, list-or-pair?, null?, nil?, symbol?, keyword?, number?, string?, vector?, true?, false?, boolean?, fn?, callable?, procedure?, environment?, is-refclass?, atom?, empty?, type-of, real?, complex?, rational?, exact?, inexact?, integer?, natural?, finite?, infinite?, nan?, even?, odd?, zero?, positive?, negative?, non-negative?, non-positive?, identical?, eq?, eqv?, equal?, equal?.default,
equal?.environment,
equal?.list, env-equal?, list-equal?, s3-type, check-s3-type-match,
use-method, set-method!, symbol->string,
string->symbol,
->symbol, ->number, ->list, ->vector, ->integer, ->double, ->complex, exact->inexact,
inexact->exact,
pair?
Modules: types.arl,
equality.arl,
conversions.arl,
and builtins
Conditionals, binding forms, looping, threading macros, continuations, and error handling.
when, unless, cond, case, try, try-catch, call-cc, call-with-current-continuation,
pattern-symbols,
destructuring-bind,
let, let*, letrec, when-let, if-let, until, do-list, loop, recur, ->, ->>, as->, some->, some->>, cond->, cond->>
Modules: control.arl,
binding.arl,
looping.arl,
threading.arl
List construction, accessors, association lists, sequence helpers, and sorting.
call, caar, cadr, cdar, cddr, caaar, caadr, cadar, caddr, cdaar, cdadr, cddar, cdddr, cadddr, cddddr, list*, append, reverse, first, second, third, fourth, rest, last, nth, assoc, assoc-by-equal?,
assoc-by-identical?,
assoc-by-==,
assq, assv, rassoc, rassoc-by-equal?,
range, iota, make-list, list-ref, list-tail, take, drop, take-while, drop-while, partition, flatten, repeatedly, repeat, zip, member, contains?, length=, length>, length<, find, distinct, split-at, split-with, interpose, partition-by, list-sort, sort-by, merge-sorted, stable-sort, car, cdr, cons
Modules: list.arl,
sequences.arl,
sort.arl,
and builtins
String manipulation, file and console I/O, environment access, and display formatting.
string-join, string-split,
trim, string-format,
string-contains?,
string-match?,
string-find,
string-replace,
string-replace-all,
string-append,
->string,
char-at, string-ref, string-slice,
string-length,
string-upcase,
string-downcase,
string-titlecase,
string<?,
string>?,
string=?, string<=?,
string>=?,
string->list,
list->string,
number->string,
string->number,
string-prefix?,
string-suffix?,
string-empty?,
string-repeat,
read-line, read-file, read-lines, write-file, write-lines, append-file, file-exists?,
newline, read-from-string,
write-string,
file-size, file-modified-time,
file-delete,
directory-exists?,
directory-list,
directory-delete,
getenv, setenv, system-output,
exit, format-value,
display, println, string-concat,
trace
Modules: strings.arl,
io.arl,
display.arl
Dictionaries, sets, and struct definitions for structured data.
dict, hash, dict?, dict-get, dict-set, dict-remove,
dict-keys, dict-values,
dict-has?,
dict-merge,
dict-update,
dict-map, dict-filter,
dict-for-each,
dict->alist,
alist->dict,
set, set?, set-add, set-remove, set-contains?,
set-union, set-intersection,
set-difference,
set->list,
list->set,
set-size, set-map, set-filter, defstruct
Modules: dict.arl,
set.arl,
struct.arl
Mapping, filtering, folding, function composition, and logical combinators.
map, mapcat, filter, remove, reduce, foldl, foldr, every?, any?, complement, compose, partial, curry, juxt, constantly, iterate, iterate-until,
memoize, for-each, count, map-indexed, group-by, frequencies, not, xor
Modules: functional.arl,
logic.arl
Arithmetic, comparison, rounding, trigonometry, number theory, and complex number utilities.
%, inc, dec, clamp, within?, signum, expt, quotient, remainder, modulo, gcd, lcm, make-rectangular,
make-polar, real-part, imag-part, magnitude, angle
Modules: math.arl
Built-in functions are defined in R/engine.R.
The Arl stdlib modules are organized by topic in inst/arl/
(each file defines a module). The engine loads these modules in
dependency order when initializing.
core.arllist.arltypes.arl
(type predicates, numeric type hierarchy)logic.arl
(logical operations)conversions.arl
(type conversions)equality.arl
(equality and S3 dispatch)control.arlfunctional.arlsequences.arlsort.arlstruct.arlthreading.arlbinding.arllooping.arldict.arlmath.arlset.arlstrings.arldisplay.arlio.arlassert.arlr-interop.arlIf you’re looking for implementation details, these files are the source of truth for the stdlib definitions.