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
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'expris 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`expris equivalent. -
unquote– Evaluate expr inside a quasiquote template. Within a template, the shorthand,expris equivalent. -
unquote-splicing– Splice list elements into a quasiquoted list. Within a quasiquote template, the shorthand,@expris 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 symbolnamefor qualified access vianame/sym. Use:referto bring specific exports (or all exports) into scope unqualified. Use:asto 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-allexports all non-private definitions; add:re-exportto 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.
Built-in functions
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.
Inherited R functions
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.
What “inherited” means
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.
Examples of commonly used inherited functions
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.
When Arl shadows R
Arl intentionally redefines some R names with its own versions. The most important are the operators:
-
Arithmetic (
+,-,*,/): Arl’s versions are variadic, so(+ 1 2 3 4)works. R’s+is binary. -
Comparison (
<,<=,>,>=): Arl’s versions chain, so(< 1 2 3)means “1 < 2 and 2 < 3”. R’s<compares two vectors. -
Equality (
=,==,!=): Arl’s versions are NULL-safe and variadic. R’s=is assignment, not comparison. -
Logical (
!): Arl usesnotand the special formsand/or. -
Control flow (
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:
-
Math wrappers (
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. -
List operations (
append,sort,reverse): Arl’s versions work on both R lists and cons-cell pair lists, with Lisp-style semantics. -
I/O and display (
print,format,system): Arl’s versions add Lisp-style formatting or Arl-specific behavior. -
Other (
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:
Beyond base: R’s default packages
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:
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:
See R Interop and Data Workflows for
more on calling R functions, using keyword arguments, formulas, and
r-eval.
Standard library
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:
- Standard Library: Core, R Interop, and Testing
- Standard Library: Types, Equality, and Conversions
- Standard Library: Control Flow and Macros
- Standard Library: Lists and Sequences
- Standard Library: Strings, Display, and I/O
- Standard Library: Collections and Data Structures
- Standard Library: Higher-Order Functions
- Standard Library: Math and Numeric Functions
Importing modules
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:
Core, R Interop, and Testing
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
Types, Equality, and Conversions
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
Control Flow and Macros
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
Lists and Sequences
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
Strings, Display, and I/O
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
Collections and Data Structures
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
Higher-Order Functions
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
Math and Numeric Functions
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
Source files
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.arl-
types.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.arl
If you’re looking for implementation details, these files are the source of truth for the stdlib definitions.