Nyquist / XLISP 2.0 -
Contents |
Tutorials |
Examples |
Reference
Predicates and Comparison
Lisp has extensive support for run-time tests.
Generalized Lisp Functions - slower than the build-ins, but no errors
- Built-in XLISP Functions
- Generalized Comparison - one or more arguments
- equalp - compares expressions with 'equality' functions.
- Symbol Predicates - one argument
- variablep - is this a symbol with a variable value bound to it?
- functionp - is this a function or a symbol with a function value bound to it?
- specialp - is this a special form or a symbol with a special form bound to it?
- macrop - is this a Lisp macro or a symbol with a Lisp macro bound to it?
- Function Predicates - one argument
- subrp - is this a build-in function?
- fsubrp - is this a build-in special form?
- closurep - is this a user-defined function?
- Character Predicates - one argument
Back to top
Built-in XLISP Functions
- Boolean Predicates - one argument [all types]
- not - does this expression evaluate to false?
- Generalized Comparison - two arguments [all types]
- eq - are the expressions identical?
- eql - are the expressions identical or equal numbers?
- equal - do the printed expressions look the same?
- Type Predicates - one argument [all types]
- atom - is this an atom?
- symbolp - is this a symbol?
- Symbol Predicates - one argument [error if not a symbol]
- boundp - has the symbol a variable value?
- fboundp - has the symbol a function value?
- numberp - is this a number?
- Number Predicates - one argument [error if not a number]
- plusp - is the number positive?
- minusp - is the number negative?
- zerop - is the number equal to zero?
- integerp - is the number an integer?
- Integer Predicates - one argument [error if not an integer]
- evenp - is the integer even?
- oddp - is the integer odd?
- floatp - is the number a floating-point number?
- Numerical Comparison - one or more arguments [error if not numbers only]
- < - true if all numbers are monotonically increasing
- <= - true if all numbers are monotonically nondecreasing
- = - true if all all numbers are the same value
- /= - true if no two numbers have the same value
- >= - true if all numbers are monotonically nonincreasing
- > - true if all numbers are monotonically decreasing
- null - is this an empty list?
- consp - is it a non-empty list?
- listp - is this a list?
- List Predicates - one argument [error if not a list]
- endp - is this the end of a list?
- stringp - is this a string?
- String Comparison - one or more arguments [error if not strings only]
- Case Sensitive
- string< - test for less than in ASCII ordering
- string<= - test for less than or equal to in ASCII ordering
- string= - test for equal to in ASCII ordering
- string/= - test for not equal to in ASCII ordering
- string>= - test for greater than or equal to in ASCII ordering
- string> - test for greater than in ASCII ordering
- Case Insensitive
- See also Unicode examples.
- characterp - is this a character?
- Character Predicates - one argument [error if not a character]
- Character Comparison - one or more arguments [error if not characters only]
- Case Sensitive
- char< - test for less than in ASCII ordering
- char<= - test for less than or equal to in ASCII ordering
- char= - test for equal to in ASCII ordering
- char/= - test for not equal to in ASCII ordering
- char>= - test for greater than or equal to in ASCII ordering
- char> - test for greater than in ASCII ordering
- Case Insensitive
- See also Unicode examples.
- arrayp - is this an array?
- streamp - is this a stream?
- objectp - is this an object?
- filep - is this a file?
- soundp - is this a sound?
Back to top
equalp
Two expressions are 'equalp':
If two numbers are
=
numerical equal.
If two characters are
char-equal.
If two strings are string-equal.
If the two cars in conses are
'equalp' and the two cdrs in conses
are 'equalp'.
If two arrays have the same number of elements and dimensions, and
the corresponding elements in all dimensions are 'equalp'.
(defun equalp (expr-1 expr-2)
(or (equal expr-1 expr-2)
(and (numberp expr-1) (numberp expr-2) (= expr-1 expr-2))
(let ((type (type-of expr-1)))
(when (eq type (type-of expr-2))
(case type
(character (char-equal expr-1 expr-2))
(string (string-equal expr-1 expr-2))
(cons (do ((x (first expr-1)
(if (consp expr-1) (first expr-1) expr-1))
(y (first expr-2)
(if (consp expr-2) (first expr-2) expr-2)))
((or (null expr-1)
(null expr-2)
(not (equalp x y)))
(and (null expr-1)
(null expr-2)))
(setq expr-1 (and (consp expr-1) (rest expr-1))
expr-2 (and (consp expr-2) (rest expr-2)))))
(array (let ((end (length expr-1)))
(when (eql end (length expr-2))
(dotimes (index end t)
(and (not (equalp (aref expr-1 index)
(aref expr-2 index)))
(return nil)))))))))))
cons: I used do instead of
recursion because XLISP has only two kilobytes stack size. The
(consp expr) tests are
necessary because in a dotted list the last
rest element is not a cons.
Examples:
(equalp 1 1.0) => T
(equalp #\a #\A) => T
(equalp "Abc" "aBc") => T
(equalp '(1 #\a "Abc") '(1.0 #\A "aBc")) => T
(equalp #(1 #\a "Abc") #(1.0 #\A "aBc")) => T
Nested expressions only match if the nesting matches:
(equalp '(1 (2 3)) '(1.0 (2.0 3.0)) => T
(equalp '(1 (2 3)) '((1.0 2.0) 3.0) => NIL
(equalp '((1 2) 3) '((1.0 2.0) 3.0) => T
(equalp '((1 2) 3) '(1.0 (2.0 3.0)) => NIL
A character does not match a string with the same character:
(equalp #\a "a") => NIL
Back to top
variablep
The 'variablep' macro tests if a Lisp expression evaluates to a symbol
with a valid variable value bound to it in the current global or lexical
environment:
(defmacro variablep (expr)
`(and (symbolp ,expr)
(valuep ,expr)))
Depends on valuep, see
and,
defmacro,
symbolp.
Back to top
functionp
The 'functionp' macro tests if a Lisp expression eveluates to a function
or a symbol with a valid function value bound to it in the current global or
lexical environment:
(defmacro functionp (expr)
`(case (type-of ,expr)
(closure (eq 'lambda (car (get-lambda-expression ,expr))))
(subr t)
(symbol (and (or (lfboundp ,expr) (fboundp ,expr))
(functionp (function ,(if (consp expr) (cadr expr) expr)))))
(t nil)))
Depends on lfboundp, see
and,
cadr,
car,
case,
closure,
defmacro,
eq,
fboundp,
function,
get-lambda-expression,
lambda,
nil,
or,
subr,
symbol,
t ,
type-of.
The awkward (function ,(if (consp expr) (cadr expr) expr))
construct is necessary because the
function special form needs a
pre-evaluated argument, what must be
done at macro-expansion time, so an additional
consp test is
needed if the 'expr' argument is a list at all, otherwise
cadr will produce an error.
Examples:
(functionp #'car) => T ; subr = built-in function
(functionp 'car) => T ; symbol with a function value
(functionp #'and) => NIL ; fsubr = built-in special form
(functionp "and") => NIL ; string
(defun a () nil) => A ; closure = user-defined function
(functionp #'a) => T ; closure
(functionp 'a) => T ; symbol with a function value
(setq b #'a) => A ; function A stored in variable B
(fboundp 'b) => NIL ; no function B found
(fboundp b) => T ; variable B evaluates to function A
(functionp #'(lambda () nil)) => T ; closure
(functionp '(lambda () nil)) => NIL ; list
(functionp (lambda () nil)) => T ; closure
(functionp #'functionp) => NIL ; macro
(let ((x nil)) ; lexical variable
(functionp x))
=> NIL
(flet ((y () nil)) ; lexical closure
(functionp y))
=> T
(labels ((z () nil)) ; lexical closure
(functionp z))
=> T
Back to top
specialp
(defmacro specialp (expr)
`(case (type-of ,expr)
(fsubr t)
(symbol (and (or (lfboundp ,expr) (fboundp ,expr))
(functionp (function ,(if (consp expr) (cadr expr) expr)))))
(t nil)))
Back to top
macrop
(defmacro macrop (expr)
`(case (type-of ,expr)
(closure (eq 'macro (car (get-lambda-expression ,expr))))
(symbol (and (or (lfboundp ,expr) (fboundp ,expr))
(macrop (function ,(if (consp expr) (cadr expr) expr)))))
(t nil)))
Back to top
subrp
The 'subrp' function returns T if the symbol is a build-in function.
(defun subrp (symbol)
(eq 'subr (type-of symbol)))
Back to top
fsubrp
The 'fsubrp' function returns T if the symbol is a build-in special
function.
(defun fsubrp (symbol)
(eq 'fsubr (type-of symbol)))
Back to top
closurep
The 'closurep' function returns T if the symbol is a user-defined
function.
(defun closurep (symbol)
(eq 'closure (type-of symbol)))
Back to top
Nyquist / XLISP 2.0 -
Contents |
Tutorials |
Examples |
Reference