System commands |
Datatypes |
Variables |
Operators |
Expressions |
Input/output |
Special commands |
Flow control |
Enhanced types |
Arrays |
Dictionaries |
Stacks |
Strings |
User defined functions |
Inbuilt functions |
System commands
System commands are used to configure aspects of the interpreter or to interact with
the host system, and are prefixed by a forward slash.
| Function | Command | Description |
| // | Comment | Indicates all subsequent entry on the current line is comment |
| /cd dir | Change directory* | change working directory to 'dir' |
| /d n | Set denominator | Set max denominator to n for decimal to rational conversion. If the argument is missing or invalid, the default value of 1000000 is used. |
| /f | Fraction printing | Toggle printing fractions as decimals. |
| /h command | Help | Return a description of the given command |
| /l n | Set print length | Set the max length for printed value strings |
| /p | Implicit printing | Toggle implicit printing of command results |
| /q | Quit* | Quit the interpreter |
| /r abc | Run script | Run script file "abc" |
| /s abc | Shell command* | Execute shell command "abc" |
| /t | Time calculations | Print out the time taken by the calculations |
| /v | Version | Print the version number |
*Command is not supported on the iPhone or iPad
| Type | Description |
| NaN | represents any uninitialised or invalid value |
| byte | 8 bit unsigned type |
| integer | signed integer |
| rational | integer numerator over integer denominator |
| decimal | floating point representation of a real number (native double type) |
| complex | floating point complex number |
Integers are represented using the native long word type unless too large, in which case an arbitrary precision representation is used. Conversion is automatic for appropriate pure integer operations, however many functions that work with integers will either fail with an arbitrary precision integer argument, or convert to decimal prior to evaluation. Explicit support for arbitrary precision integers is implemented in all basic arithmetic operations and rational powers, as well as calculation of factorials, binomial coefficients, LCMs, GCDs and factorisation.
Arbitrary precision is not supported for rational and complex types.
Named variables are assigned using the ~ operator. User-defined variables must start with a lowercase letter and be comprised of alphanumeric characters only. The $ symbol is used to represent the result of the last complete calculation, and assignment to . clears a defined variable.
| Operators | Description |
| + | copy |
| ^ | exponent |
| - | unary minus |
| ! | logical negate |
| !! | bit negate |
| ++, -- | increment and decrement (no pre/post distinction) |
| *, /, %, /% | multiply, divide, modulus and integer division |
| ** | matrix multiply |
| +, - | add and subtract |
| <<, >> | shift left and shift right |
| ?? | type |
| <, > | less than and greater than |
| <=, >= | less than or equal, greater than or equal |
| =, != | equal, not equal |
| &&, ^^, || | bit and, bit xor, bit or |
| &, | | logical and, logical or |
| (...) | brackets for grouping |
Note that the bit boolean operators are consistently a doubled version of the associated logical operator.
An expression is any syntactically correct sequence of values, operators and identifiers that defines a calculation. Distinct expressions on a single line are separated by a ; character. Types are inferred and automatic numeric promotion is applied where appropriate.
Interaction with the interpreter is by entering (or reading from a text file) a sequence of expressions to be calculated.
| Command | Description |
| ] | An instruction to print the value of the following expression with a new line |
| ]XXX,YYY | prints with a single space separation on the same line |
| ]XXX:YYY | prints without separation on the same line |
| ]%XXX | prints and suppresses the following new line |
| @ | prompt for a value to be entered |
Recall that if implicit printing is on (see System Commands) then the result of any non-assignment expression will be printed automatically.
# // set implicit printing for calculator like operation
# /p
Implicit printing on
# 7 + 3^2 * 2
25
# 26 / 6 - 4
1/3
# Dec $
0.33333333333333
# 0.5 * 0.72
0.36
# Frac $
9/25
# (3 + 2*I) * (3 - 2*I)
13
# a ~ 3 + 2*I
# b ~ 3 - 2*I
# c ~ a * b
# ]a,b,c
(3+2i) (3-2i) 13
# 253^25
1196776435607632482790118858840382391829660917532091147865693
# 23481729348712983749123847123 * 9812793847238273418273
230421369275565156221292747340623890303817486678579
#
| Command | Description |
| ]] | print all user-defined variables and functions |
| .. | clear all user-defined variables and functions |
These commands may not form part of an expression, but must comprise the entire input line on entry.
Conditional and repeat evaulation of expressions is controlled by the following operators:
| Command | Description |
| ? {X} {Y} | If expression X evaluates true (i.e. non-zero) then expression Y is evaluated. |
| ?: {X} {Y} {Z} | If expression X evaluates true (i.e. non-zero) then expression Y is evaluated, otherwise expression Z is evaluated. |
| ?+ {X} {Y} | While expressions X evaluates true, evaluate expression Y. |
| ?+ n {Y} | Evaluate expression Y n times, where n is either an integer valued constant or expression. |
| ?+ a {Y} | For a an array (see Enhanced types), evaluate Y once for each element in the array. |
For all of these, the return value is the value of the last expression evaluated. The >< operator in the {Y} expression will terminate the loop, and within a loop, the symbol _ acts as an identifier representing the current innermost loop index (up to 10 levels of nesting supported).
If the loop has the form ?+ a {Y} where a is an array of any type, the expression Y is evaluated once for each element of the array a, and the implicit loop variable _ returns each array element in turn.
If the conditional expression X is an array or stack, the check is for non-empty.
# a~11
# // if a is greater than 10, set it to a mod 10
# ? {a > 10}{a ~ a%10}
# // print the resulting value of a
# ]a
1
# // if a is greater than 10, set it to a mod 10, otherwise add 10 to its value
# ?: {a > 10}{a ~ a % 10}{a ~ a + 10}
# ]a
11
# // while a is greater than 5, print it and reduce its value by 1
# ?+ {a > 5}{]a;a--}
11
10
9
8
7
6
# // loop 5 times, printing the implicit loop counter and its square
# ?+ 5{]_,_^2}
1 1
2 4
3 9
4 16
5 25
# // create the array [1 2 3 4 5]
# b ~ [1:5]
# // loop through its elements, printing them and their squares
# ?+ b{]_,_^2}
1 1
2 4
3 9
4 16
5 25
#
| Command | Description |
| array | indexed collection of values of any type |
| stack | LIFO stack of values of any type |
| string | NULL(0) terminated string of characters |
| dictionary | pair of equal length arrays, the first providing the keys and the second the values |
The ?? operator will return the type of any given expression as a string.
| Command | Description |
| [[n]] | An array of n uninitialised values, where n is an integer constant, variable or expression. If n is a stack, then each entry is added to the array |
| [i:j] | An array of values from i to j in steps of 1 (i, j constants or expressions) |
| [i:j:k] | An array of values from i to j in steps of k (i, j, k integer, rational or float constants or expressions) |
| a~[l m n...] | An array initialised to contain the specific values listed (l, m, n constants or bracketed expressions) |
Arrays support all standard operations, either applying to correponding elements for equal-length arguments, or applying a single value across all array elements. In addition, the following operations for acting on the array explicitly are also available:
| Operator | Operation | Description |
| ' | index | integer constant or integer array argument for element selection |
| # | size | returns the number of elements in the array |
| : | head | returns the first element of the array |
| ` | tail | returns all but the first element of the array |
| <- | index in | x <- a returns the index of x in array a, or false ($0) if not present |
| :: | append | a::b appends the value or array b to the array a |
| ## | choose | a##b returns those entries from array a selected by the non-zero elements of the byte array b |
Arrays can be passed in place of single value function arguments where it makes sense — the functions will map over all values. However, this can lead to some unexpected results when the argument is interpreted literally as an array. For example, consider the expression:
?: {x%2}{"odd"}{"even"}that evaluates to "even" if x is an even integer, and otherwise to "odd". If x is an array, it will not result in an array of corresponding strings "even" and "odd", but rather the conditional expression will simply test whether or not the array is empty. If this is not the desired behaviour, the standard library function Apply can be used to ensure the condition is evaluated element by element.
Dictionaries associate an array of keys [k] with an (equally sized) array of values [v] and are defined using d ~ [k]->[v].
Most array operations have analagous version that applies to dictionaries.
| Operator | Operation | Description |
| ' | key | d'key returns the associated value (analagous to arrays) and can be used in assignment and deletion |
| # | size | returns the number of elements in the dictionary |
| : | keys | returns the key array (by analogy with head) |
| ` | values | returns the value array (by analogy with tail) |
| <- | key in | value<-d returns the key for the given value in dictionary d |
| :: | append | Appends two dictionaries. This fails if there are duplicate keys. |
<s> n1 n2 op1 n3 ( expr )
There are several stack specific operations.
| Operator | Operation | Description |
| # | depth | returns the number of elements in the stack |
| . | pop | <a b c ...> . → <b c ...> |
| @ | rot | <a b c ...> @ → <b c a ...> |
| : | dup | <a b ...> : → <a a b ...> |
| / | over | <a b ...> / → <b a b ...> |
| \ | swap | <a b ...> \ → <b a ...> |
| ! | neg | <a b ...> ! → <-a b ...> |
# // allocate a 3 element array - all values are uninitialised
# a~[[3]]
# ]a
[ NaN NaN NaN ]
# // set values for the first two elements
# a'1~5
# a'2~6
# ]a
[ 5 6 NaN ]
# // define a new array and initialise as an arithmetic sequence from 1 to 7 in steps of 2
# b~[1:7:2]
# ]b
[ 1 3 5 7 ]
# // and another from -1 to 0 in steps of 0.1
# c~[-1:0:0.1]
# ]c
[ -1 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0 ]
# //perform a calculation on all elements at once
# ]5 * c + 1
[ -4 -3.5 -3 -2.5 -2 -1.5 -1 -0.5 0 0.5 1 ]
# // array elements can be themselves arrays
# d ~ [1 7 b 26 [1 5 3]]
# ]d
[ 1 7 [ 1 3 5 7 ] 26 [ 1 5 3 ] ]
# // get the number of elements
# ]#d
5
# // select the 5th element
# ]d'5
[ 1 5 3 ]
# // loop through and print each element
# ?+ d {]_}
1
7
[ 1 3 5 7 ]
26
[ 1 5 3 ]
#
# // Now try using a dictionary
#
# keys ~ [1:5]
# values ~ [1:5]^2
# dict ~ keys->values
# ]dict
1->1
2->4
3->9
4->16
5->25
# // select entries where the key is even
# ]dict'keys##!(keys%2)
[ 4 16 ]
# // select entries where the value is greater than 10
# sel~keys##values>10
# ]sel->dict'sel
4->16
5->25
#
# // And now try a string
#
# s ~ "Hello World"
# ]:s
$48
# ]`s
ello World
# ]s'3
$6C
# ]s'[3:6]
lo W
# ]s::"X"
Hello WorldX
# ]Rev s
XdlroW olleH
#
Functions are defined using the syntax name () argument list, e.g.
f () a b ~ a * a + bCompound expressions require braces
f () x y ~ { expr1; expr2;... }
f () x:xs ~ {x + f xs} {x}Multiple recursive calls in the function definition are explicitly unsupported.
It is not possible to define a function using a name that is already being used by a variable, or vice versa.
If desired, parameter type info can be associated with function arguments by using the following forms in the argument list definition (compare the output of the ?? operator described in the section on enhanced types):
Global variables are not visible inside a function, and any new variables declared within a function body are local in scope and deleted on function exit. If access to a global is required, it's identifier must be prefixed with an underscore — i.e. _a will reference global variable a. Argument names in function definitions are merely markers to be replaced with generic, locally scoped identifiers on invocation.
Function arguments may also be operators, defined using the syntax @<digit>, or other functions, defined using the syntax @<letter>.
For example, we can define a function that evaluates any single argument function given as its argument for value 3 using
f3 () @f ~ @f 3and invoke it as
f3 @Log
Similarly a function that folds a list using an arbitrary binary operator can be defined using an operator parameter and recursive syntax
f () x:xs @1 ~ {x @1 f xs @1}{x}and invoked as
f [1:4] +or
f [1:4] *for example.
There is no support for variables holding functions as values, but strings can be used to represent the function arguments as follows:
s~"@Log"; f3 s
Some standard library functions, as well as user-defined functions as described above, require a function as an argument. An anonymous function is a convenient way to create a function that is not required to persist beyond the particular invocation and pass it in as the argument.
The syntax is an extension of the usual @<name> function argument syntax, but with the anonymous function body being included between following braces. Up to 9 parameters are supported, using the notation ?n with n ranging from 1 to 9. Expressions are supported, but any variables must be accessed using the global scope operator _.
For example,
Apply @{GDist 0 1 ?1} [1:10]will perform exactly as if we had defined the function
f () x ~ GDist 0 1 xand then called
Apply @f [1:10]
This example shows using an expression and accessing a variable
# a ~ [[10]]Anonymous functions are particularly convenient for plotting
# p ~ 0.5
# t ~ 10
# FnFill a @{BRand _p (10 * _t)}
[ 59 46 44 55 44 54 53 54 45 60 ]
FLinePlot @{CCDF 0 1 ?1} [-5:5:0.1] AxesPlotDefs LineDefsand random array generation
a~[[10]];FnFill a @{GRand 10 5}The Apply2D function requires a 2 parameter function argument. In this next example an anoymous function is used to calculate the probability of up to 2 successes across a range of binomial trials (3 to 5 in this example) with probability of success from 10% to 50%:
# Apply2D @{BCDF 2 ?1 ?2} [3:5] [0.1:0.5:0.1]Here is a mutiple parameter example involving a user-defined function:
[ 0.999 0.9963 0.99144
0.992 0.9728 0.94208
0.973 0.9163 0.83692
0.936 0.8208 0.68256
0.875 0.6875 0.5 ]
# // define a 4 parameter function
# g () a b c d ~ a * b * c * d
# // the f123 function calls a passed in 3 argument function with argument values 1, 2 and 3
# f123 () @f ~ @f 1 2 3
# // Use an anonymous function to map between the two — using a fixed value of 100 as the 1st argument to g
# f123 @{g 100 ?1 ?2 ?3}
600
Anonymous functions are not only useful for managing arguments to other functions, but can consist of arbitrary expressions involving the automatic parameters as in the following example:
# Apply2D @{?1^?2 + ?1} [1:3] [1:3]
[ 2 4 6
2 6 12
2 10 30 ]
A comprehensive standard library of built in functions is provided and documented here. All inbuilt start with a capital and cannot be deleted or redefined.