Language reference
Summary
Symbols
nil, t, nothing, *features*
Reader macros
#', #*, #., #\, #(, #nA, #|, #b, #o, #x
List functions
cons, car, first, cdr, rest, caar, cadr, second, cdar, cddr, caaar, caadr, cadar, caddr, third, cdaar, cdadr, cddar, cdddr, list, copy-list, append, length, reverse, nth, sort
Array functions
make-array, length, aref, arrayp, array-dimensions
Defining variables and functions
lambda, defun, defvar, setq, set, let, let*
Arithmetic functions
+, -, *, /, mod, 1+, 1-, abs, random, max, min
Arithmetic comparisons
=, <, <=, >, >=, /=, plusp, minusp, zerop, oddp, evenp
Bitwise operations
logand, logior, logxor, lognot, ash, logbitp
Conditionals
if, cond, when, unless, case, and, or, not
Tests
null, atom, listp, consp, numberp, streamp, eq, equal, symbolp, boundp
Characters
char, char-code, code-char, characterp
Strings
string/=, string<, string<=, string=, string>, string>=, stringp, string, concatenate, read-from-string, prin1-to-string, princ-to-string, with-output-to-string
Evaluation
Strings and lists
Iteration
loop, return, dolist, dotimes, do, do*
Mapping
mapc, mapcar, mapcan, mapcon, mapl, maplist, assoc, member
In-place operations
Error handling
unwind-protect, ignore-errors, error
Documentation
?, documentation, apropos, apropos-list
Input/output
read, print, princ, prin1, pprint, pprintall, terpri, read-byte, write-byte, read-line, write-line, write-string, format
System functions
globals, makunbound, break, gc, save-image, load-image, edit, room, time, trace, untrace, sleep, require, list-library, register
Arduino interface
millis, for-millis, with-i2c, restart-i2c, with-serial, with-spi, with-sd-card, pinmode, digitalread, digitalwrite, analogread, analogreference, analogreadresolution, analogwrite, analogwriteresolution, delay, note
Floating-point extensions
For the floating-point extensions see Floating-point extensions.
#' reader macro
Ignored.
The sequence #' is ignored, to allow you to paste in Common Lisp programs that need to include it before function names in some contexts.
#* reader macro
Introduces a one-dimensional bit array. For example:
> #*10100100010000
#. reader macro
The atom or form after the #. is evaluated when the code is read in.
#\ reader macro
Allows you to enter a character.
The sequence #\ can be followed by one of the following three options:
- A single ASCII character
- One of the following strings representing a control code:
Null, SOH, STX, ETX, EOT, ENQ, ACK, Bell, Backspace, Tab, Newline, VT, Page, Return, SO, SI,
DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, CAN, EM, SUB, Escape, FS, GS, RS, US, Space
- A number between 000 and 255 representing the decimal character code of the character.
#( reader macro
Introduces a one-dimensional array.
For example:
> #(6 28 496 8128) #(6 28 496 8128)
#nA reader macro
Introduces an n-dimensional array.
For example:
> #2A((1 2 3) (2 4 6)) #2A((1 2 3) (2 4 6))
#| reader macro
Introduces a multi-line comment.
All the text between #| and |# is ignored.
#b, #o, #x reader macros
Allow you to enter numbers in binary, octal, or hexadecimal notation.
For example:
> #xFFFF -1 > #b0101010101010101 21845 > #o777 511
' special form
Syntax: 'item
Quotes the argument.
'(+ 1 2)
is a shorthand for:
(quote (+ 1 2))
* function
Syntax: (* number*)
Multiplies its arguments together.
*features* special form
Syntax: *features*
Returns a list of keywords representing the capabilities of this version of uLisp.
The following features are available:
Feature | Description |
:floating-point | Floating-point arithmetic, in addition to integers; see Floating-point extensions. |
:arrays | Arrays. |
:documentation | Integral documentation; see Integral documentation. |
:machine-code | Machine-code and assembler programming. |
:error-handling | Error handling using unwind-protect, ignore-errors, and error. |
:wi-fi | Wi-fi extensions; see Wi-Fi extensions. |
:gfx | Graphics extensions; see Graphics extensions. |
For example:
> *features* (:floating-point :arrays :documentation :machine-code :error-handling :wi-fi :gfx)
You can use member to test whether a particular feature is supported.
Note that *features* is not a regular variable and cannot be modified.
+ function
Syntax: (+ number*)
Adds its arguments together.
- function
Syntax: (- number*)
If there is one argument, negates the argument.
If there are two or more arguments, subtracts the second and subsequent arguments from the first argument.
/ function
Syntax: (/ number*)
If there is one argument, inverts the argument (floating-point platforms only).
If there are two or more arguments, divides the first argument by the second and subsequent arguments.
For example:
> (/ 60 2 3)
10
/= function
Syntax: (/= number*)
Not equal. Returns t if none of the arguments are equal, and nil if two or more arguments are equal.
A potential source of confusion is that this function is called "!=" in C.
1+ function
Syntax: (1+ number)
Adds one to its argument and returns it.
> (1+ (* 3 3))
10
(1+ x) is a shorter way of writing (+ x 1).
1- function
Syntax: (1- number)
Subtracts one from its argument and returns it.
> (1- (* 3 3))
8
(1- x) is a shorter way of writing (- x 1).
; (semicolon)
Introduces a comment line, which will be ignored. For example:
; Factorial function
(defun f (n) (if (= n 0) 1 (* n (f (- n 1)))))
Because the Arduino Serial Monitor removes line endings uLisp ignores all characters after a semicolon up to the next opening bracket. This imposes a couple of restrictions in the use of comments:
- Comments should not include an opening bracket.
- Comments are not valid if they are not followed by an opening bracket; for example:
(defvar data '(#x01 ; Invalid comment #x20))
In this situation you can use a multi-line comment instead; see #|.
A comment line turns off echo so that by starting a long listing with a comment, it can safely be pasted in to the Arduino IDE's Serial Monitor without overflowing the serial buffer. Echo is turned back on automatically after a one second delay if there is no activity on the serial input.
< function
Syntax: (< number*)
Returns t if each argument is less than the next argument, and nil otherwise.
<= function
Syntax: (<= number*)
Returns t if each argument is less than or equal to the next argument, and nil otherwise.
= function
Syntax: (= number*)
Returns t if the arguments are numerically equal, and nil otherwise.
For example:
> (= (* 4 3) (* 2 6) (* 1 12))
t
To add documentation to a user-defined function see defun.
> function
Syntax: (> number*)
Returns t if each argument is greater than the next argument, and nil otherwise.
>= function
Syntax: (>= number*)
Returns t if each argument is greater than or equal to the next argument, and nil otherwise.
? special form
Syntax: (? symbol)
Prints documentation about the built-in or user-defined function symbol.
For example:
> (? maplist) (maplist function list1 [list]*) Applies the function to one or more lists and then successive cdrs of those lists, and returns the resulting list.
For information about adding documentation to a user-defined function see defun.
abs function
Syntax: (abs number)
Returns the absolute, positive value of its argument.
analogread Arduino function
Syntax: (analogread pin)
Reads the specified Arduino analogue pin number and returns the value.
For details of the available pins see the appropriate board description on this site.
On most processors the analogue inputs are 10 bits, so the value is a number between 0 and 1023.
If you prefer to use the pin labels A0, A1, etc you can define appropriate variables; for example, for the Arduino Zero:
(defvar A0 15)
analogreadresolution Arduino function
Syntax: (analogreadresolution bits)
Sets the analogue read resolution for the analogue inputs on platforms that support it. The default resolution on all platforms is 10 bits.
For details of the options available see the appropriate board description on this site.
analogreference Arduino function
Syntax: (analogreference keyword)
Selects the analogue reference voltage used for analogue input.
For details of the available keywords see the appropriate board description on this site.
analogwrite Arduino function
Syntax: (analogwrite pin value)
Writes the value to the specified Arduino pin number.
For details of the available pins see the appropriate board description on this site.
On most processors the analogue outputs are 8 bits, so the value is a number between 0 and 255. For example:
(analogwrite 3 127)
analogwriteresolution Arduino function
Syntax: (analogwriteresolution value)
Sets the analogue write resolution.
and special form
Syntax: (and item*)
Evaluates its arguments until one returns nil, and returns the last value. It's usually used to combine conditions. For example, pos tests whether something is a positive number:
(defun pos (a) (and (numberp a) (> a 0)))
append function
Syntax: (append list*)
Joins its arguments, which should be lists, into a single list.
For example:
> (append '(1 2 3) '(4 5 6) '(7 8 9))
(1 2 3 4 5 6 7 8 9)
apply function
Syntax: (apply function list)
Returns the result of evaluating the function specified by the first argument with the list of arguments specified by the second parameter. So, for example:
> (apply cons '(a b))
(a . b)
This is equivalent to (cons 'a 'b).
apropos function
Syntax: (apropos item)
Prints the user-defined and built-in functions and variables whose names contain the specified string or symbol.
For example:
> (defun catty () "meow") catty > (apropos "cat") catty (user function) truncate (function) concatenate (function)
You could also write:
(apropos 'cat)
apropos-list function
Syntax: (apropos-list item)
Returns a list of the user-defined and built-in functions and variables whose names contain the specified string or symbol.
For example:
> (defun catty () "meow") catty > (apropos-list "cat") (catty truncate concatenate)
You could use this to write a function that prints out the documentation for all functions containing a string:
(defun all-doc (pat) (mapc #'(lambda (symbol) (format t "~a~%~%" (documentation symbol))) (apropos-list pat)) nothing)
For example, try:
> (all-doc 'map)
array-dimensions function
Syntax: (array-dimensions item)
Returns a list of the dimensions of an array. For example:
> (array-dimensions #2A((1 2) (3 4) (5 6))) (3 2)
You can also use length to get the length of a one-dimensional array.
arrayp function
Syntax: (arrayp item)
Returns t if its argument is an array.
aref function
Syntax: (aref array index [index*])
Returns an element from the specified array. The aref function can be used to return a value as in:
(print (aref a 99))
To access elements in a multi-dimensional array you need to give an index for each dimension; for example:
(print (aref b 2 3))
The aref function can also be used with the in-place operations setf, incf, and decf to change an element of an array; for example, to change the value of an array element:
(setf (aref b 42) 3.14159)
or to increment an element:
(incf (aref c 99))
ash function
Syntax: (ash value shift)
Returns the result of bitwise shifting value by shift bits. If shift is positive, value is shifted to the left. For example:
> (ash 7 3) 56
If shift is negative, value is shifted to the right. For example:
> (ash 15 -2) 3
The right shift is an arithmetic shift, so the sign bit is preserved; for example:
> (format t "~x" (ash #x8000 -8)) ff80
assoc function
Syntax: (assoc key list [:test function])
Looks up a key in an association list of (key . value) pairs, and returns the matching pair, or nil if no pair is found.
Example:
> (assoc 'c '((a . 1) (b . 2) (c . 3) (d . 4))) (c . 3)
The test function defaults to eq, but you can specify an alternative after a :test keyword; for example:
> (assoc "three" '(("one" . "eins") ("two" . "zwei") ("three" . "drei")) :test #'string=) ("three" . "drei")
Association lists are useful for storing complex data; for example you could use an association list to specify the colour of an RGB LED:
(setq col '((r . 127) (g . 63) (b . 255)))
You could then get one colour component using assoc:
> (cdr (assoc 'g col))
63
atom function
Syntax: (atom item)
Returns t if its argument is a single number, symbol, or nil.
Example:
> (atom 'b) t
> (atom '(a b))
nil
The function atom is the inverse of consp.
boundp function
Syntax: (boundp item)
Returns t if the argument has a value or nil otherwise.
> (boundp 'a) nil > (defvar a 23) a > (boundp 'a) t
break function
Syntax: (break)
Inserts a breakpoint in your uLisp program.
When the (break) function is evaluated you will be returned to the uLisp prompt, and you can then examine the values of parameters and local variables.
The uLisp prompt is preceded by a number giving the break level. Type nil to exit from break and continue execution.
For example:
> (let* (lis) (dolist (x '(a b c)) (setq lis (cons x lis)) (break))) Break! : 1> lis (a) : 1> nil Break! : 1> lis (b a)
caaar ... cdddr function
Syntax: (caaar list)
These are all equivalent to the corresponding sequence of car and cdr functions. For example,
(cdaar list)
is equivalent to:
(cdr (car (car list)))
car function
Syntax: (car list)
Returns the first item in a list.
> (car '(a b c d e f))
a
Equivalent to first.
case special form
Syntax: (case keyform ((key form*) (key form*) … ))
The case special form evaluates a keyform to produce a test key, and then tests this against a series of arguments, each of which is a list containing a key optionally followed by one or more forms.
If the test key equals the key the forms are evaluated, and the last value is returned as the result of the case. Otherwise none of the forms are evaluated, and the next argument is processed in the same way.
Specifying a key of t will always succeed.
In place of a single key you can specify a list of keys, any of which will match the test key.
The following example prints a different string according to the value of animal:
(case animal (cat (print "maiou")) (dog (print "woof")) ((sparrow thrush) (print "tweet")) (t (print "don't know"))
char function
Syntax: (char string n)
Returns the nth character in a string, counting from zero.
Example:
> (char "uLisp" 1) #\L
char-code function
Syntax: (char-code character)
Returns the ASCII code for a character, as an integer.
For example:
> (char-code #\return)
13
characterp function
Syntax: (characterp item)
Returns t if the argument is a character and nil otherwise.
cdr function
Syntax: (cdr list)
Returns a list with the first item removed.
> (cdr '(a b c d e f))
(b c d e f)
Equivalent to rest.
code-char function
Syntax: (code-char integer)
Returns the character for the specified ASCII code.
For example:
> (code-char 126) #\~
concatenate function
Syntax: (concatenate 'string string*)
Joins together the strings given in the second and subsequent arguments, and returns a single string. The second argument specifies the type of the result; uLisp only supports string.
Example:
> (concatenate 'string "One" "Two" "Three") "OneTwoThree"
cond special form
Syntax: (cond ((test form*) (test form*) … ))
The cond special form provides a more flexible conditional structure than the simpler functions if, while, and unless.
Each argument is a list consisting of a test optionally followed by one or more forms.
If the test evaluates to non-nil the forms are evaluated, and the last value is returned as the result of the cond.
If the test evaluates to nil, none of the forms are evaluated, and the next argument is processed in the same way.
The following example reads an analogue input and sets one of four outputs high depending on the value of the input:
(let* ((a (analogread 0))) (cond ((< a 64) (digitalwrite 2 t)) ((< a 128) (digitalwrite 3 t)) ((< a 192) (digitalwrite 4 t)) (t (digitalwrite 5 t))))
As in this example, the last test in a cond is usually t to provide the action to be performed when all the previous tests fail.
cons function
Syntax: (cons item item)
If the second argument is a list, cons returns a new list with item added to the front of the list. For example:
> (cons 'a '(b c d e))
(a b c d e)
If the second argument isn't a list cons returns a dotted pair:
> (cons 'a 'b)
(a . b)
consp function
Syntax: (consp item)
Returns t if its argument is a non-null list.
Example:
> (consp 'b) nil
> (consp '(a b))
t
The function consp is the inverse of atom.
copy-list function
Syntax: (copy-list list)
Returns a copy of a list.
This is useful to keep a copy of an original list before using a function that modifies it, such as sort or setf.
decf special form
Syntax: (decf place [number])
Subtracts one from the value of place, and returns the new value. The second argument place can be one of the forms:
symbol (car form) (cdr form) (nth n form) (aref array index [index*])
For more information see setf.
For example:
> (defvar a 123) a > (decf a) 122 > a 122
You can include an optional second argument to specify the decrement.
defun special form
Syntax: (defun name (parameters) [docstring] form*)
Allows you to define a function. For example:
(defun sq (x) (* x x))
This creates a function called sq with one parameter, x. When the function is called, the body is evaluated with x bound to the argument. For example:
> (sq 7)
49
This is equivalent to:
(defvar sq '(lambda (x) (* x x))
Optional arguments
You can specify optional arguments by giving the &optional keyword followed by the parameters you want to make optional. If an argument is not specified for an optional parameter it will have the value nil. For example, the following function rec calculates the area of a rectangle:
(defun rec (x &optional y) (if y (* x y) (* x x)))
It can be called with two arguments:
> (rec 3 4) 12
or one argument to calculate the area of a square:
> (rec 5) 25
You can specify a default value for any optional argument by specifying a list consisting of the optional argument followed by an expression. For example, the above definition could be written:
(defun rct (x &optional (y x)) (* x y))
Variable number of arguments
You can define a function that takes a variable number of arguments by giving the &rest keyword followed by a single parameter; this parameter is bound to a list of the remaining arguments.
For example, this defines a function out that defines any number of Arduino pins as outputs:
(defun out (&rest x) (mapc (lambda (p) (pinmode p t)) x))
You could call it with:
(out 4 5 6 7)
You can use both &optional and &rest in the same definition; for example:
(defun tst (x &optional y &rest z) (list "x=" x "y=" y "z=" z))
Trying it out:
> (tst 1 2 3 4 5) ("x=" 1 "y=" 2 "z=" (3 4 5))
Documentation
You can add documentation to a function by adding a documentation string docstring after the parameters. You can then display this using ? or documentation.
For example:
> (defun sq (x) "Squares a number" (* x x)) sq > (? sq) Squares a number
defvar special form
Syntax: (defvar variable form)
Defines a global variable. For example:
(defvar x 1000)
delay function
Syntax: (delay number)
Delays for a specified number of milliseconds. For example:
(delay 1000)
gives a one-second delay.
On the 16-bit platforms the maximum delay is 32767, or approximately 32 seconds. On the 32-bit platforms the maximum delay is 2147483647, or approximately 24 days.
See also for-millis.
digitalread Arduino function
Syntax: (digitalread pin)
Reads the state of the specified Arduino pin number and returns t (high) or nil (low).
The pin can also be the keyword :led-builtin.
digitalwrite Arduino function
Syntax: (digitalwrite pin state)
Sets the state of the specified Arduino pin number. The pins are the same as for digitalread above.
The pin can also be the keyword :led-builtin.
The state can be a keyword, or t or nil:
Keyword | Description |
:low or nil | Low level |
:high or t | High level |
do special form
Syntax: (do ((var [init [step])*) (end-test result*) form*)
Iterates over a group of forms until end-test is true. An arbitrary number of variables var can be initialised and are updated in parallel at the start of each iteration. Each variable can be given an initial value init, and can be updated by a step form.
In do each variable's init and step forms are evaluated in parallel.
The following example uses three variables, i, this, and next, and calculates the nth Fibonacci number:
(defun fib (n) (do ((i 0 (1+ i)) (this 0 next) (next 1 (+ this next))) ((= i n) this))) > (fib 10) 55
Often, as in this example, all the work is done in the variable forms, and there is no need for a do body.
do* special form
Syntax: (do* ((var [init] [step])*) (end-test result*) form*)
Iterates over a group of forms until end-test is true. An arbitrary number of variables var can be initialised and are updated in sequence at the start of each iteration. Each variable can be given an initial value init, and can be updated by a step form.
In do* each variable's init and step forms can refer to a previous variable in the list.
For example, the following function calculates the nth triangular number:
(defun triangular (n) (do* ((i 1 (1+ i)) (sum i (+ sum i))) ((= i n) sum))) > (triangular 10) 55
Again, in this example, all the work is done in the variable forms, and there is no need for a do* body.
documentation function
Syntax: (documentation 'symbol [type])
Returns the documentation string for the built-in or user-defined function symbol.
For example:
> (documentation 'nth) "(nth number list) Returns the nth item in list, counting from zero."
For information about adding documentation to a user-defined function see defun.
dolist special form
Syntax: (dolist (var list [result]) form*)
Sets the local variable var to each element of list in turn, and executes the forms. It then returns result, or nil if result is omitted.
dotimes special form
Syntax: (dotimes (var number [result]) form*)
Executes the forms number times, with the local variable var set to each integer from 0 to number-1 in turn. It then returns result, or nil if result is omitted.
For example, to flash an LED ten times:
(defun ten () (pinmode 13 t) (dotimes (x 10) (digitalwrite 13 t) (delay 500) (digitalwrite 13 nil) (delay 500)))
edit function
Syntax: (edit 'function)
Lets you step through a function definition, editing it a bit at a time, using the following single-key editing commands:
Command | Name | Description |
Enter | enter | Prettyprints the current form. |
a | car | Takes the car of the current form. |
d | cdr | Takes the cdr of the current form. |
r | replace | Replaces the current form with what you type in. |
c | cons | Conses what you type in onto the front of the current form. |
x | delete | Deletes the car of the current form. |
b | back | Backs up the tree. |
q | quit | Quits from the editor. |
To edit the function you type a series of a or d commands to step through the function to the part you want to edit, use r, c, or x to make changes, type b to go back, or type q to exit from the editor.
At any stage you can press Enter to print the current part of the function you've reached.
If you type an invalid key the editor prints ?, and if you reach the end of the tree with a or d the editor prints !. For more information see Using the program editor.
Note that for the editor to work properly you need to have the line ending option set to Newline on the pop-up menu at the bottom of the Serial Monitor window.
eq function
Syntax: (eq item item)
Tests whether the two arguments are the same object, and returns t or nil as appropriate.
Objects are eq if they are the same symbol, same character, equal numbers, or point to the same cons.
equal function
Syntax: (equal item item)
Tests whether the two arguments look the same when printed, and returns t or nil as appropriate. Note that they might not necessarily be the same object.
Objects are equal if they are eq, have the same string representation, or have the same list structure.
For example:
> (defvar a "twin") a > (defvar b "twin") b > (eq a b) nil > (equal a b) t
error special form
Syntax: (error controlstring [arguments]*)
Signals an error. The message is printed by format using the controlstring and arguments.
eval function
Syntax: (eval form*)
Evaluates its argument an extra time.
For example:
> (eval (list '* 7 8))
56
evenp function
Syntax: (evenp number)
Returns t if the argument is even, or nil otherwise.
first function
Syntax: (first list)
Returns the first item in a list.
> (first '(a b c d e f))
a
Equivalent to car.
format function
Syntax: (format output controlstring arguments*)
Outputs its arguments formatted according to the format directives in the control string.
The output argument can be one of:
- nil: the formatted output is returned as a string. For example:
> (format nil "The answer is ~a" 42) "The answer is 42"
- t: the formatted output is printed to the serial output. For example:
> (format t "The answer is ~a" 42) The answer is 42 nil
- a stream: the formatted output is printed to the specified stream.
Format directives
The control string can contain the following format directives:
Directive | Name | Description |
~a | ASCII | Output as princ would print it in human-readable format. |
~s | Sexp | Output as prin1 would print it, with escape characters and quotation marks. |
~d | Decimal | Decimal, as princ would print it. |
~b | Binary | Binary. |
~x | Hexadecimal | Hexadecimal. |
~g | General | General floating-point format, as princ would print it. |
~~ | Tilde | Just prints a ~. |
~% | Newline | Outputs a newline. |
~& | Newline | Outputs a newline unless already at the start of a line. |
~{ | List start | Formats elements from a list. |
~^ | List exit | Exits from ~{ … ~} if the list is empty. |
~} | List end | Ends formatting list elements. |
Any other characters in the control string are just output unchanged.
For example:
> (format t "The battery is ~aV or ~a%." batt (* batt 20)) The battery is 4.75V or 95%.
If the argument is the wrong type for the directives ~d, ~b, ~x, or ~g the argument is output as if with ~a.
Width parameter
Each of the directives ~a, ~s, ~d, ~g, ~b, or ~x can include a width parameter after the tilde, and the output is padded with spaces to the specified width. If the output wouldn't fit in the specified width it is output in full, and overflows the width. The ~a and ~s directives pad with spaces to the right; all the other directives pad with spaces to the left. In uLisp this is the only difference between ~a and ~d or ~g.
The width parameter is useful for formatting data in a neat table. For example:
(defun facts () (let ((n 1)) (dotimes (x 10) (format t "n = ~2d, n! = ~7d~%" (1+ x) (setq n (* n (1+ x)))))))
This prints:
> (facts) n = 1, n! = 1 n = 2, n! = 2 n = 3, n! = 6 n = 4, n! = 24 n = 5, n! = 120 n = 6, n! = 720 n = 7, n! = 5040 n = 8, n! = 40320 n = 9, n! = 362880 n = 10, n! = 3628800 nil
Pad character
The directives ~d, ~g, ~b, or ~x can also include a pad character, which is output in place of spaces to fill the argument to the specified width. The pad character is specified after the width, separated by a comma and a single quote. The pad character is useful combined with the width character for formatting output to be displayed on output devices such as seven-segment displays; for example:
> (format nil "~2,'0d-~2,'0d-~2,'0d" 1 45 7) "01-45-07"
Lists
The ~{ and ~} directives allow you to format elements in a list. The argument must be a list, and the format directives between ~{ and ~} are repeated until all the items in the list have been used. For example:
> (format t "~{~a/~a ~}" '(1 2 3 4 5 6)) 1/2 3/4 5/6
The ~^ directive exits from the directives between ~{ and ~} if the list being processed is finished. It is useful if you want to put a delimiter between list elements, but not after the last one. For example, to convert a Lisp list to JavaScript format you could use:
> (format t "[~{~a~^,~}]" '(1 2 3 4 5)) [1,2,3,4,5]
Note that uLisp only supports one level of nesting of ~{ and ~}.
for-millis Arduino function
Syntax: (for-millis ([number]) form*)
Executes the forms and then waits until a total of number milliseconds have elapsed. It returns the total number of milliseconds taken.
It can be used to define the duration of an event. For example, to play a one-second tone:
(defun bep () (for-millis (1000) (note 3 0 4)) (note))
Alternatively, if the number parameter is zero or omitted, for-millis can be used to time the execution of a function:
> (for-millis () (fib 15)) 493
On the 16-bit platforms the maximum delay is approximately 32 seconds. On the 32-bit platforms the maximum delay is approximately 24 days. If the execution of the body takes longer than this for-millis returns nil.
funcall function
Syntax: (funcall function argument*)
Calls the function with the specified arguments.
gc function
Syntax: (gc)
Forces a garbage collection and prints the number of objects collected, and the time taken.
globals function
Syntax: (globals)
Returns a list of the global variables and functions that are currently defined. For example:
> (globals) (blu grn red)
if special form
Syntax: (if test then [else])
Evaluates test. If it's non-nil the form then is evaluated and returned; otherwise the form else is evaluated and returned.
The else form is optional.
For example:
> (if (digitalread 3) (digitalwrite 4 t) (digitalwrite 5 t))
This reads input D3. If it's high the LED on D4 is lit; otherwise the LED on D5 is lit.
ignore-errors special form
Syntax: (ignore-errors [forms]*)
Evaluates forms ignoring errors, and returns the value of the last form, or if an error occurs it returns the special value nothing.
For example, the following function calc evaluates Lisp expressions you type in:
(defun calc () (loop (let ((input (read))) (when (eq input '~) (return)) (ignore-errors (format t "~%Result: ~a~%" (eval input))))))
Run it with:
> (calc) (/ 1 2) Result: 0.5
Without ignore-errors the calculator will exit if you type in an invalid expression, such as (/ 1 0).
incf special form
Syntax: (incf place [number])
Adds one to the value of place, and returns the new value. The second argument place can be one of the forms:
symbol (car form) (cdr form (nth n form) (aref array index [index*])
For more information see setf.
For example:
> (defvar a 123) a > (incf a) 124 > a 124
You can include an optional second argument to specify the increment.
lambda special form
Syntax: (lambda (parameter*) form*)
Creates an unnamed function with parameters. The body is evaluated with the parameters as local variables whose initial values are defined by the values of the forms after the lambda form.
Functions are usually defined with a specified name using defun. The usual use of lambda is to create an unnamed function as the argument for a function such as mapc or mapcar. For details of the options see defun.
Examples
For example, you could write:
((lambda (x y) (+ x y)) 4 3)
This would assign 4 to x and 3 to y, evaluate (+ x y), and return the result.
The following example uses mapcar to square every number in a list:
> (mapcar (lambda (x) (* x x)) '(0 1 2 3 4 5 6)) (0 1 4 9 16 25 36)
It is also used when you want to create a function that returns a function. The following example defines a function do2 that takes a function of one argument, and returns a function that performs that function twice:
> (defun sq (x) (* x x)) sq > (defun do2 (fun) (lambda (arg) (fun (fun arg)))) do2 > ((do2 sq) 3) 81
length function
Syntax: (length item)
Returns the number of items in a list, the length of a string, or the length of a one-dimensional array.
Examples:
> (length '(a b c d))
4
> (length "hello")
5
> (length #(1 4 9 16 25))
5
let special form
Syntax: (let ((var value) … ) forms*)
Declares local variables, and evaluates forms with those local variables.
In its simplest form you can declare a list of one or more variables which will be initialised to nil, and these can then be used in the subsequent forms:
(let (a b) (setq a 1) (setq b 2) (* a a b))
For each variable you can specify an initial value by specifying it as a list of (variable value), so the above example is equivalent to:
(let ((a 1) (b 2)) (* a a b))
let* special form
Syntax: (let* ((var value) … ) form*)
Like let, but each declaration can refer to local variables that have already been defined.
For example, defining:
(defun tst () (let ((a 7) (b a)) (print a) (print b)))
and evaluating (tst) will give the error:
Error: 'a' undefined
(defun tst (a) (let* ((a 7) (b a)) (print a) (print b)))
and evaluating (tst) will print 7 7.
list function
Syntax: (list item*)
Returns a list of the values of its arguments.
Example:
> (list (* 1 1) (* 2 2) (* 3 3) (* 4 4))
(1 4 9 16)
list-library function
Syntax: (list-library)
Prints a list of the functions defined in the List Library.
For example, if the Lisp Library is defined in the source file with:
const char LispLibrary[] PROGMEM = "(defun sq (x) (* x x))" "(defun cub (x) (* x x x))";
then you could list the library with:
> (list-library) sq cub
For more information see Lisp Library.
listp function
Syntax: (listp item)
Returns t if its argument is a list.
Example:
> (listp 'b) nil
> (listp '(a b))
t
The function listp differs from consp because (listp nil) is t whereas (consp nil) is nil.
load-image function
Syntax: (load-image
[filename])
Loads a saved uLisp image from non-volatile memory or SD card.
On SD card, by default the image is saved to a file ULISP.IMG, but you can specify a string parameter to load the image from a file of that name.
Like save-image, the function returns the size of the image, in objects.
Note: You can make a saved uLisp image load automatically and run a specified function at startup; see save-image.
logand function
Syntax: (logand [value*])
Returns the bitwise logical AND of the values.
logbitp function
Syntax: (logbitp bit value)
Returns t if bit number bit in value is a '1', and nil if it is a '0'.
For example:
> (logbitp 0 1)
t
logior function
Syntax: (logior [value*])
Returns the bitwise logical OR of the values.
lognot function
Syntax: (lognot value)
Returns the bitwise logical NOT of the value.
logxor function
Syntax: (
logxor [value*])
Returns the bitwise logical EXCLUSIVE-OR of the values.
loop special form
Syntax: (loop forms*)
The loop special form executes its arguments repeatedly until one of them reaches a return form, which exits from the loop.
For example, the following function b blinks an LED on I/O line 10 a specified number of times:
(defun b (x) (loop (digitalwrite 10 t) (delay 1000) (digitalwrite 10 nil) (delay 1000) (setq x (- x 1)) (if (= x 0) (return))))
To blink the light 5 times execute:
> (b 5)
nil
make-array function
Syntax: (make-array size [:initial-element element]
[:element-type 'bit])
Arrays are not supported in the AVR-Nano version of uLisp.
If size is an integer make-array creates a one-dimensional array with elements from 0 to size-1. By default they are initialised to nil, but you can provide a default value with the :initial-element keyword parameter. For example:
(defvar a (make-array 100 :initial-element 0))
One-dimensional arrays are printed in the standard #( ... ) notation; for example:
> (make-array 3 :initial-element "Hello") #("Hello" "Hello" "Hello")
If size is a list of n integers make-array creates an n-dimensional array. For example:
(defvar a (make-array '(2 3 4) :initial-element 0))
N-dimensional arrays are printed using the notation #nA( ... ), where n is the number of dimensions in the array. For example, the above array is printed as:
> a #3A(((0 0 0 0) (0 0 0 0) (0 0 0 0)) ((0 0 0 0) (0 0 0 0) (0 0 0 0)))
You can read in an array using the same notation; for example:
(defvar a #2a((1 2 3) (4 5 6)))
Bit arrays
To make a bit array use the option :element-type 'bit. For example:
> (defvar b (make-array 40 :element-type 'bit)) b
By default bit arrays are initialised to 0, but you can override this with:
:initial-element 1
One-dimensional bit arrays are printed using #* notation followed by a string of bits; for example:
> b #*0000000000000000000000000000000000000000
For an example of using bit arrays see Prime number spiral.
Accessing or changing array elements
To access elements in arrays or bit arrays use the aref function.
To change elements in arrays or bit arrays use the setf, incf, or decf functions.
makunbound function
Syntax: (makunbound symbol)
Removes the definition of a function created with defun, or a global variable created with defvar, freeing up the space.
For example:
> (makunbound 'rgb)
rgb
The function will return the symbol.
mapc function
Syntax: (mapc function list1 [list]*)
Applies the function to each element in one or more lists, ignoring the results. It returns the first list argument.
For example:
> (mapc print '(1 2 3))
1
2
3
(1 2 3)
The function mapc is like mapcar, but it doesn't accumulate a list of results, and so is used for its side-effects. For example, if you had an RGB LED connected to I/O pins 9, 10, and 11 you could set the colour of the LED to yellow with:
(mapc digitalwrite '(9 10 11) '(255 255 0))
For other examples of using mapc see Processing items in a list.
mapcan function
Syntax: (mapcan function list1 [list2]*)
Applies the function to each element in one or more lists. The results, which should be lists, are destructively concatenated together to give the result.
One use for mapcan is as a filter, to select elements from a list only if they meet a specified test. For example, to extract the numbers from a list:
> (mapcan (lambda (x) (if (numberp x) (list x))) '(1 a 2 b c 3 d 4)) (1 2 3 4)
For other examples of using mapcan see Processing items in a list.
mapcar function
Syntax: (mapcar function list1 [list]*)
Applies the function to each element in one or more lists, and returns a list of the results.
The function can be a built-in function; for example:
> (mapcar * '(1 2 3) '(4 5 6) '(7 8 9))
(28 80 162)
Alternatively it can be a user-defined function or a lambda expression; for example:
> (mapcar (lambda (x) (* x x)) '(1 2 3 4 5)) (1 4 9 16 25)
For other examples of using mapcar see Processing items in a list.
mapcon function
Syntax: (mapcon function list1 [list]*)
Applies the function to the lists and then successive cdrs of those lists. The results, which should be lists, are destructively concatenated together to give the result.
One application is to extract duplicate values from a sorted list:
> (mapcon (lambda (x) (when (eq (first x) (second x)) (list (car x)))) '(1 2 3 3 5 7 7 8 9)) (3 7 11)
For other examples of using mapcon see Processing items in a list.
mapl function
Syntax: (mapl function list1 [list]*)
Applies the function to the lists and then successive cdrs of those lists, ignoring the results. It returns the first list argument.
For example:
> (mapl print '(1 2 3 4)) (1 2 3 4) (2 3 4) (3 4) (4) (1 2 3 4)
For other examples of using mapl see Processing items in a list.
maplist function
Syntax: (maplist function list1 [list]*)
Applies the function to the lists and then successive cdrs of those lists, and returns a list of the results.
For example:
> (maplist princ-to-string '(1 2 3 4)) ("(1 2 3 4)" "(2 3 4)" "(3 4)" "(4)")
For other examples of using maplist see Processing items in a list.
max function
Syntax: (max number*)
Returns the maximum of one or more arguments. For example:
> (max 3 1 4 1 5 9 1 6)
9
member function
Syntax: (member item list [:test function])
Searches for an item in a list and returns the list starting from the first occurrence of the item, or nil if it is not found.
For example:
> (member 's '(u l i s p))
(s p)
The test function defaults to eq, but you can specify an alternative after a :test keyword; for example:
> (member "three" '("one" "two" "three" "four") :test string=) ("three" "four")
millis Arduino function
Syntax: (millis)
Returns the time in milliseconds that uLisp has been running. On 8/16-bit versions of uLisp this is a signed 16-bit number, so after 32.767 seconds the number will wrap around from 32767 to -32768. In 32-bit versions of uLisp this is a signed 32-bit number which will wrap around after about 25 days.
See also for-millis.
min function
Syntax: (min numbers)
Returns the minimum of one or more arguments. For example:
> (min 3 1 4 1 5 9 1 6)
1
minusp function
Syntax: (minusp number)
Returns t if the argument is less than zero, or nil otherwise.
mod function
Syntax: (mod number number)
Returns its first argument modulo the second argument.
For example:
> (mod 127 10)
7
nil symbol
Syntax: nil
A symbol equivalent to the empty list ().
not function
Syntax: (not item)
Returns t if its argument is nil, or nil otherwise. Equivalent to null.
note Arduino function
Syntax: (note [pin] [note] [octave])
This is a lightweight replacement for the Arduino function tone. It generates a square wave on a digital pin.
It takes three arguments:
- A pin number. The pins supported depend on the platform.
- A note number, from 0 to 11, representing the note in the well-tempered scale, where 0 represents C, 1 represents C#, and so on.
- The octave, which can be from 0 to 8*. If omitted it defaults to 0.
* On the ATmega328P, ATmega2560, and ATmega1284P the octave can be between 3 and 6.
So to play middle C, C4, on pin 3 use:
(note 3 0 4)
To stop the note playing call note with no arguments:
(note)
The note number can be greater than 11 as an alternative way of representing notes in higher octaves. For example, the following function scale plays the scale of C on pin 3:
(defun scale () (mapc (lambda (n) (note 3 n 4) (delay 500)) '(0 2 4 5 7 9 11 12)) (note))
The following function wow uses the voltage on analogue input A0 to change the note:
(defun wow () (loop (let ((x (analogread 0))) (note 3 (/ x 22) 3))))
nothing symbol
Syntax: nothing
A symbol with no value. It is useful if you want to suppress printing the result of evaluating a function.
It is equivalent to (values) in Common Lisp.
nth function
Syntax: (nth number list)
Returns the nth item in a list, counting from zero.
Example:
> (nth 2 '(a b c d)) c
You could use nth to write a function end which returns the last item in a list:
(defun end (lis) (nth (- (length lis) 1) lis))
For example:
> (end '(a b c d)) d
null function
Syntax: (null item)
Returns t if its argument is nil, or nil otherwise. Equivalent to not.
numberp function
Syntax: (numberp item)
Returns t if its argument is a number.
Example:
> (numberp 'b) nil
> (numberp (+ 1 2))
t
oddp function
Syntax: (oddp number)
Returns t if the argument is odd, or nil otherwise.
or special form
Syntax: (or item*)
Evaluates its arguments until one returns non-nil, and returns its value.
pinmode Arduino function
Syntax: (pinmode pin mode)
Sets the input/output mode of an Arduino pin number, and returns nil. The mode parameter can be an integer, a keyword, or t or nil:
Keyword | Description |
:input or nil | Input |
:output or t | Output |
:input-pullup | Input with pullup resistor |
:input-pulldown | Input with pulldown resistor * |
* ARM processors only.
plusp function
Syntax: (plusp number)
Returns t if the argument is greater than zero, or nil otherwise. Note that (plusp 0) is nil.
pop special form
Syntax: (pop place)
Modifies the value of place, which should be a list, to remove its first item, and returns that item. The second argument place can be one of the forms:
symbol (car form) (cdr form) (nth n form) (aref array index [index*])
For more information see setf.
For example:
> (defvar a '(1 2 3 4)) a
> (pop a) 1 > a (2 3 4)
pprint function
Syntax: (pprint item
[stream])
Prints its argument, using the pretty printer, to display it formatted in a structured way. It returns no value. For example, after defining the function var as follows:
(defun var () (loop (let* ((v (analogread 0))) (mapc analogwrite '(10 9 11) (list (red v) (grn v) (blu v))))))
> (pprint var) (lambda nil (loop (let* ((v (analogread 0))) (mapc analogwrite '(10 9 11) (list (red v) (grn v) (blu v))))))
If stream is specified the argument is printed to the specified stream.
pprintall function
Syntax: (pprintall [stream]
)
Pretty-prints the definition of every function and variable you've defined in the uLisp workspace nicely formatted. The optional stream allows you to print the definitions to a stream
For example, to print a listing of all the currently defined functions and variables to an SD card do:
(with-sd-card (str "Listing.txt" 2) (pprintall str))
prin1 function
Syntax: (prin1 item
[stream])
Prints its argument, and returns its value. Strings are printed with quotation marks and escape characters; for example:
(prin1 "He said \"hello\"")
"He said \"hello\""
If stream is specified the argument is printed to the specified stream.
prin1-to-string function
Syntax: (prin1-to-string item
[stream])
Prints its argument to a string, and returns the string. Characters and strings are printed with quotation marks and escape characters, in a format that will be suitable for read-from-string. For example:
> (prin1-to-string #\") "#\\\""
In general,
(read-from-string (princ-to-string 'item))
will give item.
If stream is specified the argument is printed to the specified stream.
princ function
Syntax: (princ item
[stream])
Prints its argument, and returns its value. Characters and strings are printed without quotation marks or escape characters; for example:
(princ "He said \"hello\"")
He said "hello"
If stream is specified the argument is printed to the specified stream.
princ-to-string function
Syntax: (princ-to-string item)
Prints its argument to a string, and returns the string. Characters and strings are printed without quotation marks or escape characters.
For example:
> (concatenate 'string "The result is " (princ-to-string (* 12 34 56))) "The result is 22848"
print function
Syntax: (print item
[stream])
Prints its argument like prin1, but on a new line and followed by a space.
If stream is specified the argument is printed to the specified stream.
progn special form
Syntax: (progn form*)
Evaluates several forms grouped together into a block, and returns the result of evaluating the last form.
push special form
Syntax: (push item place)
Modifies the value of place, which should be a list, to add item onto the front of the list, and returns the new list. The second argument place can be one of the forms:
symbol (car form) (cdr form) (nth n form) (aref array index [index*])
For more information see setf.
For example:
> (defvar a '(2 3 4)) a
> (push 1 a) (1 2 3 4) > a (1 2 3 4)
quote special form
Syntax: (quote item)
Prevents its argument from being evaluated. Can be abbreviated to a single quote mark.
For example:
> '(+ 2 3)
(+ 2 3)
random function
Syntax: (random number)
Returns a random number between 0 and one less than its argument. For example, to simulate a dice throw:
(+ (random 6) 1)
read function
Syntax: (read
[stream])
Reads an atom or list from the specified stream and returns it.
If stream is not specified the item is read from the serial input.
read-byte function
Syntax: (read-byte stream)
Reads a byte from a stream and returns it.
read-from-string function
Syntax: (read-from-string string)
Reads an atom or list from the specified string and returns it.
For example:
> (eval (read-from-string "(* 7 8)")) 56
Any additional characters after the atom or list are ignored; for example:
> (read-from-string "(+ 1 2) (+ 3 4)") (+ 1 2)
read-line function
Syntax: (read-line
[stream])
Reads characters from the serial input up to a newline character, and returns them as a string, excluding the newline.
If stream is specified the line is read from the specified stream.
register function
Syntax: (register address
[value])
Reads or writes the value of a peripheral register.
If value is not specified the function returns the value of the register at address.
If value is specified the value is written to the register at address and the function returns value.
For examples on the AVR and ARM versions of uLisp see Programming AVR registers or Programming ARM registers.
require function
Syntax: (require 'symbol)
Loads the definition of a function defined with defun, or a variable defined with defvar, from the Lisp Library. It returns t if it was loaded, or nil if the symbol is already defined, or if the symbol isn't defined in the Lisp Library.
For example, if the Lisp Library is defined in the source file with:
const char LispLibrary[] PROGMEM = "(defun square (x) (* x x))" "(defun cube (x) (* x x x))";
then you could load the definition of square into the Lisp workspace using:
(require 'square)
For more information see Lisp Library.
rest function
Syntax: (rest list)
Returns a list with the first item removed.
> (rest '(a b c d e f))
(b c d e f)
Equivalent to cdr.
restart-i2c function
Syntax: (restart-i2c stream
[read-p])
Restarts an i2c-stream.
If read-p is nil or omitted the stream is written to.
If read-p is an integer it specifies the number of bytes to be read from the stream.
return special form
Syntax: (return [value])
Exits from a loop, dotimes, or dolist block. Returns value, or nil if no value is specified.
reverse function
Syntax: (reverse list)
Returns a list with the elements of list in reverse order. For example:
> (reverse '(1 2 3 4 5))
(5 4 3 2 1)
The function reverse is useful if you have been using cons to add elements onto the front of a list, but you want to return the list with the earliest elements at the front. For example, the following function log reads x values on analogue input A0 once a second, and returns the list of values:
(defun log (x) (let ((lst nil)) (dotimes (j x (reverse lst)) (setq lst (cons (analogread 0) lst)) (delay 1000))))
If the voltage was slowly rising on A0 you might get:
> (log 10)
(14 16 27 38 49 79 102 134 156 178)
room function
Syntax: (room)
Returns the number of free Lisp cells remaining.
> (room)
280
save-image function
Syntax: (save-image [symbol])
Saves the current uLisp image to non-volatile memory or SD card so it can be loaded using load-image.
Note that saved Lisp images may not be compatible across different releases of uLisp.
Saving to SD card
If you have SD card support enabled, with #define sdcardsupport active, save-image saves to the SD card:
- To save the image on the SD card as ulisp.img, with no autorun function, give the command:
(save-image)
- To save the image to the SD card as filename, with no autorun function, give the command:
(save-image filename)
- To save the image to the SD card as ulisp.img, with (fun) as the autorun function, give the command:
(save-image 'fun)
Note: The autorun function will only be run if the option #define resetautorun is active.
Saving to EEPROM or DataFlash
If you don't have SD card support enabled, with #define sdcardsupport commented out, save-image saves to EEPROM or DataFlash if these are available:
- To save the image to EEPROM/DataFlash, with no autorun function, give the command:
(save-image)
- To save the image to EEPROM/DataFlash, with (fun) as the autorun function, give the command:
(save-image 'fun)
Note: The autorun function will only be run if the option #define resetautorun is active.
The save-image command will return the size of the image, in objects. For example, since each object is four bytes, an ATmega328 with 1 Kbytes of EEPROM has room for an image containing 256 objects.
If there isn't enough EEPROM space to save the image, the following error will be displayed;
Error: Image size too large: 258
You should then free some space with makunbound, and try again.
search function
Syntax: (search pattern target
[:test function])
Returns the index of the first occurrence of pattern in target, or nil if it's not found. The target can be a list or string.
For example:
> (search "cat" "the cat sat on the mat"))
4
> (search '(1 5) '(3 1 4 1 5 9 2 6))
3
If target is a list you can specify the test function; otherwise eq is used. For example:
> (search '("one" "five") '("three" "one" "four" "one" "five" "nine") :test string=) 3
second function
Syntax: (second list)
Returns the second item in a list.
> (second '(a b c d e f))
b
A more memorable name for cadr.
set function
Syntax: (set symbol value [
symbol value]*)
Assigns the value of the second argument to the value of the first argument:
> (set 'a (+ 1 2 3)) 6
setf special form
Syntax: (setf place value [
place value]*)
Modifies an existing list by setting the position in the list specified by place to the result of evaluating value. The second argument place can be one of the forms:
symbol (car form) (cdr form) (nth n form) (char string n) (aref array index [index*])
first and rest can also be used as synonyms for car and cdr.
The following examples illustrate each of these options.
variable
(setf symbol value)
This is equivalent to:
(setq symbol value)
car
(setf (car form) value)
Replaces the car of the value of form with value. For example:
> (defvar a '(b c)) a > (setf (car a) 'e) e
> a
(e c)
cdr
(setf (cdr form) value)
Replaces the cdr of the value of form with value. This is particularly useful in conjunction with assoc, to change the value associated with a key in an association list. For example:
> (defvar col '((red . 23) (blu . 34) (grn . 45))) col > (setf (cdr (assoc 'grn col)) 100) 100 > col ((red . 23) (blu . 34) (grn . 100))
nth
(setf (nth n form) value)
Replaces the nth value of the list form with value. For example:
> (let ((x '(1 2 3))) (setf (nth 1 x) 7) x) (1 7 3)
char
(setf (char string index) character)
Replaces the value of the specified character in string with character. For example:
> (let ((s "abc")) (setf (char s 1) #\r) s) "arc"
aref
(setf (aref array index [index*]) value)
Replaces the value of the specified element in array with value. For example:
> (defvar a (make-array '(2 3))) a > a #2A((nil nil nil) (nil nil nil)) > (setf (aref a 1 2) 90) 90 > a #2A((nil nil nil) (nil nil 90))
setq special form
Syntax: (setq symbol value [
symbol value]*)
Assigns the value of the second argument to the variable specified in the first argument:
> (setq a (+ 1 2 3)) 6
You can make several assignments in a single setq:
> (setq a (+ 2 3) b (+ 4 5)) 9
sleep function
Syntax: (sleep seconds)
Puts the processor into a low-power sleep mode for approximately the specified number of seconds. During sleep the current consumption typically drops to 50 µA on ATmega processors.
sort function
Syntax: (sort list test)
Sorts the list according to the test function, and returns the sorted list. Note that for efficiency the sort is destructive, meaning that the value of list may be changed by the operation.
For example:
> (sort '(3 1 4 1 5 9) <) (1 1 3 4 5 9)
> (sort '("dog" "cat" "ant" "eel" "owl" "mouse") string<) ("ant" "cat" "dog" "eel" "mouse" "owl")
The test function could be a lambda expression; for example, to sort strings into ascending order of length:
> (sort '("giraffe" "lion" "ape" "rhino") (lambda (x y) (< (length x) (length y)))) ("ape" "lion" "rhino" "giraffe")
streamp function
Syntax: (streamp item)
Returns t if the argument is a valid stream and nil otherwise.
string function
Syntax: (string item)
Converts its argument, which should be a character or a symbol, to a string.
For example:
> (string #\*) "*" > (string 'cons) "cons"
string/= function
Syntax: (string/= string string)
Returns the index to the first mismatch if the two strings are not the same, or nil otherwise. For example:
> (string/= "love" "lisp") 1
string< function
Syntax: (string< string string)
Returns the index to the first mismatch if the first string is alphabetically less than the second string, or nil otherwise. For example:
> (string< "mouse" "mice") nil
string<= function
Syntax: (string<= string string)
Returns the index to the first mismatch if the first string is alphabetically less than or equal to the second string, or nil otherwise. For example:
> (string<= "cat" "cats") 3
string= function
Syntax: (string= string string)
Returns t if the two strings are the same, or nil otherwise.
string> function
Syntax: (string> string string)
Returns the index to the first mismatch if the first string is alphabetically greater than the second string, or nil otherwise. For example:
> (string> "mouse" "mice") 1
string>= function
Syntax: (string>= string string)
Returns the index to the first mismatch if the first string is alphabetically greater than or equal to the second string, or nil otherwise. For example:
> (string>= "mouser" "mouse") 5
stringp function
Syntax: (stringp item)
Returns t if the argument is a string and nil otherwise.
subseq function
Syntax: (subseq string start [end])
Returns a subsequence of a list or string.
Lists
Returns a new list consisting of item start to item end-1:
> (subseq '(0 1 2 3 4 5) 2 4) (2 3)
If the third argument is omitted subseq returns from start to the end of the string:
> (subseq '(0 1 2 3 4 5) 2) (2 3 4 5)
Strings
Returns a new string consisting of character start to character end-1:
> (subseq "hello" 0 3) "hel"
If the third argument is omitted subseq returns from start to the end of the string:
> (subseq "hello" 3) "lo"
The following example day returns a three-letter day string for the day number 0 to 6:
(defun day (d) (subseq "MonTueWedThuFriSatSun" (* 3 d) (* 3 (1+ d))))
symbolp function
Syntax: (symbolp item)
Returns t if the argument is a symbol and nil otherwise.
t symbol
Syntax: t
A symbol representing true.
terpri function
Syntax: (terpri
[stream])
Prints a new line, and returns nil.
If stream is specified the new line is written to the specified stream.
third function
Syntax: (third list)
Returns the third item in a list.
> (third '(a b c d e f))
c
A more memorable name for caddr.
time special form
Syntax: (time form)
Prints the value returned by the form, and the time taken to evaluate the form in milliseconds or seconds.
For example:
> (time (tak 18 12 6)) 7 Time: 56.1 s
trace special form
Syntax: (trace [function]*)
Turns on tracing of up to three user-defined functions. It returns a list of the functions currently being traced; for example:
> (trace fac) (fac sq)
Giving (trace) with no arguments returns a list of the functions currently being traced.
Tracing a function prints out the call depth, and a list of the arguments each time the function is called, and the call depth and result each time the function returns.
For example, if you defined:
(defun fac (n) (if (= n 1) 1 (* n (fac (- n 1)))))
you can turn on tracing of fac by typing:
> (trace fac)
Calling fac as follows:
> (fac 4)
will print this trace output:
0: (fac 4) 1: (fac 3) 2: (fac 2) 3: (fac 1) 3: fac returned 1 2: fac returned 2 1: fac returned 6 0: fac returned 24 24
Note that trace will not show calls to functions supplied as an argument to another function, such as apply, funcall, mapc, or mapcar, because in these cases only the body of the function is passed. For example:
(defun sq (x) (* x x)) (trace sq) (mapcar sq '(1 2 3))
The solution is to wrap the function call in a lambda:
(mapcar (lambda (x) (sq x)) '(1 2 3))
unless special form
Syntax: (unless test form*)
Evaluates the test. If it's nil the forms are evaluated and the last value is returned.
For example:
> (unless (digitalread 3) (digitalwrite 4 t))
This reads input D3. If it's low the LED on D4 is lit.
untrace special form
Syntax: (untrace [function]*)
Turns off tracing of the specified user-defined functions.
To turn off tracing for all functions type:
> (untrace)
This returns a list of the functions that have been untraced.
unwind-protect special form
Syntax: (unwind-protect form1 [forms]*)
Evaluates form1 and forms in order and returns the value of form1, but guarantees to evaluate forms even if an error occurs in form1.
For example, the standard blink program can leave the LED on if you escape. You can solve this with unwind-protect:
(defun blink () (pinmode :led-builtin t) (unwind-protect (loop (digitalwrite :led-builtin (not (digitalread :led-builtin))) (delay 1000)) (digitalwrite :led-builtin nil)))
Now the LED will always be turned off when you escape by typing ~.
when special form
Syntax: (when test form*)
Evaluates the test. If it's non-nil the forms are evaluated and the last value is returned.
For example:
> (when (digitalread 3) (digitalwrite 4 t))
This reads input D3. If it's high the LED on D4 is lit.
with-i2c special form
Syntax: (with-i2c (stream [port] address [read-p]) form*)
Evaluates the forms with stream bound to an i2c-stream defined by address.
On processors that support two I2C ports port can be 0 or 1 to specify the port. If omitted it defaults to 0.
For details of the available pins see the appropriate board description on this site.
If read-p is nil or omitted the stream is written to.
If read-p is an integer it specifies the number of bytes to be read from the stream.
The stream is bound to an i2c-stream:
> (with-i2c (str #x70) str)
<i2c-stream #x70>
The AVR version of uLisp uses my own I2C routines which don't need a buffer, and don't impose any limit on the length of transactions. The ARM, ESP, and MSP430 versions of uLisp use the Arduino Wire library, which imposes a 32-byte limit on each transaction.
Port scanner
If the start operation fails the stream variable is bound to nil:
> (with-i2c (str #x71) str)
nil
This allows you to write a very simple port scanner to find all the I2C devices on the bus:
(defun scn () (dotimes (p 127) (with-i2c (str p) (when str (print p)))))
with-output-to-string special form
Syntax: (with-output-to-string (stream) form*)
Returns a string containing the output to the specified stream variable.
For example:
> (with-output-to-string (str) (princ "The result is: " str) (princ 24 str)) "The result is: 24"
uLisp only supports outputting to one string at a time from with-output-to-string or princ-to-string.
with-sd-card Arduino function
Syntax: (with-sd-card (stream filename [mode]) form*)
Evaluates the forms with stream bound to an sd-stream reading from or writing to the file filename.
The filename should be a string of up to 12 characters, consisting of a filename of up to 8 characters, a dot, and an extension of up to three characters.
The mode argument specifies whether the file is opened for reading or writing:
Mode | Effect |
0 or nil | Read |
1 | Write-Append |
2 | Write-Overwrite |
If the file already exists Append writes to the end of the file without affecting the existing contents, whereas Overwrite deletes any existing content first.
For example, the following command writes the string "Hello" to the SD card file "Greeting.txt":
(with-sd-card (str "Greeting.txt" 2) (print "Hello" str))
and the following command reads it back:
(with-sd-card (str "Greeting.txt") (read str))
Writing to an SD card
The functions print, prin1, princ, terpri, pprint, write-byte, write-string, and write-line can all be used to write to an SD card.
Reading from an SD card
The functions read, read-byte, and read-line can all be used to read from an SD card. If the end of the file has been reached, each of these functions returns nil.
with-serial special form
Syntax: (with-serial (stream port [baud]) form*)
Evaluates the forms with stream bound to a serial-stream using serial port port.
For details of the available pins see the appropriate board description on this site.
By default the baud rate is 9600. You can specify the following baud rates by specifying the third baud parameter as one of the following values:
3, 6, 12, 24, 48, 96, 144, 192, 288, 384, 576, or 1152.
Note that the baud rate is the baud parameter times 100; for example, for 38400 baud specify 384.
For example, if you define:
(defun listen () (with-serial (str 1 96) (loop (print (read-line str)))))
and then connect the Port 1 RX pin to the TX pin of a GPS module, running the listen program by typing:
(listen)
will display output from the GPS module; for example:
"$GPRMC,183534.000,A,5213.1091,N,00008.2271,E,0.39,248.14,201117,,,A*61 "$GPVTG,248.14,T,,M,0.39,N,0.72,K,A*39
with-spi special form
Syntax: (with-spi (stream pin [clock] [bitorder] [mode] [port]) form*)
Evaluates the forms with stream bound to an spi-stream. The parameters are:
- stream: a variable that will be bound to an spi-stream. The variable should be specified in commands to read from and write to the stream within the form.
- pin: the enable pin.
- clock: the frequency of the SPI clock, in kHz. It defaults to 4000, a 4 MHz clock.
- bitorder: the bit order, 0 for LSBFIRST, or 1 for MSBFIRST. It defaults to MSBFIRST.
- mode: the SPI mode, 0 to 3. It defaults to mode 0.
- port: the SPI port, 0 or 1. It defaults to 0.
For example, to write a byte #xAA using pin 10 as the enable pin, a 4 MHz clock, MSB first, and mode 0, you would specify:
(with-spi (str 10 4000 1 0) (write-byte #xAA str))
You would get the same settings if you wrote:
(with-spi (str 10) (write-byte #xAA str))
For details of the available pins see the appropriate board description on this site.
The SPI interface will use the fastest available clock rate that is less than or equal to the specified value of clock.
write-byte function
Syntax: (write-byte number [stream])
Writes a byte to a stream.
write-line function
Syntax: (write-line string [stream])
Writes a string terminated by a newline character. If stream is specified the string is written to the stream.
write-string function
Syntax: (write-string string [stream])
Writes a string. If stream is specified the string is written to the stream.
zerop function
Syntax: (zerop number)
Returns t if the argument is zero, or nil otherwise.