URL http://www.cs.hmc.edu/~keller/rex

Convenience link to CS 60 and to the rex *lite*Reference Card.

Last updated 5 September 1999 by keller@cs.hmc.edu.Please report any errors or inaccuracies to keller@cs.hmc.edu.

This card also forms the basis of the interactive help file callable from rex, which might explain its slightly unusual organization. The rex help system looks for the keyword "bullets"which mark each item.

**Help**

One way to get help interactively is to type

(return)`*h`

to the rex read loop. This puts you into the **help loop**, wherein you can type terms, or parts of terms and get descriptions from this document.

To return to the rex read loop from the help loop, type the character control-d.

Another way to invoke help on a topic is to call, within rex,

`help(Topic);`

It is not necessary to put quotes around the topic. Help is available on the following topics, as well on all individual functions.

- alphabetic listing of all functions
- anonymous functions
- arithmetic functions
- arity notation
- arrays and array functions
- Booleans
- character functions
- command-line arguments
- comments
- definitions
- dynamic types
- examples
- expressions
- forms
- grammar
- infinite list functions
- input-output pseudo-functions
- interrupting rex
- lists and list functions
- local definitions and equational guards
- local recursive definitions
- logical functions
- miscellaneous functions
- operators
- quick commands
- precedence of operators
- relational functions
- sequence functions
- strings and string functions
- side-effect pseudo functions
- system commands
- system variables
- transcendental functions
- trace command
- type function and list of types
- variables

**Read Loop**

rex runs an interactive "read loop", also called read-eval-printloop. This means that the following cycle repeats until the user types end-of-file (e.g. control-d):

- user enters an expression.
- rex evaluates the expression
- rex shows the answer

In some cases, it is a little more complicated than this: the evaluation can be interleaved with printing the answer. This ishelpful when the answer is very long, and essential when the answeris infinite. An evaluation can be interrupted (seeinterrupting rex).

**Quick Commands**

Quick commands provide an alternative for entering system and helpcommands with a minimum of key strokes. A quick command is identifiedby a single line starting with * and terminated by return (no ;) Thefollowing quick commands are available:

`*i`

*Filename*- Load the named file (
**no quotes**around*Filename*). `*h`

- Enter the help loop.
`*q`

- Toggle "quotes" mode. Only output is affected. In this mode, double quotes are shown as strings and single quotes are shown around characters.
`*r`

- Toggle "readline" mode. In this mode, you can use emacs-like commands to edit single lines and move backward and forward in the history list of commands. (Note: Currently in readline mode, suspending with control-Z is ineffective and causes problems.)
`*t`

- toggle the function trace
`*`

*N*- where
*N*is a positive number: redo expression number*N*. `*`

-*N*- where
*N*is a positive number: redo the expression*N*expressions ago `**`

- redo the previous expression (same as *-1)
**Comments**

Comments are as in C++. They either start with

//and continue to end-of-line, or start with

/*and continue to*/.

Currently the latter comments cannot be recursive (i.e. you can'thave `/*` .... `*/` within `/*` ....`*/`).

**Dynamic Types and Storage**

rex is a dynamically-typed language, meaning that types are associated with values, rather than with variables. A given variablecan be bound to any type of value and there are no type declarations. Many of the functions are polymorphic (accepting more than one type of argument).

The down-side of this is that types have to be checked for sensibility at run-time. For example, it doesn't make sense to multiply one string by another. Thus there may be errors about whichyou don't find out until run-time, but which would have been caughtat compile-time by a statically-typed language. rex handles such errors for you by returning an error value when types don't makesense. A list of types is given with the description of the function*type* which will indicate the type of adata item.

Another sense in which rex is dynamic is that there are no storage allocation commands. Data items, typically lists, get created as theresult of function evaluations. But the programmer does not preallocate space for these results. Reclamation of unused storage issimilarly handled by the system.

**Expressions**

There are three types of rex expressions:

**All expressions to be evaluated are terminated with asemi-colon.** (end-of-line doesn't terminate an expression,because expressions can take an arbitrary number of lines, and it isnot generally evident when there isn't more to an expression.)

**Definitions**

Definitions bind variables and function names. A definitionappears as

LHS=RHS;

where LHS is the variable or variables being defined, and RHS iswhat defines them. Examples are:

cube(x) = x*x; // defines the cube function alist = [1, 2, 3, 4]; // defines a list variable calledalist[x, y, z] = foo(alist); // defines variables x, y, and z,

**Caution:** While definitions have a certain similarity toassignments (e.g. in C), they should not be used that way. Theability to reassign is simply for convenience in interacting with thesystem. At the core, rex is a functional language and is designed tohelp learn to program without assignment statements. Global definitions have a value 1 if the definition succeeds and 0 if not.The reason a definition might not succeed is that the RHS valuesdon't match the LHS pattern. For example, in

[x, y, z] = [1, 2];

the list on the right has two values whereas the one on the lefthas three. On the other hand

[x, y | z] = [1, 2];

will succeed and bind `x` to 1, `y` to 2, and`z` to [ ]. See also localdefinitions.

**Rules**

Rules define parts of functions by using pattern matching andguards, and are collected together by rex to make a definition. A rule has the form: `LHS` => `RHS`; (The symbol=> an = followed by a > and is read "yields"). The following are examples of rules (for the greatest-common-divisorfunction):

gcd(0, y) => y;

gcd(x, y) => x <= y ? gcd(y % x, x);

gcd(x, y) => gcd(y, x);

The second rule above uses a guard, anexpression which must be true in order for the rule to apply. Asanother example, the following rules use pattern matching to find thelast element in a non-empty list.

last([X]) => X; last([_ | X]) => last(X);

**Evaluable Expressions**

Although all expressions have a value, the remaining kinds ofexpressions are entered for purposes of evaluation. They yield avalue which is printed. They can also have side-effects, but the routine use of side-effects is discouraged. The computations of theseexpressions are done in the context of definitions and rules.

For example, to use the `gcd` and `last`functions defined above in a computation, we'd need to enter anexpression:

gcd(56, 72);

rex would respond with the answer 8. If we entered:

last([1, 2, 3, 4, 5]);

rex would respond with the answer 5.

**Variables**

A variable is a sequence of contiguous characters starting with aletter (upper or lower case) or underscore, and containing letters,underscores, and digits. Names of functions are considered to bevariables bound to anonymous function values.

**Operators**

The following kinds of operators are available:

- arithmetic functions: + -* / %
- definitional: = =>
- lists and list functions [ , , , ....] [ , , .... | ]
*first**rest**null* - logical functions: && || !
*implies* - relational functions: == != > >= <=

Arithmetic, logical, and relational operators are pretty much thesame as in C and C++.

**Precedence and Grouping**

The following lists operator precedence tightest to weakest. Alloperators group *left* unless otherwise indicated.

- function application ...(...)
- $ (defer) and unary - group
*right* - * (multiply) / (divide) % (modulus)
- +(add) - (binary subtract)
- == != > < >= <= (equality and inequalities)
*do not group* - ! (not) groups
*right* - && (and)
- || (or)
- ? = (guards and definitions) group
*right* - => (
*yields*in anonymous functions) groups*right*

**Arithmetic Functions**

- + (addition)
- - (subtraction)
- * (multiplication)
- / (division)
- % (modulus, remainder)
- abs (absolute value)
- ack (Ackermann's function)
- ceil (ceiling)
- divides
- exp (exponential)
- fac (factorial)
- finite
- frexp (floating point number decomposition)
- float
- floor
- isnan
- is_prime
- integer
- ldexp (floating point number composition)
- make_number
- minus
- pow
- sign (sign, +1, 0, -1)
- sq (square)

These functions are defined as follows:

**+**as in`N`+_{1}`N`+ .... +_{2}`N`_{n}- with 2 or more numeric arguments, + adds the arguments together.
- with 2
*list*arguments, adds the arguments together component-wise. - with 1 argument, +(N) is defined as the function (X) => X+N.
**-**as in`N`-_{1}`N`_{2}- with 2 arguments, - subtracts its second argument from its first.
- with 2
*list*arguments, subtracts the arguments component-wise. - As a prefix operator -(....) is unary minus, i.e. negates its argument.
*****as in`N`*_{1}`N`* .... *_{2}`N`_{n}- with 2 or more numerical arguments, * multiplies the arguments together.
- with 2
*list*arguments, multiplies the arguments component-wise. - with the first argument a scalar and the second a list, multiplies each element in the list by the scalar.
- with 1 argument, *(N) is defined as the function (X) => X*N.
**/**as in`N`/_{1}`N`_{2}- with 2 arguments, / divides its first argument by its second.
- with 2
*list*arguments, divides the elements of the first list by those in the second. - with 1 argument, /(N) is defined as the function (X) => X/N. The result is integer if all arguments are integer, otherwise it is floating.
**%**as in`N`%_{1}`N`_{2}- gives the remainder of dividing the first argument by the second. Only integer arguments are supported.
**abs**`abs(N)`returns the absolute value of*N*.**ack**- Ackermann's function
`ack(N, X, Y`) returns the value of X op Y at the Nth level of the hierarchy of ops +, *,`pow`, ... **ceil**`ceil(N)`returns the smallest integer >=*N*;**divides**`divides(N`) returns 1 if integer_{1}, N_{2}*N*divides_{1}*N*with no remainder._{2}- divides(N
_{2}) is the function which, with argument*N*will give the value divides(N_{1}_{1}, N_{2}).For example,

`divides(3)(N`will return 1 whenver N_{1})_{1}divides 3. **exp**`exp(N`) returns the exponential function of*N*, i.e. pow(e, N) where e is base of the natural logarithm.**fac**`fac(N)`returns the factorial of N (N*(N-1)*(N-2)*....*2*1).**finite**`finite(Expression)`returns 1 or 0 depending on whether the argument is neither of Infinity nor -Infinity in IEEE floating point.**floor**`floor(N)`returns the largest integer <=*N*;**float**`float(N)`returns a floating point value of a number N, whether N is floating or integer**frexp**`frexp(N)`returns a list of a floating point number and an integer. Every non-zero number can be written uniquely as x * 2^n where the ``mantissa'' (fraction) x is in the range 0.5 < |x| < 1.0, and the ``exponent'' n is an integer.*frexp*returns the mantissa and exponent in the form of a list of two elements. When the value is zero, both elements are 0.**ldexp**`ldexp(L)`constructs a floating-point number from a list consisting of a floating-point mantissa and an exponent. In this form, it is the inverse of frexp- ldexp(M, E) takes the mantissa and exponent explicitly rather than in a list.
**integer**`integer(N)`returns the integer part of N as an integer, whether N is integer or floating. If N is a character, it returns the character code (e.g. ascii) for N.**isnan**`isnan(Expression)`returns 1 or 0 depending on whether the argument is a NaN ("not a number" in IEEE floating point). Note that by IEEE rules, two Nan's are always unequal and a given Nan is not even equal to itself. We currently violate the latter rule: x == x will always be true.**is_prime**`is_prime(N)`returns 1 if*N*is prime, 0 otherwise. Only applies to integers.**make_number**`make_number(A)`If*A*is a string,*make_number*tries to interpret it as a decimal numeral (integer or floating, in that order) and create a number from it. Similarly, if*A*is a char for a decimal digit. If*A*is a number, returns that number. Otherwise returns an error.**minus**`minus(N)`returns the negative of*N*, i.e. the same as -*N*.**pow**`pow(N`returns the_{1}, N_{2})*N*raised to the power_{1}*N*. The result is floating point if either argument is, otherwise it is integer._{2}**sq**`sq(N)`returns the square of*N*.**sqrt**`sqrt(N)`returns the square root of*N*. If N is an integer, the result is the largest integer M such that M*M <= N.**Relational Functions**

These apply to more than just numeric values. For example, listsand arrays can be compared in lexicographic order.

**==**`A1 == A2`evaluates to 1 if the arguments are equal, otherwise 0.- ==(A2) is the function which, with argument
*A1*, gives the value of A1 == A2. **!=**`A1 != A2`evaluates to 1 if the arguments are unequal, otherwise 0.- !=(A2) is the function which, with argument
*A1*, gives the value of A1 != A2. **>**`A1 > A2`evaluates to 1 if*A1*is greater than*A2*.- >(A2) is the function which, with argument
*A1*, gives the value of A1 > A2. **<**`A1 < A2`evaluates to 1 if*A1*is less than A2.- <(A2) is the function which, with argument
*A*, gives the value of A1 < A2. **>=**`A1 >= A2`evaluates to 1 if*A1*is greater than or equal A2.- >=(A2) is the function which, with argument
*A1*, gives the value of A1 >= A2. **<=**`A1 <= A2`evaluates to 1 if*A1*is less than or equal*A2*.- <=(A2) is the function which, with argument
*A1*, gives the value of A1 <= A2. **max**`max(A1, A2, ...., An)`evaluates to the largest of the arguments. There must be at least one argument.**min**`min(A1, A2, ...., An)`evaluates to the smallest of the arguments. There must be at least one argument.**Booleans**

The Boolean model used by rex is: 0, [ ] (the empty list), andfailure values are false, and anything elseis true. When a built-in returns a Boolean, it is either 0 or 1.

**Logical Operators**

The logical operators are:

**!**- !A1 returns 1 if the argument is false, otherwise returns 0.
**&&**- A1 && A2 && .... && An evaluates arguments in sequence, until one is false, The first false argument is returned. Otherwise 1 is returned.
**||**- A1 || A2 || .... || An evaluates arguments in sequence, until one is not false. The first non-false argument is returned. Otherwise 0 is returned.
**implies**- implies(A1, A2)
*A1*is evaluated. If it is not false, the result is*A2*. Otherwise the result is 1.**Lists and List Functions**

List formation is represented by [X0, X1, ...., Xn-1]. A listresult will show in this fashion as well, unless it is converted tosome other format. The null list is [ ].

Lists may be written to and read from files as S expressions bysingle commands.

A list may be formed from an item and an existing list by [X | L],meaning to construct the list consisting of X followed by the elements of L. Another way to get the same effect is cons(X, L). Withrespect to the list thus created, X is the "first" of the list and Lis the "rest".

This notation may be generalized: [X0, X1, ...., Xn-1 | L] formsthe list starting with the n elements indicated, followed by the elements of L.

An "improper list" is formed by [X | Y] where Y is not a list. Aresult of this form will show as [X | Y]. Programming will generallybe simplified if improper lists are avoided.

**Incrementaland "infinite" lists** may be created by deferring the rest of thelist: In [X |$ L] the $ acts to defer the evaluation of L. Taking therest of the list will give the seed $L which is not further evaluateduntil needed (e.g. in the case of checking to see whether the rest isthe empty list.

Some list functions are:

- cons: make a list from elements and a list
- first: first element of a list
- list: make a list from elements
- null: test for emptiness
- rest: list of all but the first element of a list
- second: second element of a list
- third: third element of a list
- range: list of a range of numbers

Other list functions may be found undersequence functions.

**list**`[A1, ...., An]`or`list(A1, ...., An)`makes a list of the values of any number of arguments. Note carefully how`list`differs from`cons`.**cons**`[A1, .... | An]`or`cons(A1, ...., An)`Function*cons*(of an arbitrary number of arguments, but often 2) makes a list of the values of its arguments, the value of the last argument becoming the tail of the new list. There must be at least one argument.**first**`first(A)`returns the first element of a non-null list.**rest**`rest(A)`returns a list of all but the first element of a non-null list.**null**`null(A)`returns 1 if its argument is the empty list and 0 otherwise.**second**`second(A)`returns the second element of a list with at least two elements.**third**`third(A)`returns the third element of a list with at least three elements.*Other selections from lists*may be made by treating the list as a function from {0, 1, 2, ..., length-1} to values: i.e.`L(i)`

is the i*th*element of L.**range**`range(N`_{1}, N_{2}):If

*N*<=_{1}*N*,_{2}`range(N`yields the list [_{1}, N_{2})*N*,_{1}*N*+1,_{1}*N*+2, ....,_{1}*N*]._{2}If

*N*>_{1}*N*,_{2}`range(N`yields the list [_{1}, N_{2})*N*,_{1}*N*-1,_{1}*N*-2, ....,_{1}*N*]._{2}`range(N`yields the list [_{1}, N_{2}, K)*N*,_{1}*N*+K,_{1}*N*+2*K, ....,_{1}*N*] in case that_{2}*N*<=_{1}*N*and_{2}*K*is positive, or*N*>=_{1}*N*and_{2}*K*is negative. Otherwise the result is [ ].Examples:

range(1, 9) ==> [1, 2, 3, 4, 5, 6, 7, 8, 9] range(9, 1) ==> [9, 8, 7, 6, 5, 4, 3, 2, 1] range(1, 9, 2) ==> [1, 3, 5, 7, 9] range(9, 1, -2) ==> [9, 7, 5, 3, 1]

**primes_to**`primes_to(N)`yields the list of primes from 2 up to the highest prime less than or equal to N.**Incremental and Infinite-List Functions**

- from: numbers from a given number
- primes: prime numbers from 2
- primes: prime numbers from an arbitrary number
- random: random numbers (in a range)

**from**`from(N)`creates the infinite list [N, N+1, N+2, ...]. If N is floating, the items will be floating. Otherwise all items will be fixed.`from(N, K)`creates the infinite list [N, N+K, N+2*K, ...]. If N is floating, the items will be floating. If K is floating, but N is not, all but the first item will be floating. Otherwise all items will be fixed.**primes**`primes()`creates the (infinite) list of primes starting with 2.**primes_from**`primes_from(N)`creates the (infinite) list of primes starting with the first prime not less than N.**random**`random()`creates an (infinite) list of pseudo-random non-negative integers.`random(M, N)`creates an (infinite) list of pseudo-random integers between M and N inclusive.**Strings and String Functions**

- concat: concatenate any number of strings
- lconcat: concatenate a list of strings
- explode: explode a string to a list of chars
- implode: create string from a list of chars
- length: length of a string
- make_string: make a string from a number or char
- words: makes a list of "words" from a string

A literal string must be in double quotes, e.g.

"this is a string"

Strings are distinguished from single characters, which are insingle quotes, e.g.` 'x'`. In either case, backslash(`\`) can be used as an escape character. The standard Cescape codes apply:

\n is newline \t is tab \\ is backslash \f is form-feed \b is backspace \a is bell \v is vertical tab \r is carriage return

**Note**: As with sequences, a particular character of a stringmay be extracted by treating the string as a function: `S(i)`,where i is between 0 and (length of the string) -1 yields thei*th* character of S.

**concat**`concat(S1, ...., Sn)`concatenates the strings to create a new string.**explode**`explode(S)`creates a list of chars from string S.**lconcat**`lconcat(L)`concatenates the strings in list L to make one single string.`lconcat(L, S)`concatenates the strings in list L interposing the string S between successive words (but not at the very end) to make one single string.**implode**`implode(L)`creates a string from a list of characters L.**length**`length(S)`gives the length of string S.**make_string**`make_string(A)`makes a string from argument A, where A is an integer, floating, or single char.**words**`words(S)`creates a list of strings from a single string. The strings are "words" in the sense that they are non-whitespace characters separated by some amount of whitespace.**Character Functions**

- isalpha: returns 1 if its argument is alphabetic, otherwise returns 0
- isdigit: returns 1 if its argument is a digit, otherwise returns 0
- isupper: returns 1 if its argument is upper-case, otherwise returns 0
- islower: returns 1 if its argument is lower-case, otherwise returns 0
- ispunct: returns 1 if its argument is punctuation, otherwise returns 0
- isspace: returns 1 if its argument is whitespace, otherwise returns 0
- iscntrl: returns 1 if its argument is a control character, otherwise returns 0

**Arrays and Array Functions**

- array: make an array from specified elements
- array_from_list: make an array from the elements of a list
- leaves: count the atoms in a multi-level array
- leafcount: count the number of atoms in a multi-level array
- length: return the length of an array
- list_from_array: make a list from the elements of an array
- make_array: make an array of specified length from a function specifying its values

Selections from arrays may be made by treating the array as afunction from {0, 1, 2, ..., length-1} to values: i.e. A(i) is thei*th* element of A.

**array**`array(A1, ...., An)`yields an array of the values of its arguments.**array_from_list**`array_from_list(L``)`

yields an array with the elements of the argument, a list, as elements.**leaves**`leaves(A)`treats the array as the root of a tree, and returns a list of the leaves of the tree. The tree can have arrays or lists as nodes.**leafcount**`leafcount(A)`is the length of leaves(A)**length**`length(A)`gives the number of elements in the array.`length(A, N)`destructively changes the number of elements in the array to N. If N is greater than the former length, then new elements are initialized to 0.**Caution**: This is not a function. It has a side-effect and should be used carefully, as the array might be shared.**list_from_array**`list_from_array(A)`creates a list with the elements of an array as elements**make_array**`make_array(N, F)`makes an array the size of which is given by the first argument. The second argument is a function which, when applied to 0, 1, 2, .... gives the values of the corresponding elements of the array.For example

`make_array(10, id)`returns an array of values from 0 to 9.**set**`set(Array, Index, Value)`sets the Index*th*component of`Array`to`Value`).**Caution**: This is not a function. It has a side-effect and should be used carefully, as the array might be shared.**Sequence Functions**

These apply to both **lists** and **arrays**, as well as to**strings** in a few cases. The ones which apply to incremental orinfinite, as well as finite, lists are annotated as "incremental".

- all: check whether all elements of a list have a property
- antiprefix: return all but the first N elements of a list
- append: concatenate two lists together
- assoc: find the first list beginning with the first argument in an association list which is the second argument
- diff: form a sequence of successive differences of elements
- drop: return the sub-sequence of elements not having a specified property
- every: form a list by selecting every Nth element
- extract: bring an item with property P to the front of a list, leaving other elements behind it
- find: return the suffix of a list starting with an element having a specified property
- find_index: return the index of the first item in a list having a specified property
- find_indices: return the list of all items in a list having a specified property
- keep: return the sub-sequence of elements having a specified property
- leaves: return a list of the innermost items of a sequence
- leafcount : return a count of the innermost items of a sequence
- length: return the length of a sequence
- map: apply a function to all elements of a sequence, or pair of sequences
- map_tail: like map, except a tail is supplied
- mappend: like map, except the results of the sequence are appended together
- mappend_tail: like mappend, except a tail is supplied
- member: test whether a given element occurs within a sequence
- merge: merge two lists together according to an order
- no: check that there is no element in a sequence satisfying a property
- pmap: a parallel version of map
- prefix: specified-length prefix of a sequence
- reduce: apply a binary operator to elements of a sequence to get a value
- remove_duplicates: remove duplicates from a list
- reverse: reverse a list or array
- scale: multiply each element of a sequence by a specified value
- scan: apply a binary operator to successive elements of a sequence, giving partial results
- some: check whether some element of a sequence has a property
- sort: arrange an array or list into increasing order according to an ordering
- suffix: return the last N elements of a sequence
- zip: interleave the elements of two sequences together

**all**`all(P, L)`yields 1 if all X occurring in L are such that P(X). Otherwise yields 0.**antiprefix**`antiprefix(N, L)`yields all but the first N items in L. If L doesn't have N items, yields []. [incremental]**append**`append(L, M)`returns the list consisting of elements of L followed by those of M. [incremental in second argument]**assoc**`assoc(X, L)`

yields the first list element of an association list having X as its first item. If there is no such item, yields [ ]. For example, assoc('c', [['a', 1], ['b', 2], ['c', 3], ['d', 4]]) will return [c, 3].**count**`count(P, L)`returns the number of X occurring in L is such that P(X).**diff**`diff(B, S)`forms the array or list of successive "differences", when the binary function B is viewed as "subtraction". If S = [S0, S1, S2, ... Sn], then diff(-, S) = [S1-S0, S2-S1, ...., Sn-Sn-1]. Thus diff(B, S) has one fewer element than S. diff(B, [ ]) is [ ] by convention. In general, B could be any binary operator, e.g. /. [incremental]**drop**`drop(P, S)`If S is an array or list, and P is a 1-ary function, then`drop(P, S)`is the array or list resulting from dropping those elements for which P is true. [incremental]**every**`every(N, L, K)`

yields a list consisting of every Nth element of L starting at the Kth (where K = 0 means the first, etc. [incremental]**extract**`extract(P, L)`

creates a new list by finding the first item X in L for which P(X) and bringing it to the front of the list. If there is no such item, this function diverges [incremental]**find**`find(P, L)`

yields the suffix of L beginning with the first item X for which P(X). If there is no such item, yields [ ], unless L is infinite, in which case this function diverges. [See also keep.]**find_index**`find(P, L)`

yields index (starting with 0 as the first index) of the first item X for which P(X). If there is no such item, yields -1, unless L is infinite, in which case this function diverges.**find_indices**`find(P, L)`

yields the list of indices of all items X for which P(X). If L is infinite but there are only finitely-many such X, this function diverges after producing the indices of those X. [See also keep.] [incremental]**keep**`keep(P, S)`

If S is an array or list, and P is a 1-ary function, then`keep(P, S)`

is the array or list resulting from keeping those elements for which P is true. [incremental]**leaves**`leaves(A)`

treats the list as the root of a tree, and returns a list of the leaves of the tree. The tree can have arrays or lists as nodes.**leafcount**`leafcount(A)`

is the length of leaves(A)**length**`length(S)`

returns the length of the list, array, or string**map**`map(F, S)`

If S is an array or list, constructs a new array or list the same length as S, by applying F to each element of S.`map(B, S1, S2)`

S1 and S2 should be both arrays or both lists. The result is a new array or list constructed by applying binary function B to the elements of S1 and S2, element-by-element. [incremental]**map_tail**`map_tail(F, S, Tail)`is like map, except that the list ends with the list`Tail`**mappend**`mappend(F, L)`

Assuming L is a list, and F is a function which will return a list when applied to a member of L, returns the result of appending the elements of`map(F, L)`together in order.**mappend_tail**`mappend(F, L, Tail)`is like`mappend(F, L)`, except that the result list ends with the list`Tail`.**member**`member(X, L)`yields 1 if`X`occurs in`L`; otherwise yields 0.**merge**`merge(L, M)`

assuming that L and M are in order according to the built-in order <, merges them together into a single with respect to <. [incremental]**merge**`merge(P, L, M)`

assuming that L and M are in order according to the partial order P, represented as a binary function, merges them together into a single list in order with respect to P. [incremental]**no**`no(P, L)`

yields 1 if no X occurring in L is such that P(X). Otherwise yields 0.**pmap**`pmap(F, S)`

is like map(F, S) except that (if multithreading is in force) each element of the result is evaluated in parallel**prefix**`prefix(N, L)`

yields the first N items in L. If L doesn't have N items, yields all of L. [incremental]**reduce**`reduce(B, U, S)`

Here B is a binary operator with unit U and S is an array or list. The result is the accumulation of applying B to elements in S.For example,

`reduce(+, 0, S)`

is the sum of elements in S, while`reduce(*, 1, S)`

is the product. Grouping is to the left, i.e. if S were [S0, S1, S2, ... Sn], then the result is B( .... B(B(B(U, S0), S1), S2) ...., Sn). [incremental]**remove_duplicates**`remove_duplicates(L)`

returns a list with any duplicates removed [incremental]**reverse**`reverse(L)`

returns the list consisting of elements of L in reverse order**scale**`scale(F, S)`

If*S*is an array or list, constructs a new array or list the same length as*S*, in which each element of the original is multiplied by*F*. [incremental]**scan**`scan(B, S)`

*B*is a binary operator and*S*is an array or list. The result is the array or list (of the same length as*S*) of partial accumulations of*B*applied to the elements of*S*. For example, scan(+, S), where S = [S0, S1, S2, ... Sn], yields [S0, S0+S1, S0+S1+S2, ...., S0+....+Sn-1]. [incremental]**some**`some(P, L)`

yields 1 if an X occurs in L such that P(X). Otherwise yields 0.**sort**`sort(S)`

returns an array or list (whichever S is) containing the elements of S in sorted order. The ordering is the natural one built into rex.**suffix**`suffix(N, L)`

yields the last N items in L. If L doesn't have N items, yields all of L. [incremental]**zip**`zip(L, M)`

yields the list formed by alternating an element of L with an element of M [incremental]**Transcendental Functions**

- log: logarithm
- sin: sine
- cos: cosine
- tan: tangent
- sinh: hyperbolic sine
- cosh: hyperbolic cosine
- tanh: hyperbolic tangent
- log: logarithm
- asin: inverse sine
- atan: inverse tangent
- asinh: inverse hyperbolic sine
- acosh: inverse hyperbolic cosine
- atanh: inverse hyperbolic tangent
- erf; error function
- erfc: complementary error function

**log**`log(N)`

returns the natural logarithm of*N*.`log(N`

returns the logarithm of_{1}, N_{2})*N*base_{2}*N*._{1}**sin**`sin(N)`

returns the sine of*N*.**cos**`cos(N)`

returns the cosine of*N*.**tan**`tan(N)`

returns the tangent of*N*.**asin**`asin(N)`

returns the inverse sine of*N*.**atan**`atan(N)`

returns the inverse tangent of*N*.**sinh**`sinh(N)`

returns the hyperbolic sine of*N*.**cosh**`cosh(N)`

returns the hyperbolic cosine of*N*.**tanh**`tanh(N)`

returns the hyperbolic tangent of*N*.**asinh**`asinh(N)`

returns the inverse hyperbolic sine of*N*.**acosh**`acosh(N)`

returns the inverse hyperbolic cosine of*N*.**atanh**`atanh(N)`

returns the inverse hyperbolic tangent of*N*.**erf**`erf(N)`

returns the "error function" of N, 2/sqrt(pi)*integral from 0 to N of exp(-t*t) dt.**erfc**`erfc(N)`

returns the "complementary error function", 1.0 - erf(N), computed by methods that avoid cancellation for large N.**Input-Output Pseudo-Functions**

- close: closes an ostream
- endl: sends an end-of-line to an ostream
- eof: test end-of-file condition
- exec: call operating system command
- inchars: input chars from standard input as an incremental list
- inline: input single line from istream
- insexp: input single S expression from a file
- insexps: input S expressions as an incremental list
- make_comment_istream: make an input stream with comments
- make_istream: make an input stream
- make_ostream: make an output stream
- outsexp: output single value as S expression to a file
- outsexps: output S expressions as an incremental list
- readchars: input single char
- readchars: makes istream of chars into incremental list
- readsexp: input single S expression from istream
- readsexps: makes istream of S expressions into incremental list
- writesexp: output a single S expression to an ostream

**close**`close(Ostream)`

closes the argument Ostream. If the stream is input to a Unix process, closing is necessary for that process to terminate.**endl**`endl(Ostream)`

sends an end-of-line to the argument Ostream.**eof**`eof()`

indicates whether the standard input is in an end-of-file condition and clears that condition**exec**`exec(Command)`

executes a command in the operating system (e.g. Unix). It returns a pair`[Istream, Ostream]`. The program sends input to the command via the Ostream and gets output from the Istream, using appropriate primitives described in this section.**inchars**`inchars()`

yields a list of characters from the characters in the standard input. The input can be unlimited, e.g. piped in from Unix. The result is an incremental list.`inchars(Filename)`

yields an incremental list of characters from the characters in the named file. The list is built incrementally on demand.**insexps**`insexps()`

yields a list of values as determined by S expressions in the standard input. The list is incremental and the input can be unlimited, e.g. piped.`insexps(Filename)`

yields an incremental list of values as determined by S expressions in the named file.**insexp**`insexp(Filename)`

yields single value as determined by the first S expression in the named file. The file is opened, then closed.**endl**`flush(Ostream)`

flushes the identified Ostream without sending an end-of-line.**make_istream**`make_istream(Filename)`

- yields an istream value from a file, for use with readsexp or readchar.
`make_istream()`

- yields an istream value from the standard input stream.
**make_commented_istream**`make_commented_istream(Filename)`

- yields an istream value which automatically ignores comments (from
`//`to end-of line and from`/*`to`*/`) which can then be used with readsexp or readchar. `make_commented_istream()`

- yields an istream value from the standard input which automatically ignores comments (from // to end-of line and from
`/*`to`*/`) which can then be used with`readsexp`or readchar. **make_ostream**`make_ostream(Filename)`

yields an ostream value, e.g. for use with writesexp.**outsexps**`outsexps(L)`

outputs an incremental list L (possibly infinite) to the standard output.`outsexps(Filename, L)`

outputs an incremental list L (possibly infinite) to the named file.**outsexp**`outsexp(Filename, V)`

outputs a single value to the named file. The file is opened, then closed.**readchar**`readchar()`

reads a single character from the standard input.`readchar(Istream)`

reads a single character from the istream identified.**readchars**`readchars(Istream)`

makes stream of chars from the istream identified into an incremental list.**readline**`readline()`

reads a single line from the standard input as a string.`readline(Istream)`

reads a single line, as a string, from the istream identified.**readsexp**`readsexp()`

reads a single S expression from the standard input.`readsexp(Istream)`

reads a single S expression from the istream identified.**readsexps**`readsexps(Istream)`

makes stream of S expressions from istream into an incremental list.**writesexp**`writesexp(Sexp)`

writes a single S expression to the standard output. Note that`Sexp`can be a single char or a single string.`writesexp(Ostream, Sexp)`

writes a single S expression to the ostream identified.**Miscellaneous Functions**

- atomic: whether datum is atomic (not list or array)
- builtin: specify builtin function by name and arity
- disable: enable a built-in function
- enable: enable a built-in function
- grow: wait for result of evaluation
- id: identity function
- k: konstant function
- quote: take argument literally
- set: set a variable destructively
- sow: evaluate in a separate thread
- spec: specify function by name and arity
- defined: get list of defined (non-builtin) identifiers
- test: test evaluation of an expression
- type: type of a datum
- undef: un-define a global variable

**atomic**`atomic(A)`

returns 1 if its argument is not a list or array.**builtin**`builtin(Name, Arity)`

returns a specific builtin function given literal name and arity.`builtin()`- returns a sorted list of built-in functions and special forms with their arities. For example:
[[!, 1],[!=, 1], [!=, 2], [%, 2], [&&, 5], [*, 1], [*, 2],[*, 5],[+, 1], [+, 2], [+, 5], [-, 1], [-, 2], [/, 1 ], [/, 2], [<, 1], [<, 2], [<=, 1], [<=, 2], [=, 3], [==, 1], [==, 2],[=>, 2], [>, 1],[>=, 1],[asin, 1], [asinh, 1], [atan, 1], [atanh, 1], [atomic, 1], [builtin, 0], [builtin, 2], [ceil, 1], [char, 1], [close, 1], [concat, 5], [cons, 2],

etc. Each function is paired with an arity.

Note that a special meaning is attached to arity 5; rather than being a specific arity, it means that the arity is arbitrary. For example,

`concat()`,`concat(A)`,`concat(A, B)`,`concat(A, B,C)`, ... are all valid since`[concat, 5]`appears in the list. In some cases, such as with`cons`above, both arity 5 and arity 2 appear. This could indicate special over-riding treatment for the specific arity 2, although in this case it turns out to be just an efficiency hack, since`cons`is usually used with just 2 arguments. **deep_type**`deep_type(A)`returns the type of A if A is not a list, or a list of the deep_types of elements of the list if it is a list. Example: deep_type([1, [2, 3], "foo") ==> [integer, [integer, integer], string]**defined**`defined()`

Creates a list of names (as strings) of identifiers (other than builtins) which are currently defined.**eval**`eval(Expression)`

Expression is evaluated, then that value is treated as if it were an expression and evaluated. This allows expressions to be constructed from lists on the fly, then evaluated. To see how expressions are constructed in general, analyze them withs the quote operator. Example:`eval(["+", 2, ["*", 3, 4]]) ==> 14`**id**`id(Datum)`

returns Datum (useful in certain contexts, e.g. make_array).**k**`k(Datum)`

makes a constant function with value`Datum`. That is, it returns a function which, when applied to any argument, returns Datum. i.e.`k(Datum)(Anything)`is`Datum`. (useful in certain contexts, e.g. make_array).**quote**`quote(Expression)`

The argument is not evaluated, but is converted into a literal structure of the same form used by the rex interpreter for programs. The resulting value may then be processed as a string or list, as appropriate. Example:`quote(a+b*c)`has the value`["+", "a", ["*", "b", "c"]]`**test**`test(Expression1, Expression2)`

evaluates the expressions and compares them for equality. Usually Expression2 is the expected answer. Prints a message indicating whether the test is "ok" or "bad".**type**`type(A)`

returns a string naming the type of its argument A. The following types are available:

- integer
- floating
- string
- char
- list
- array
- function
- builtin
- istream
- ostream
- channel
- error
- failure

`type()`returns a list of strings naming the available types. Lists and arrays may have any of these types as elements, in any mixture, include lists and arrays to any number of levels of nesting.

The following functions return 1 or 0, depending on whether theargument is of the corresponding type:

`is_integer``is_floating``is_number (integer or floating)``is_string``is_char``is_list``is_array``is_sequence (list or array)``is_function (user-defined or builtin)``is_builtin``is_channel``is_error`

See also `atomic` which returns 1 ifits argument is not a list or array.

**sow**`sow(Expression)`

If multithreading is available, the value of`Expression`is evaluated in a separate thread. Meanwhile, the expression is treated as being deferred. Any attempt to use the value will synchronize with the evaluating thread until the value becomes available.**grow**`grow(Expression)`

Explicitly waits for the result of`Expression`to be evaluated, e.g. in the case that the result is that of a sow. This function is implicit in the built-in functions which require it, thus it is not often used.**spec**`spec(Name, Arity)`

or`Name#Arity`

Returns a specific function given literal name and arity.**Side-Effect Pseudo Functions**

**Caution:** Use of side effects is not in the spirit of a functional language. These primitives may be disabled for purposes of teaching functional programming.

**set**`set(Variable, Value)`

Changes the value of an already-defined variable, local or global, to the specified value. At the global level, if the variable is not yet defined, set will define it.**undef**`undef(Variable)`

The most recent global definition of Variable, if any, is removed. The previous definition is restored. The value returned is 1 if there was a definition, 0 otherwise. Caution: This effects globals, even if called inside a function with the same variable bound locally.**repeat**`repeat(Value, Command)`

does

`Command`the number of times specified by Value.**while**`while(Condition, Command)`

repeatedly tests

`Condition`and if true executes`Command`. Returns the value [].**for**`for(Initialization, Condition, Incrementation, Command)`

does

`Initialization`, then repeatedly tests`Condition`and if true executes`Command`, after which Incrementation is executed.**Forms (not necessarily functions)**

**?**as in`Guard ? Body`

- is used in guarded rules.
`Guard`

is the*guard*, a logical expression, and Body is an expression. The rule applies only if the guard is true, in which case the result is the value of Body. **?**as in`Condition`

`? True_Alternative : False_Alternative`

`Condition`is evaluated first and if true, the result is the value of`True_Alternative`, otherwise it is the value of`False_Alternative`.**=>**(read "yields") as in`Head => Body`

- is used in two ways: to define rules and to define anonymous functions.
To define a rule:

`Head => Body;`

where Head is a function name with arguments, defines one rule for the named function.

Example:

`foo([A | L], N) => foo(L, A+N);`

On the other hand,

`Head => Body`

where Head is just a list of arguments in parentheses, is an "anonymous function" (also known as a "lambda expression").

Example:

`(F, X) => F(F(X))`is the function of two arguments, say F and X, which applies F to X, then applies F to the resulting value. **$**(read "defer") as in`$ Expression`

Evaluation of the expression following the $ operator is deferreduntil the value is actually needed. The definition of "needed" isdependent on the operators which apply to the value.

For example, in the conditional form

C ? F : T,

if `F` or `T` is deferred, then they are leftdeferred in the result. On the other hand, applying the function"first" to the result would evaluate a deferred argument, since itneeds to know the first element of the argument as a list. Theimmediate value of a *defer* before evaluation is an internalstructure called a *seed*. While seeds are not seen as output,they may be seen in tracing.

**Arity Notation**

Some built-in functions are overloaded. For example,`map` has two or three arguments. When abuilt-in function is passed as an argument, the ambiguity of whichfunction is to be used can be resolved by appending to the function name a # followed by the arity, e.g. `map#2`

vs.`map#3`

. The same applies to operators, e.g.`+#1`

vs. `+#2`

. Some functions can take anarbitrary number of arguments, e.g. max takes any number greater thanzero of arguments. Similarly, `+`

is two differentfunctions: `+#1`

is the "curried" +, while`+#_`

is the addition function with any other number ofarguments. If # is not attached, rex will make a choice of arity. Forexample, the binary arithmetic functions are the choice for`+`, `-`, `*`, `/`, `%`.

**Local Definitions and Equational Guards**

A local definition takes the form

`LHS = RHS, Expression;`

The value of the overall expression is the value of`Expression` in the context of the bindings made in the equation. These bindings are local, and hold only for the evaluationof `Expression`. They have no impact on existing bindings tothe variables. Example:

root = sqrt(x), f(root, g(root));

Here root is bound to the value of `sqrt(x)`

, for the evaluation of `f(root, g(root))`

. One use of a localdefinition is to prevent repeated expensive evaluation of anexpression.

When the right-hand side of a rule has this form, we call it anequational guard. The idea is that the rule only applies if thedefinition succeeds. As with global definitions, a definition willfail if there is a mis-match between the LHS and RHS. Example:

f(x) => root = sqrt(x), g(root,h(root));

Here the value of `f(x)`

is computed by binding root to`sqrt(x)`

, then returning the value `g(root,h(root))`

. Since root is only a single variable, the pattern istrivial and this guard will never fail. If the evaluation of *g*fails, this translates to a failure of the whole function *f*,not to the failure of a guard.

**Local Recursive Definitions**

When an ordinary local definition is made, the values of variablesand functions on the RHS is that determined by the surroundingcontext. Sometimes it is desirable to make those values be exactlythe ones being defined locally. This is particularly true in the caseof defining a recursive function locally. For example, suppose forsome reason we wished to apply a local definition of the factorialfunction. The following would not work:

f(N) = N < 2 ? 1 : N*f(N-1), f(10);

- The reason this doesn't work is that the f on the RHS of the equation (but not the one after the comma) is not the local f, but rather the surrounding f, if indeed there is one. In order to make both f's be the same, so that recursion will work, we need to use a recursive local definition, signified by braces {....}. The proper way to define and use f is:
**System Commands**

{ f(N) = N < 2 ? 1 : N*f(N-1); f(10) };

In general, the expressions inside braces consist of some number of equations terminated by semi-colon, followed by an expression, the value of which becomes the value of the overall brace expression. Another use of local recursive definitions is in infinite-list functions with loops. For example, to define a function which is the infinite repetition of an item *X*, without recomputing *X*, we can define

repeat(X) = { Y = [X |$ Y]; Y };

Here it is *Y* which is the same on both the left- and right-hand sides of the equation `Y = [X |$ Y]`

.

System commands look just like expressions to be evaluated, butthey generally have side-effects, such as reading a rex source file.The "function" sys is thus not really a mathematical function. Thesecond argument to sys is interpreted literally as one of a number ofsub-commands, and there will usually be additional arguments, whichare either literal or evaluated, depending on the sub-command.

The `in` sub-command:

`sys(in, Filename)`

Here *in* is literal and `Filename` is an expressionwhich must evaluate to a string. That string is looked up accordingto the usual interpretation and loaded as a series of rexexpressions.

The `on and off` sub-commands:

`sys(on, Flag)`

`sys(off, Flag)`

Here *on* and *off* are literal and `Flag` isinterpreted literally (without evaluation). The corresponding flag isturned on or off. The following are **possible flags**:

`ftrace`: turn on the function trace`nonstop`: for a large amount of output, don't stop after a certain number of items`show_quotes`: show quotes around strings and characters when they are printed`show_parse`: show the result of parsing the rex expression`defer`: when tracing deferred computations, don't indent trace to the level at which the seed was sown`show_original`: when tracing, show the original unevaluated expression on lines where a result is shown (on by default)`ptrace`: trace the action of the rex parser`ttrace`: trace the start and completion of threads

The `get and set` sub-commands:

`sys(set, Variable, Value)`

`sys(get, Variable)`

Here *set* and *get* are literal. The expressionsets or gets the value of system variable as indicated. Thefollowing system variables aresupported:

`limit`: limit on number of items printed on a line`conc`: concurrency level (multithreading only)`threads`: the number of threads not completed (get only)`env`: the environment of the current rex expression (get only)

**Trace Commands**

To trace or not trace function entry and exit, use one of

`*t`

- toggles the function trace

`sys(on, ftrace);`

- turns the trace on

`sys(off, ftrace);`

- turns the trace off

**Interrupting rex**

To interrupt rex while in evaluation, type control-c once ortwice. You will be offered a menu of possible options, such as:

Interrupt: Please select one of the following: a - abort to top level b - enter break loop c - continue where program left off f - continue with ftrace on h - enter the help loop n - continue with ftrace off s - continue in line-by-line stop mode q or control D - quit the program

In UNIX implementations, a file name to be read initially as rexsource can be specified on the command line. Example, with thebold-face representing what the user types:

UNIX >rex fac.rexfac.rex loaded 1 rex >fac(10);3628800

In addition to the full examples below, see other examples in thetext such as gcd. Below we show the definitionwith a sample interactive execution.

composecomposes two unary functionscompose(F, G)(x) = F(G(x)); compose(sq, sq)(4) ==> 256fibsis a way of defining the Fibonacci sequence with a "loop"fibs = [1, 1 |$ map(+, fibs, rest(fibs))]; fibs ==> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, ... prodis a parallel productprod(M, N) => M >= N ? M; prod(M, N) => Median = (M+N)/2, bottom = sow(prod(M, Median)), // creates parallel thread top = prod(Median+1, N), bottom*top; prod(1, 10) ==> 3628800 9 threads created, 9 threads completedinnercomputes the inner product of two lists, using an accumulatorinner(X, Y) = inner_aux(X, Y, 0); inner_aux([], _, Acc) => Acc; inner_aux(_, [], Acc) => Acc; inner_aux([A | X], [B | Y], Acc) => inner_aux(X, Y, Acc+A*B); inner([1, 2, 3], [4, 5, 6]) ==> 32

**Grammar**

This is a simplified grammar. Some constraints and nuances are notshown. The following without quotes are meta-symbols: ( ) | -> { }{....} means "any number of repetitions of", including zero. Commentsfollow // to end-of-line.

input_item -> definition ';' | rule ';' | term ';' definition -> head '=' body head -> var_head | function_head function_head -> identifier var_list { '(' var_list ')' } var_head -> identifier | '[' var_head_list ']' var_list -> empty | identifier { ',' identifier } var_head_list -> var_head { ',' var_head } | var_head { ',' var_head } '|' var_head rule -> match_head '=>' body match_head -> identifier '(' match_list ')' match_list -> empty | match_term { ',' match_term } match_term -> identifier | constant | identifier '+' numeric_constant | '[' match_list ']' | '[' match_list '|' match_term ']' body -> term '?' term // guard | { definition ',' } term // equational guard term -> or_exp '?' term ':' term | or_exp or_exp -> and_exp { '||' and_exp } and_exp -> not_exp { '&&' not_exp } not_exp -> { '!' } rel_exp rel_exp -> add_exp comp_op add_exp comp_op -> '!=' | '>=' | '>' | '==' | '<=' | '<' add_exp -> mul_exp { add_op mul_exp } add_op -> '+' | '-' mul_exp -> un_exp { mul_op un_exp } mul_op -> '*' | '/' | '%' un_exp -> { '-' | '$' } primary primary -> constant | '(' term ')' | '[' list ']' | '[' list | term ']' | identifier { '(' list ')' } // variable or function application list -> empty | term { ',' term } constant -> numeric_constant | string_constant | char_constant string_constant -> '"' { char } '"' // e.g. "a123" char_constant -> ''' char ''' // e.g. 'a' or '\n' numeric_constant -> sign digits exponent | sign digits '.' exponent | sign '.' digits exponent | sign digits '.' digits exponent sign -> '+' | '-' | empty // optional sign exponent -> ( 'e' | 'E' ) sign digits | empty // optional exponent digits -> digit { digit } identifier -> letter { letter | digit } letter -> 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'|'k'|'l'|'m' |'n'|'o'|'p'|'q'|'r'|'s'|'t'|'u'|'v'|'w'|'x'|'y'|'z' |'A'|'B'|'C'|'D'|'E'|'F'|'G'|'H'|'I'|'J'|'K'|'L'|'M' |'N'|'O'|'P'|'Q'|'R'|'S'|'T'|'U'|'V'|'W'|'X'|'Y'|'Z' |'_' digit -> '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' char -> any ascii character | '\' any ascii character // escape sequence empty -> // the empty string

**Alphabetic Listing of all Functions**

- abs: absolute value
- ack: Ackermann's function
- all: whether all of a sequence satisfies predicate
- append: append one list to another
- array: create array given elements
- array_from_list
- asin: inverse sine
- atan: inverse tangent
- asinh: inverse hyperbolic sine
- acosh: inverse hyperbolic cosine
- atanh: inverse hyperbolic tangent
- atomic: whether datum is atomic (not list or array)
- builtin: specify builtin function by name and arity
- ceil (ceiling): smallest integer greater than
- close: closes an ostream
- concat: concatenate strings
- cons: construct list from items and list
- cos: cosine
- cosh: hyperbolic cosine
- defined: get list of defined (non-builtin) identifiers
- diff: list difference
- disable: enable a built-in function
- divides: whether one integer divides another
- drop: drop items from a list
- enable: enable a built-in function
- endl: sends an end-of-line to an ostream
- eof: test end-of-file condition
- erf: error function
- erfc: complementary error function
- eval: evaluate constructed expression
- every: whether all elements satisfy a predicate
- exec: call operating system command
- explode: explode a string into a list of chars
- extract: move item satisfying predicate to front of list
- fac: factorial function
- find: find where item identified by predicate first occurs in list
- find: gives index at which item first occurs in list
- find: gives list of indices at which item first occurs in list
- finite: check floating-point number for finiteness
- first: first element of a list
- floor: greatest integer less than
- float: floating-point value of number
- for: iteration command
- frexp: decompose a floating-point number
- from: numbers from a given number
- grow: wait for result of evaluation
- id: identity function
- implies: logical implication
- implode: string from a list of chars
- inchars: read chars from input as a list
- insexp: input single S expression from a file
- insexps: input S expressions as an incremental list
- integer: integer part of a number
- isnan: check floating-point number for being NaN
- is_array: determine whether type is array
- is_builtin: determine whether type is builtin
- is_channel: determine whether type is channel
- is_char: determine whether type is char
- is_error: determine whether type is error
- is_floating: determine whether type is floating
- is_function: determine whether type is user-defined or builtin
- is_integer: determine whether type is integer
- is_list: determine whether type is list
- is_number: determine whether type is integer or floating
- is_prime: determine whether integer is prime
- is_sequence: determine whether type is list or array
- is_string: determine whether type is string
- isalpha: determine whether argument is alphabetic
- iscntrl: determine whether argument is a control character
- isdigit: determine whether argument is a digit
- islower: determine whether argument is lower-case
- ispunct: determine whether argument is punctuation
- isspace: determine whether argument is whitespace
- isupper: determine whether argument is upper-case
- keep: keep elements satisfying a predicate
- k: konstant function
- lconcat: concatenate list of strings
- ldexp: compose a floating-point number
- leaves: leaves of a list or array
- leafcount: the number of leaves of a list or array
- length: length of list, array, or string
- list: make a list with given elements
- list_from_array
- log (logarithm): natural logarithm
- make_array: make array given size and function
- make_number: make a number from a string
- make_string: make a string from a number or char
- map: map function over array or list
- map_tail: map function over list with tail
- mapppend: map function over list and append results
- mapppend_tail: map function over list and append results, with tail
- max: maximum of arguments
- member: whether item occurs in list or array
- merge: merge ordered lists together
- min: minimum of arguments
- no: whether no item in list satisfies predicate
- null: whether list is empty
- outsexp: output single value as S expression to a file
- outsexps: output S expressions as a list
- pmap: parallel version of map
- pow: arithmetic power
- prefix: prefix of list or array
- primes: infinite list of prime numbers
- primes_from: infinite list of prime numbers from a given number
- primes_to: list of primes up to a given number
- quote: take argument literally
- random: infinite list of random numbers
- range: list of numbers in a range
- readchars: input single char
- readchars: makes istream of chars into incremental list
- readsexp: input single S expression from istream
- readsexps: makes istream of S expressions into incremental list
- inline: input single line from istream
- reduce: apply binary operator to a list
- remove_duplicates: remove duplicates from a list
- repeat: repeat command
- rest: all but the first item in a list
- reverse: reverse of list or array
- scale: multiply array or list by a factor
- scan: successive applications of binary operator
- second: second item in a list or array
- set: set a variable destructively
- sign: sign of a number
- sin: sine function of a number
- sinh: hyperbolic sine function of a number
- some: whether some item in list satisfies predicate
- sow: evaluate in a separate thread
- spec: specify function by name and arity
- sq (square):
- sqrt (square root)
- sys: system command
- tan: tangent function of a number
- tanh: hyperbolic tangent function of a number
- test: test evaluation of an expression
- third: third item in list or array
- type: type of a datum
- while: while command
- words: create a list of words from string
- zip: interleave lists or arrays
- undef: un-define a global variable
- writesexp: output a single S expression to an ostream
- + (addition)
- - (subtraction)
- * (multiplication)
- / (division)
- % (modulus, remainder)
- !=
- >
- <
- <=
- ! (not)
- && (and)
- || (or)
- $

- RCS ID: $Id: rex.html,v 1.29 1996/06/25 19:09:14 keller Exp keller $