On this page:
2.1 Syntax and Evaluation Model
2.2 Binding and Control Forms
2.2.1 Expression Forms
lambda
let
let*
letrec
if
and
or
when
unless
cond
else
begin
quote
quasiquote
unquote
unquote-splicing
quote-syntax
quote-module-path
2.2.2 Definition Forms
define
define-syntax
struct
include
require
provide
module+
2.3 Booleans
boolean?
not
eq?
equal?
2.4 Numbers
integer?
+
-
*
quotient
remainder
modulo
=
<
<=
>
>=
bitwise-ior
bitwise-and
bitwise-xor
bitwise-not
2.5 Pairs and Lists
pair?
null?
list?
cons
car
cdr
list
list*
append
reverse
length
list-ref
list-set
list-tail
caar
cadr
cdar
cddr
map
for-each
foldl
andmap
ormap
filter
sort
member
assoc
remove
2.6 Strings
string?
string
string-length
string-ref
substring
string=?
string-ci=?
string<?
string-u32-ref
string->integer
string-sha256
char
string-split
string-join
string-trim
string-tree?
2.7 Symbols
symbol?
symbol->string
string->symbol
string->uninterned-symbol
2.8 Hash Tables (Persistent Maps)
hash?
hash
hash-ref
hash-set
hash-remove
hash-keys
hash-count
hash-keys-subset?
2.9 Procedures
procedure?
apply
call/  cc
call/  prompt
continuation-prompt-available?
2.10 Paths
path-string?
relative-path?
build-raw-path
build-path
split-path
explode-path
simple-form-path
find-relative-path
path-only
file-name-from-path
path->complete-path
path-replace-extension
at-source
2.11 Opaque Records
opaque
opaque-ref
2.12 Variables
variable?
variable
variable-set!
variable-ref
2.13 Modules and Evaluation
module-path?
build-module-path
module->hash
dynamic-require
kernel-eval
kernel-env
2.14 Void
void?
void
2.15 Reading and Writing Objects
string-read
~v
~a
~s
display
displayln
error
alert
arity-error
arg-error
2.16 Syntax Objects
identifier?
syntax-e
syntax->datum
datum->syntax
bound-identifier=?
syntax-error
bad-syntax
misplaced-syntax
duplicate-identifier
context-consumer
context-consumer?
2.17 Files, Streams, and Processes
handle?
fd-open-input
fd-open-output
:  error
:  truncate
:  must-truncate
:  append
:  update
:  can-update
fd-close
fd-read
fd-write
fd-poll
fd-terminal?
fd-valid?
file->string
display-to-file
eof
cleanable-file
cleanable-cancel
process
process-wait
process-status
find-executable-path
string->shell
shell->strings
2.18 Filesystem
stat
ls
ls*
rm
rm*
mv
mkdir
mkdir-p
rmdir
symlink
readlink
cp
:  no-replace-mode
cp*
file-exists?
directory-exists?
link-exists?
2.19 Run Time Configuration
runtime-env
system-type
current-time
dump-image-and-exit
exit
suspend-signal
resume-signal
8.12

2 Zuo Base Language🔗ℹ

 #lang zuo
 #lang zuo/base

The zuo language is Zuo’s default language. It’s meant to be familiar to Racket programmers, and the description here leans heavily on comparisons and the Racket documentation, for now. Zuo forms and functions tend use traditional Racket names, even when a different choice might be made in a fresh design, and even when the Zuo construct is not exactly the same. Filesystem operations, however, tend to use the names of Unix programs, which are much shorter than Racket’s long names.

The zuo/base language includes most of the bindings from zuo, but not the ones from zuo/cmdline, zuo/build, zuo/shell, zuo/thread, zuo/glob, or zuo/config.

When using module->hash on zuo/base, zuo, or a module implemented with one of those languages, the resulting hash table includes 'dynamic-require mapped to the dynamic-require function. Getting dynamic-require that way provides a path from the primitive Zuo kernel module protocol to zuo/base module exports.

Changed in version 1.2: Added the 'dynamic-require key for zuo and related languages.

2.1 Syntax and Evaluation Model🔗ℹ

A zuo module consists of a sequence of definitions (e.g., define), macro definitions (e.g., define-syntax), imports (e.g., require), exports (e.g., provide), and expressions (e.g., 5). Loading the module first expands it, and then evaluates it. A module is loaded only once, so if a module is demanded more than once, the result of the first load is used.

The expansion process expands macro uses, loads imported modules, and evaluates macro definitions as such forms are encountered for the module body. Expansion creates a binding for each definition as encountered, but does not expand or evaluate the definition, yet. Expansion of definitions and expressions is deferred until all forms in the module body have been processed. Some expression forms have local definition contexts, which can include further imports and macro definitions, so expansion at those points nests the same two-step process as used for the module body.

Evaluation of a module evaluates its definitions and expressions (some of which may have been introduced by macro expansion) in order. Definitions bind mutually recursively within the enclosing module or definition context, and referencing a defined variable before its evaluation is an error. The value of each expression in a module body is printed using alert compiled with ~v.

A module’s provided variables and macros are made available to other modules that import it. Variables and macros that are not provided are completely inaccessible outside of the module.

There are no phases in the sense of Racket. When zuo macro expansion encounters an import, it makes all of the imported module’s exports immediately available for use in macro implementations, both variables and macros. For example, an imported macro might be used both to implement a macro body and in nearby run-time code or even run-time code generated by the macro’s expansion. The absence of a phase separation is related to the way that each module is evaluated only once, and it’s made workable in part by the absence of mutable data structures in Zuo, and in part because there is no support for compiling a zuo module and saving it separate from its instantiation in a Zuo process or saved image.

Zuo macros consume a representation of syntax that uses plain pairs, numbers, strings, etc., but with an identifier syntax object potentially in place of a symbol. Even for symbols, using a syntax object is optional; by using quote-syntax to create a syntax object, a macro can generate a term with identifiers bound at the macro’s definition site, instead of a use site’s, but the macro expander does not impose or automate that binding. See quote-syntax for more information.

2.2 Binding and Control Forms🔗ℹ

A zuo syntactic form is either a definition form or an expression form. Expressions can appear in definition contexts, but not vice versa. In descriptions of syntactic forms body ...+ refers to a context that allows definition forms, but the last form in the expansion of the definition context must be an expression form.

2.2.1 Expression Forms🔗ℹ

syntax

(lambda formals body ...+)

 
formals = (id ... [id expr] ...)
  | id
  | (id ... [id expr] ... . id)
Analogous to lambda in racket, but without keyword arguments.

syntax

(expr expr ...)

A function call, where the initial expr is not an identifier bound to a macro.

syntax

(let ([id val-expr] ...) body ...+)

(let proc-id ([id init-expr] ...) body ...+)

syntax

(let* ([id val-expr] ...) body ...+)

syntax

(letrec ([id val-expr] ...) body ...+)

Just like let, let*, and letrec in racket.

syntax

(if test-expr then-expr else-expr)

syntax

(and expr ...)

syntax

(or expr ...)

syntax

(when test-expr body ...+)

syntax

(unless test-expr body ...+)

syntax

(cond cond-clause ...)

 
cond-clause = [test-expr then-body ...+]
  | [else then-body ...+]

syntax

else

syntax

(begin expr ...+)

Just like if, and, or, when, unless, cond, else, and begin in racket, except that cond is more limited.

syntax

(quote datum)

syntax

(quasiquote datum)

syntax

unquote

syntax

unquote-splicing

syntax

(quote-syntax datum)

Analogous to quote-syntax from racket, but only identifiers have a specialized syntax-object representation in place of symbols. Tree structure in datum is represented using plain pairs, and non-identifier elements are represented with plain numbers, strings, etc.

A Zuo module’s representation starts with plain pairs and symbols, a macro procedure can receive terms containing plain symbols, and it can return a term with plain symbols. A symbol non-hygienically acquires a scope at the point where its binding is resolved or where it creates a binding.

A scope corresponds to a particular binding context. It can be a module context, an internal definition context, or a binding site for an expression form like the formals of a lambda or the right-hand side of a letrec.

An identifier syntax object created by quote-syntax closes over a binding at the point where it is created, closing over the enclosing module scope if the identifier is not (yet) bound. The closure does not change if the identifier is nested in a later quote-syntax form. Identifiers that are introduced by macros are not automatically given a scope or otherwise distinguished from identifiers that appeared as input to a macro, and a plain symbol is implicitly coerced to a syntax object only at the point where it binds or where its binding is resolved as a reference.

There is no quasisyntax, unsyntax, or unsyntax-splicing analog, since quasiquote, unquote, and unquote-splicing are already convenient enough for most purposes. To generate a fresh symbol for the output of a macro expansion, use string->uninterned-symbol.

Produces the module path of the enclosing module.

2.2.2 Definition Forms🔗ℹ

syntax

(define id expr)

(define (id . formals) body ...++)
Like define from racket, but without keyword arguments, optional arguments, or header nesting for curried functions.

syntax

(define-syntax id expr)

(define-syntax (id . formals) body ...++)
Analogous to define-syntax from racket, binds id as a macro. The value of expr must be either a procedure (of one argument) or a value constructed by context-consumer.

If expr produces a context-consumer wrapper, then when id is used for a macro invocation, the wrapped procedure receives three arguments: the macro use as syntax, a function that acts like free-identifier=?, and either #f or an inferred-name string. (In racket, free-identifier=? and syntax-local-name are implicitly parameterized over the context of a macro invocation. Explicitly providing a comparison procedure and name string to a macro implementation, instead, avoids the implicit parameterization.)

See quote-syntax for more information about the representation of syntax that a macro function consumes and produces.

syntax

(struct id (field-id ...))

Analogous to struct from racket, but defining only id as a constructor, id? as a predicate, id-field-id as an accessor for each field-id, and id-set-field-id as a functional-update operation (along the lines of struct-copy) for each field-id.

syntax

(include module-path)

Splices the content of the module identified by module-path, assuming that module-path is implemented in a language like zuo/datum.

syntax

(require spec ...)

 
spec = module-path
  | 
(only-in module-path
         maybe-renamed-id ...)
  | 
(rename-in module-path
           renamed-id ...)
     
maybe-renamed-id = id
  | renamed-id
     
renamed-id = [provided-id id]

syntax

(provide spec ...)

 
spec = id
  | (rename-out renamed-id ...)
  | (all-from-out module-path)
     
maybe-renamed-id = id
  | renamed-id
     
renamed-id = [id provided-id]
Like require and provide from racket, but a require can appear in any definition context, while provide is not allowed in submodules.

syntax

(module+ id defn-or-expr ...)

Declares a kind of submodule, roughly analogous to module+ from racket, but without allowing submodules nested in submodules.

A submodule becomes a procedure of zero arguments that is a mapped from the symbol form of id in the enclosing module’s representation as a hash table (see Zuo Module Protocol). Calling the procedure evaluates the defn-or-expr content of the submodule, where expression results are printed and the procedure’s result is (void).

When Zuo loads a starting module (see Building and Running Zuo), it checks for a main submodule and runs it if one is found.

2.3 Booleans🔗ℹ

Zuo booleans are written #t or #true and #f or #false. Any value other than #f counts as true for conditionals.

procedure

(boolean? v)  boolean?

  v : any/c

procedure

(not v)  boolean?

  v : any/c
Just like boolean? and not from racket.

procedure

(eq? v1 v2)  boolean?

  v1 : any/c
  v2 : any/c
Analogous to eq? from racket, but even small Zuo numbers are not necessarily eq? when they are =.

procedure

(equal? v1 v2)  boolean?

  v1 : any/c
  v2 : any/c
Analogous to equal? from racket.

2.4 Numbers🔗ℹ

A Zuo number corresponds to a 64-bit two’s complement representation with modular arithmetic (i.e., wraparound on overflow). It is always written in decimal form with a leading - for negative numbers.

procedure

(integer? v)  boolean?

  v : any/c
Returns #t if v is an integer, #f otherwise.

procedure

(+ z ...)  integer?

  z : integer?

procedure

(- z)  integer?

  z : integer?
(- z w ...+)  integer?
  z : integer?
  w : integer?

procedure

(* z ...)  integer?

  z : integer?

procedure

(quotient n m)  integer?

  n : integer?
  m : integer?

procedure

(remainder n m)  integer?

  n : integer?
  m : integer?

procedure

(modulo n m)  integer?

  n : integer?
  m : integer?

procedure

(= z w)  boolean?

  z : integer?
  w : integer?

procedure

(< x y)  boolean?

  x : integer?
  y : integer?

procedure

(<= x y)  boolean?

  x : integer?
  y : integer?

procedure

(> x y)  boolean?

  x : integer?
  y : integer?

procedure

(>= x y ...)  boolean?

  x : integer?
  y : integer?

procedure

(bitwise-ior n m)  integer?

  n : integer?
  m : integer?

procedure

(bitwise-and n m)  integer?

  n : integer?
  m : integer?

procedure

(bitwise-xor n m)  integer?

  n : integer?
  m : integer?

procedure

(bitwise-not n)  integer?

  n : integer?
Analogous to +, -, *, quotient, remainder, modulo, =, <, <=, >, >=, bitwise-ior, bitwise-and, bitwise-xor, and bitwise-not from racket, but on Zuo integers and sometimes constrained to two arguments.

Changed in version 1.9: Added remainder and changed modulo to match Racket.

2.5 Pairs and Lists🔗ℹ

Zuo pairs and lists work the same as in Racket with the same textual representation.

procedure

(pair? v)  boolean?

  v : any/c

procedure

(null? v)  boolean?

  v : any/c

procedure

(list? v)  boolean?

  v : any/c

procedure

(cons a d)  pair?

  a : any/c
  d : any/c

procedure

(car p)  any/c

  p : pair?

procedure

(cdr p)  any/c

  p : pair?

procedure

(list v ...)  list?

  v : any/c

procedure

(list* v ... tail)  any/c

  v : any/c
  tail : any/c

procedure

(append lst ...)  list?

  lst : list?
(append lst ... v)  any/c
  lst : list?
  v : any/c

procedure

(reverse lst)  list?

  lst : list?

procedure

(length lst)  integer?

  lst : list?

procedure

(list-ref lst pos)  any/c

  lst : pair?
  pos : integer?

procedure

(list-set lst pos v)  any/c

  lst : pair?
  pos : integer?
  v : any/c

procedure

(list-tail lst pos)  any/c

  lst : any/c
  pos : integer?
Just like pair?, null?, cons, car, cdr, list?, list*, append, reverse, list-ref, list-set, and list-tail from racket, except that list? takes time proportional to the length of the list.

procedure

(caar p)  any/c

  p : pair?

procedure

(cadr p)  any/c

  p : pair?

procedure

(cdar p)  any/c

  p : pair?

procedure

(cddr p)  any/c

  p : pair?
Just like caar, cadr, cdar, and cddr from racket.

procedure

(map proc lst ...+)  list?

  proc : procedure?
  lst : list?

procedure

(for-each proc lst)  void?

  proc : (any/c . -> . any/c)
  lst : list?

procedure

(foldl proc init lst)  any/c

  proc : (any/c any/c . -> . any/c)
  init : any/c
  lst : list?

procedure

(andmap proc lst)  any/c

  proc : (any/c . -> . any/c)
  lst : list?

procedure

(ormap proc lst)  any/c

  proc : (any/c . -> . any/c)
  lst : list?

procedure

(filter proc lst)  list?

  proc : (any/c . -> . any/c)
  lst : list?

procedure

(sort lst less-than?)  list?

  lst : list?
  less-than? : (any/c any/c . -> . any/c)
Like map, for-each, foldl, andmap, ormap, and filter from racket, but mostly restricted to a single list.

procedure

(member v lst)  (or/c pair? #f)

  v : any/c
  lst : list?

procedure

(assoc v lst)  (or/c pair? #f)

  v : any/c
  lst : list?

procedure

(remove v lst)  (or/c pair? #f)

  v : any/c
  lst : list?
Like member, assoc, and remove from racket.

2.6 Strings🔗ℹ

Zuo strings are sequences of bytes.

procedure

(string? v)  boolean?

  v : any/c

procedure

(string char ...)  string?

  char : integer?

procedure

(string-length str)  integer?

  str : string?

procedure

(string-ref str k)  integer?

  str : string?
  k : integer?

procedure

(substring str start [end])  string?

  str : string?
  start : integer?
  end : integer? = (string-length str)

procedure

(string=? str1 str2)  boolean?

  str1 : string?
  str2 : string?

procedure

(string-ci=? str1 str2)  boolean?

  str1 : string?
  str2 : string?

procedure

(string<? str1 str2)  boolean?

  str1 : string?
  str2 : string?
Analogous to string?, string, string-length, string-ref, substring, string=?, string-ci=?, and string<? from racket, or more precisely analogous to bytes?, bytes, bytes-length, bytes-ref, subbytes, bytes=?, and bytes<? (and, in principle, bytes-ci=?) from racket.

procedure

(string-u32-ref str k)  integer?

  str : string?
  k : integer?
Returns the two’s complement interpretation of four bytes in str starting at index k using the host machine’s endianness.

procedure

(string->integer str)  (or/c integer? #f)

  str : string?
Tries to parse str as an integer returning #f if that fails.

procedure

(string-sha256 str)  string?

  str : string?
Returns the SHA-256 hash of str as a 64-digit hexadecimal string.

See also file-sha256 and sha256-length.

syntax

(char str)

Expands to (string-ref str 0), where str must be a literal string of length 1.

procedure

(string-split str)  (listof string?)

  str : string?
(string-split str sep)  (listof string?)
  str : string?
  sep : string?
Breaks str into a sequence of substrings that have a non-empty separator string in between. When sep is not provided, " " is used as the separator, and empty strings are filtered from the result list. When sep is provided, empty strings are not filtered from the result list.

procedure

(string-join strs [sep])  string?

  strs : list?
  sep : string? = " "
Concatenates the strings in strs with sep between each pair of strings.

procedure

(string-trim str [edge-str])  string?

  str : string?
  edge-str : string? = " "
Removes any number of repetitions of edge-str from the start and end of str.

procedure

(string-tree? v)  boolean?

  v : any/c
Returns #t if v is a string or if it is a list where string-tree? returns #t for each element, #f otherwise. The flattened form of a string tree is a list of its strings in order. See also process and build-shell.

2.7 Symbols🔗ℹ

Zuo symbols are interned by the reader, where two interned symbols are eq? when they have the same string content. An uninterned symbol is eq? only to itself. Zuo symbols are the only kind of value that can be used as a key for a Zuo hash table.

The textual representation of symbols does not include escapes for special character, unlike the way | works in Racket. Symbols with those characters will print in a way that cannot be read back into Zuo.

procedure

(symbol? v)  boolean?

  v : any/c

procedure

(symbol->string sym)  string?

  sym : symbol?

procedure

(string->symbol str)  symbol?

  str : string?

procedure

(string->uninterned-symbol str)  symbol?

  str : string?
Analogous to symbol?, symbol->string, string->symbol, and string->uninterned-symbol from racket, but string->symbol accepts only strings that do not contain the null character.

2.8 Hash Tables (Persistent Maps)🔗ℹ

Zuo hash tables do not actually have anything to do with hashing, but they’re called that for similarity to Racket. A hash table maps symbols to other values, and updating a hash table produces a new hash table (which, internally, may share with the original).

Hash tables print in a way analogous to Racket, but there is no reader support to convert the textual form back into a hash table value.

procedure

(hash? v)  boolean?

  v : any/c

procedure

(hash key val ... ...)  hash?

  key : symbol?
  val : any/c

procedure

(hash-ref hash key)  any/c

  hash : hash?
  key : symbol?
(hash-ref hash key failure-value)  any/c
  hash : hash?
  key : symbol?
  failure-value : any/c

procedure

(hash-set hash key v)  hash?

  hash : hash?
  key : symbol?
  v : any/c

procedure

(hash-remove hash key)  hash?

  hash : hash?
  key : symbol?

procedure

(hash-keys hash)  (listof symbol?)

  hash : hash?

procedure

(hash-count hash)  integer?

  hash : hash?

procedure

(hash-keys-subset? hash1 hash2)  boolean?

  hash1 : hash?
  hash2 : hash?

Besides being constrained to symbol keys, there are two additional differences:

2.9 Procedures🔗ℹ

procedure

(procedure? v)  any/c

  v : any/c

procedure

(apply proc lst)  any/c

  proc : procedure?
  lst : list?

procedure

(call/cc proc)  any/c

  proc : (any/c . -> . any/c)

procedure

(call/prompt proc tag)  any/c

  proc : (-> any/c)
  tag : symbol?

procedure

(continuation-prompt-available? tag)  boolean?

  tag : symbol?
Like procedure?, apply, call/cc, call-with-continuation-prompt, and continuation-prompt-available? from racket, but apply accepts only two arguments, call/cc has no prompt-tag argument and captures up to the nearest enclosing prompt of any tag, call/prompt expects a symbol for a prompt tag, and continuation-prompt-available? checks only whether the immediately enclosing prompt has the given tag.

2.10 Paths🔗ℹ

A path string is a string that is not empty and contains no null bytes.

procedure

(path-string? v)  boolean?

  v : any/c
Returns #t if v is a path string, #f otherwise.

procedure

(relative-path? path)  boolean?

  path : path-string?
Returns #t if path is a relative path, #f otherwise.

procedure

(build-raw-path base rel ...)  path-string?

  base : path-string?
  rel : path-string?
Combines base path (absolute or relative) with relative rel paths, adding path separators as needed.

procedure

(build-path base rel ...)  path-string?

  base : path-string?
  rel : path-string?
Similar to build-raw-path, but any "." or ".." element in a rel is syntactically eliminated, and separators in rel are normalized. Removing ".." elements may involve syntactically resolving elements at the end of base. Furthermore, if base is at some point reduced to ".", it will not be prefixed on the result.

procedure

(split-path path)  pair?

  path : path-string?
Splits path into its directory (if any) and a final element components. If path has only a single element, the car of the result is #f, and the cdr is path unchanged; otherwise, the final element is returned without trailing separators.

procedure

(explode-path path)  (listof path-string?)

  path : path-string?
Split path into a list of individual path elements by repeatedly applying split-path.

procedure

(simple-form-path path)  path-string?

  path : path-string?
Syntactically normalizes path by eliminating "." and ".." elements (except for ".." at the start that cannot be eliminated), removing redundant path separators, and making all path separators the platform default (on Windows).

procedure

(find-relative-path base path)  path-string?

  base : path-string?
  path : path-string?
Attempts to find a path relative to base that accesses the same file or directory as path. Both base and path must be normalized in the sense of simple-form-path, otherwise "." and ".." elements are treated as normal path elements. Assuming that base and path are normalized, the result is always normalized.

The result path depends on whether base and path are relative or absolute:

procedure

(path-only path)  path-string?

  path : path-string?
Returns path without its final path element in the case that path is not syntactically a directory. If path has only a single, non-directory path element, "." is returned. If path is syntactically a directory, then path is returned unchanged.

procedure

(file-name-from-path path)  (or/c path-string? #f)

  path : path-string?
Returns the last element of path in the case that path is not syntactically a directory, #f otherwise.

procedure

(path->complete-path path)  path-string?

  path : path-string?
Returns path if it is absolute, otherwise returns (build-path (hash-ref (runtime-env) 'dir) path).

procedure

(path-replace-extension path suffix)  path-string?

  path : path-string?
  suffix : string?
Removes any . suffix from the last element of path, and then appends suffix to the end of the path. A . at the start of a path element does not count as a file suffix.

syntax

at-source

Expands to a function that acts like build-path starting from the enclosing module’s directory. That is, expands to a function roughly equivalent to

(lambda args
  (apply build-path (cons (path-only (quote-module-path))
                          args)))

If the argument to the function is an absolute path, however, the enclosing module’s directory is ignored, and the function acts simply like build-path.

2.11 Opaque Records🔗ℹ

procedure

(opaque key val)  any/c

  key : any/c
  val : any/c
Returns an opaque record that encapsulates val with access allowed via key.

procedure

(opaque-ref key v failure-val)  any/c

  key : any/c
  v : any/c
  failure-val : any/c
Returns the value encapsulated in v if it is an opaque object with access allowed via key, failure-val otherwise.

2.12 Variables🔗ℹ

A variable is a value with a name that contains another value. The contained value is initially undefined, and attempting to access the contained value before it’s set results in an error where the variable’s name is used in the error message. A variable’s contained value can be set only once.

procedure

(variable? v)  boolean?

  v : any/c
Returns #t if v is a variable, #f otherwise.

procedure

(variable name)  variable?

  name : symbol?
Creates a variable named by name and without a value until one is installed with variable-set!.

procedure

(variable-set! var val)  void?

  var : variable?
  val : any/c
Sets the value contained by var to val or errors if var already has a contained value.

procedure

(variable-ref var)  any/c

  var : variable?
Returns the value contained by var or errors if var does not yet have a contained value.

2.13 Modules and Evaluation🔗ℹ

A module path is a path string or a symbol, where a symbol must contain only the letters A-Z, a-z, 0-9, -, +, _, or /. Furthermore, / in a symbol module path cannot be at the start, end, or adjacent to another /.

procedure

(module-path? v)  boolean?

  v : any/c
Returns #t if v is a module path, #f otherwise.

procedure

(build-module-path base rel-path)  module-path?

  base : module-path?
  rel-path : path-string?
Analogous to build-path, but for module paths. The rel-path string must end with .zuo, and the characters of rel-path must be allowable in a symbol module paths, except for a . in "." and ".." elements or a .zuo suffix.

procedure

(module->hash mod-path)  hash?

  mod-path : module-path?
Loads mod-path if it has not been loaded already, and returns the hash table representation of the loaded module. See also Zuo Module Protocol.

procedure

(dynamic-require mod-path export)  any/c

  mod-path : module-path?
  export : symbol?
Like module->hash, but extracts an exported value. The module referenced by mod-path must be implemented in zuo, zuo/hygienic, or a derived compatible language.

procedure

(kernel-eval s-exp)  any/c

  s-exp : any/c
Evaluates a term as if it appeared in a zuo/kernel module (but the result does not have to be a hash table).

procedure

(kernel-env)  hash?

Returns a hash table that maps each primitive and constant name available in the body of a zuo/kernel module to its value.

2.14 Void🔗ℹ

procedure

(void? v)  boolean?

  v : any/c
Returns #t if v is the unique void value, #f otherwise.

procedure

(void v ...)  void?

  v : any/c
Accepts any number of arguments and ignores them, returning the void value.

2.15 Reading and Writing Objects🔗ℹ

procedure

(string-read str [start where])  list?

  str : string?
  start : integer? = 0
  where : any/c = #f
Reads all S-expressions in str, starting at index start and returning a list of the S-expressions (in order as they appeared in the string). The where argument, if not #f, is used to report the source of errors.

See also Zuo S-Expression Reader.

procedure

(~v v ...)  string?

  v : any/c

procedure

(~a v ...)  string?

  v : any/c

procedure

(~s v ...)  string?

  v : any/c
Like ~v, ~a, and ~s, but with no formatting options. These three format options corresponds to print style, display style, and write style, respectively.

Unlike uninterned symbols in racket, Zuo uninterned symbols format in print and write styles with #<symbol:...>. Opaque objects, handles, and variables print with #<:...> notation in all styles.

procedure

(display v)  void?

  v : any/c

procedure

(displayln v)  void?

  v : any/c
Convenience output functions that are analogous to display and displayln from racket. They use ~a and (fd-open-output 'stdout).

procedure

(error v ...)  void?

  v : any/c
Errors (and exits) after printing the vs to standard error, using an error color if standard error is a terminal.

If the first v is a string, its characters are printed followed by : . All other vs (including the first one if it’s not a string) are combined using ~v, and the resulting string’s characters are printed.

procedure

(alert v ...)  void?

  v : any/c
Prints to standard output using the same formatting rules as error, but in an alert color for terminals. This function is useful for simple logging and debugging tasks.

procedure

(arity-error name args)  void?

  name : (or/c string? #f)
  args : list?
Errors (and exits) after printing an error about name receiving the wrong number of arguments, where args are the arguments that were supplied.

procedure

(arg-error who what v)  void?

  who : symbol?
  what : string?
  v : any/c
Errors (and exits) after printing an error from who about a what expected in place of v.

2.16 Syntax Objects🔗ℹ

A syntax object combines a symbol with a binding scope, where the two are used to determine a binding when the identifier is used in a macro expansion.

procedure

(identifier? v)  boolean?

  v : any/c

procedure

(syntax-e v)  symbol?

  v : identifier?

procedure

(syntax->datum v)  any/c

  v : any/c

procedure

(datum->syntax ctx v)  any/c

  ctx : identifier?
  v : any/c

procedure

(bound-identifier=? id1 id2)  boolean?

  id1 : identifier?
  id2 : identifier?
Analogous to identifier?, syntax-e, syntax->datum, datum->syntax, and bound-identifier=? from racket. Plain symbols count as an identifier, however, and for bound-identifier=?, a symbol is equal only to itself. The datum->syntax function always just returns its second argument.

procedure

(syntax-error message stx)  void?

  message : string?
  stx : any/c
Exits as an error after printing message, : , and (~s (syntax->datum stx)).

procedure

(bad-syntax stx)  void?

  stx : any/c

procedure

(misplaced-syntax stx)  void?

  stx : any/c

procedure

(duplicate-identifier stx)  void?

  stx : any/c
Calls syntax-error with a suitable error message and stx.

procedure

(context-consumer proc)  context-consumer?

  proc : procedure

procedure

(context-consumer? v)  boolean?

  v : any/c
The context-consumer constructor wraps a procedure to indicate that it expects three arguments as a macro transformer; see define-syntax for more information. The context-consumer? predicate recognizes values produced by context-consumer.

2.17 Files, Streams, and Processes🔗ℹ

Files, input and output streams, and processes are all represented as handles.

procedure

(handle? v)  boolean?

  v : any/c
Returns #t if v is a handle, #f otherwise.

procedure

(fd-open-input filename [options])  handle?

  filename : (or/c path-string? 'stdin integer?)
  options : hash? = (hash)
Opens a file for reading, obtains a reference to standard input when filename is 'stdin, or (on Unix) obtains a reference to an existing file descriptor when filename is an integer. The result handle can be used with fd-read and closed with fd-close.

No keys are currently recognized for options, so it must be an empty hash table.

procedure

(fd-open-output filename [options])  handle?

  filename : (or/c path-string? 'stdout 'stderr integer?)
  options : hash? = (hash)

value

:error : hash?

value

:truncate : hash?

value

:must-truncate : hash?

value

:append : hash?

value

:update : hash?

value

:can-update : hash?

The fd-open-output procedure opens a file for writing, obtains a reference to standard output when filename is 'stdout, obtains a reference to standard error when filename is 'stderr, or (on Unix) obtains a reference to an existing file descriptor when filename is an integer. When opening a file, options specifies options as described below, but options must be empty for 'stdout or 'stderr. The result handle can be used with fd-write and closed with fd-close.

In options, a single key is currently recognized: 'exists. The mapping for 'exists must be one of the symbols accepted for #:exists by open-output-file from racket, but not 'replace or 'truncate/replace, and the default mapping is 'error. Any other key in options is an error.

The :error, :truncate, :must-truncate, :append, :update, and :can-update hash tables each map 'exists to the corresponding mode.

procedure

(fd-close handle)  void?

  handle : handle?
Closes the file or stream associated with handle, if it refers to an open input or output stream. Any other kind of handle triggers an error.

procedure

(fd-read handle amount)  (or/c string? eof)

  handle : handle?
  amount : (or/c integer? eof 'avail)
Reads from the input file or input stream associated with handle, erroring for any other kind of handle. The amount argument can be a non-negative integer to read up to that many bytes, eof to read all content up to an end-of-file, or 'avail where supported (on Unix) to read as many bytes as available in non-blocking mode. The result is eof if amount is not 0 or eof and if no bytes are available before an end-of-file; otherwise, it is a string containing the read bytes.

The number of bytes in the returned string can be less than amount if the number of currently available bytes is less than amount but at least one byte. The result can be an empty string only if amount is 0 or eof.

On Windows, 'avail mode is not supported for console input.

Changed in version 1.5: Report eof when available in 'avail mode.

procedure

(fd-write handle str)  void?

  handle : handle?
  str : string?
Writes the bytes of str to the output file or output stream associated with handle, erroring for any other kind of handle.

procedure

(fd-poll handles [timeout-msecs])  (or/c handle? #f)

  handles : (listof handle?)
  timeout-msecs : (or/c integer? #f) = #f
Given a list of open input and output file descriptor handles as handles, checks whether any is ready for reading or writing. If timeout-msecs is #f, fd-poll blocks until at least one is ready, and then it returns the first element of handles that is ready. If timeout-msecs is a number, then it specifies a number of milliseconds to wait; the result is #f if no handle in handles is ready before timeout-msecs milliseconds pass.

Added in version 1.1.

procedure

(fd-terminal? handle [check-ansi?])  boolean?

  handle : handle?
  check-ansi? : any/c = #f
Returns #t if the open input or output stream associated with handle is a terminal, #f otherwise. If check-ansi? is true, the result is #t only if the terminal is likely to support ANSI escape codes.

When using ANSI escapes that change the character style, consider bracketing a change and restore with suspend-signal and resume-signal to avoid leaving a terminal in a mangled state after Ctl-C.

procedure

(fd-valid? handle)  boolean?

  handle : handle?
Reports whether a file descriptor opened by appears to be a valid file descriptor, which is potentially useful after supplying an integer to fd-open-input or fd-open-output

procedure

(file->string name)  string?

  name : path-string?

procedure

(display-to-file str name [options])  void?

  str : string?
  name : path-string?
  options : hash? = (hash)
Convenience function to open name and read its content into a string or to write str as its new content.

value

eof : any/c

A constant representing an end-of-file.

procedure

(cleanable-file name)  handle?

  name : path-string?

procedure

(cleanable-cancel cleanable)  void?

  cleanable : handle?
The cleanable-file function registers name as a file to delete on any exit, including errors or termination signals, unless cleanable-cancel is called on the handle to cancel the clean-up action.

procedure

(process executable args ... [options])  hash?

  executable : path-string?
  args : string-tree?
  options : hash? = (hash)
Creates a new process to run executable with arguments as the flattened sequence args. The result is a hash table that at least contains the key 'process mapped to a handle representing the new process. The process handle can be used with process-wait and process-status.

If options is supplied, it controls the process creation and may cause additional keys to be mapped in the result. The recognized keys are as follows, and supplying an unrecognized key in options is an error:

See also shell.

Changed in version 1.1: Pipes created for a process are explicitly closed when a Zuo will terminate, and they are closed before waiting for processes to exit.

procedure

(process-wait process ...)  handle?

  process : handle?
Waits until the process represented by a process has terminated, erroring if a process is any other kind of handle. The result is the handle for a terminated process that’s one of the argument process handles; waiting again on the same handle will produce a result immediately.

procedure

(process-status process)  (or/c 'running integer?)

  process : handle?
Returns 'running if the process represented by process is still running, the exit value if the process has exited (0 normally means success), erroring for any other kind of handle.

procedure

(find-executable-path name)  (or/c path-string? #f)

  name : path-string?
Returns an absolute path to a file name, potentially by consulting the PATH environment variable. If name is an absolute path already, and if a file name exists, the name is returned as-is—except that ".exe" is added on Windows if it produces an existent path name while name by itself does not exist. Otherwise, if a file exists relative to path in PATH (with ".exe" potentially added on Windows), that file’s path is returned.

The PATH environment variable is treated as a list of :-separated paths on Unix and ;-separated paths on Windows. On Windows, the current directory is automatically added to the start of PATH.

procedure

(string->shell str)  string?

  str : string?

procedure

(shell->strings str [starts-exe?])  (listof string?)

  str : string?
  starts-exe? : any/c = #f
The string->shell function converts a string to a command-line fragment that encodes the same string. The shell->strings function takes a command-line fragment and parses it into a list of strings in the same way the shell would. On Windows, the shell parses an executable name differently than arguments in a command, so provide a true value as starts-exe? if the command-line fragment str starts with an executable name.

2.18 Filesystem🔗ℹ

procedure

(stat name [follow-links? false-on-error?])  (or/c hash? #f)

  name : path-string?
  follow-links? : any/c = #t
  false-on-error? : any/c = #f
Returns information about the file, directory, or link referenced by name. If follow-links? is #f, then when name refers to a link, information is reported about the link; otherwise, information is reported about the target of a link.

If name is a valid path but no such file, directory, or link exists, the result is #f. If accessing name encounters an error (e.g., name uses a file as a directory or permission is denied), then #f is reported instead of an error if false-on-error?. Otherwise, the hash table has similar keys and values as file-or-directory-stat from racket, but with only certain keys per platform:

The abbreviated 'type field contains 'file, 'dir, or 'link, with 'link only on Unix and only when follow-links? is #f.

procedure

(ls dir)  (listof path-string?)

  dir : path-string?
Returns a list of path strings for files in dir.

procedure

(ls* dir)  (listof path-string?)

  dir : path-string?
Like ls, but builds a path using dir for each element of the result list.

procedure

(rm name)  void?

  name : path-string?
Deletes the file or link name.

procedure

(rm* name)  void?

  name : path-string?
Deletes the file, directory, or link name, including the directory content if name refers to a directory (and not to a link to a directory). Unlike rm, it’s not an error if name does not refer to an existing file, directory, or link.

procedure

(mv name new-name)  void?

  name : path-string?
  new-name : path-string?
Renames the file, directory, or link name to new-name.

procedure

(mkdir dir)  void?

  dir : path-string?
Creates a directory dir.

procedure

(mkdir-p dir)  void?

  dir : path-string?
Creates a directory dir if it does not already exist, along with its ancestor directories.

procedure

(rmdir dir)  void?

  dir : path-string?
Deletes a directory dir.

procedure

(symlink target name)  void?

  target : path-string?
  name : path-string?
Creates a symbolic link name with the content target. This function is not supported on Windows.

procedure

(readlink name)  void?

  name : path-string?
Gets the content of a link name. This function is not supported on Windows.

procedure

(cp source destination [options])  void?

  source : path-string?
  destination : path-string?
  options : hash? = (hash)

value

:no-replace-mode : hash?

Copies the file at source to destination, replacing (or attempting to replace) destination if it exists.

On Unix, if destination does not exist, it is created with the mode (i.e., permissions) specified by 'mode in options, which must be an integer between 0 and 65535 inclusive; if 'mode is not provided, the mode of source is used. The creation-time mode can be modified by the process’s umask, but unless options maps 'replace-mode to #f, the mode is explicitly applied again to destinationwhether destination was just created or exists already, and ignoring the process’s umask. On Windows, the attributes of source are always copied to destination, and if 'mode is provided, then the file is made read only if and only if the bitwise-and of the mode value and 2 is 0.

The :no-replace-mode hash table maps 'replace-mode to #f.

Changed in version 1.6: Added the options argument and :no-replace-mode.

procedure

(cp* source destination [options])  void?

  source : path-string?
  destination : path-string?
  options : hash? = (hash)
Copies the file, directory, or link source to a corresponding new file, directory, or link destination, including the directory content if source refers to a directory (and not to a link to a directory). The options argument is passed along to individual file-copy operations.

Changed in version 1.6: Added the options argument.

procedure

(file-exists? name)  boolean?

  name : path-string?

procedure

(directory-exists? name)  boolean?

  name : path-string?

procedure

(link-exists? name)  boolean?

  name : path-string?
Uses stat to check for a file, directory, or link, respectively. If stat encounters an error (e.g., access permission), then the file, directory, or link is treated as non-existent.

2.19 Run Time Configuration🔗ℹ

procedure

(runtime-env)  hash?

Returns a hash table containing information about the current Zuo process. The hash table includes the following keys:

Changed in version 1.1: Added 'minor-version.

procedure

(system-type)  symbol?

Returns (hash-ref (runtime-env) 'system-type).

procedure

(current-time)  pair?

Reports the current wall-clock time as a pair: seconds since January 1, 1970 and additional nanoseconds.

procedure

(dump-image-and-exit output)  void?

  output : handle?
Writes an image of the current Zuo process to output, which must be an open output file or stream, and then exits.

This function is intended to be used after some set of modules has been loaded, so that the loaded modules are included in the image. The dump fails if any handle is encountered as reachable from loaded modules, however.

procedure

(exit [status])  void?

  status : integer? = 0
Exits the Zuo process with the given status, where 0 normally means “success.”

procedure

(suspend-signal)  void?

procedure

(resume-signal)  void?

Suspends or resumes recognition of termination signals, such as Ctl-C. Calls can be nested, and each call to suspend-signal must be balanced by a call to resume-signal to re-enable signal handling.