Type Checking and Equivalence¶
These procedures test the type of a value or compare values for equality.
Available from (scheme base).
Equivalence Predicates¶
eq?¶
Syntax: (eq? obj1 obj2)
Tests whether obj1 and obj2 are the same object in memory (pointer
identity). This is the fastest comparison but only reliable for symbols,
booleans, the empty list, and pairs/vectors whose identity (not content)
you want to test. Its behavior on numbers, characters, and strings is
implementation-dependent -- use eqv? or equal? when comparing values.
kaappi> (eq? 'a 'a)
;=> #t
kaappi> (eq? '() '())
;=> #t
kaappi> (eq? #t #t)
;=> #t
kaappi> (define x (list 1 2))
kaappi> (eq? x x)
;=> #t
kaappi> (eq? (list 1 2) (list 1 2))
;=> #f
eqv?¶
Syntax: (eqv? obj1 obj2)
Extends eq? with reliable value comparisons for numbers and characters.
Two numbers are eqv? if they are both exact or both inexact, have the
same value, and (for complex numbers) have eqv? real and imaginary
parts. Two characters are eqv? if they represent the same Unicode
codepoint. For all other types, eqv? behaves like eq?.
kaappi> (eqv? 42 42)
;=> #t
kaappi> (eqv? 42 42.0)
;=> #f
kaappi> (eqv? #\a #\a)
;=> #t
kaappi> (eqv? "abc" "abc")
;=> #f
kaappi> (eqv? '() '())
;=> #t
equal?¶
Syntax: (equal? obj1 obj2)
Performs deep structural comparison. Two pairs are equal? if their
car and cdr fields are recursively equal?. Two vectors are equal?
if they have the same length and all corresponding elements are equal?.
Strings and bytevectors are compared element-by-element. For numbers and
characters, equal? delegates to eqv?. This is the most general
equality predicate but also the slowest for large structures.
kaappi> (equal? '(1 2 3) '(1 2 3))
;=> #t
kaappi> (equal? "hello" "hello")
;=> #t
kaappi> (equal? '#(1 2) '#(1 2))
;=> #t
kaappi> (equal? 42 42.0)
;=> #f
kaappi> (equal? '(1 (2 3)) '(1 (2 3)))
;=> #t
Boolean Operations¶
not¶
Syntax: (not obj)
Returns #t if obj is #f, and returns #f for every other value.
In Scheme, only #f is considered false -- all other values, including
0, "", and '(), are true.
kaappi> (not #f)
;=> #t
kaappi> (not #t)
;=> #f
kaappi> (not 0)
;=> #f
kaappi> (not '())
;=> #f
kaappi> (not "")
;=> #f
See also: boolean?
boolean=?¶
Syntax: (boolean=? b1 b2 b3 ...)
Returns #t if all arguments are booleans and have the same truth value.
It is an error if any argument is not a boolean. This is stricter than
comparing with eqv? because it enforces that every argument is a
boolean rather than silently accepting non-boolean values.
kaappi> (boolean=? #t #t)
;=> #t
kaappi> (boolean=? #f #f)
;=> #t
kaappi> (boolean=? #t #f)
;=> #f
kaappi> (boolean=? #t #t #t)
;=> #t
symbol=?¶
Syntax: (symbol=? s1 s2 s3 ...)
Returns #t if all arguments are symbols and are the same symbol. It is
an error if any argument is not a symbol. Because symbols are interned,
this is equivalent to eq? on symbols but includes the type check.
kaappi> (symbol=? 'foo 'foo)
;=> #t
kaappi> (symbol=? 'foo 'bar)
;=> #f
kaappi> (symbol=? 'a 'a 'a)
;=> #t
Type Predicates¶
pair?¶
Syntax: (pair? obj)
Returns #t if obj is a pair (created by cons or a list literal),
and #f otherwise. Note that the empty list is not a pair.
kaappi> (pair? '(1 2))
;=> #t
kaappi> (pair? (cons 1 2))
;=> #t
kaappi> (pair? '())
;=> #f
kaappi> (pair? 42)
;=> #f
See also: null?, list?,
Pairs and Lists
null?¶
Syntax: (null? obj)
Returns #t if obj is the empty list '(), and #f otherwise. This
is the standard way to test for the end of a list when recursing down its
spine.
kaappi> (null? '())
;=> #t
kaappi> (null? '(1))
;=> #f
kaappi> (null? #f)
;=> #f
kaappi> (null? 0)
;=> #f
See also: pair?, list?,
Pairs and Lists
list?¶
Syntax: (list? obj)
Returns #t if obj is a proper list -- either the empty list or a chain
of pairs terminated by the empty list. Dotted pairs and circular
structures return #f. Kaappi uses the tortoise-and-hare algorithm to
detect cycles without unbounded traversal.
kaappi> (list? '(1 2 3))
;=> #t
kaappi> (list? '())
;=> #t
kaappi> (list? (cons 1 2))
;=> #f
kaappi> (list? 42)
;=> #f
See also: pair?, null?,
Pairs and Lists
number?¶
Syntax: (number? obj)
Returns #t if obj is a number of any type in the numeric tower:
fixnum, bignum, exact rational, flonum, or complex. This is the broadest
numeric predicate.
kaappi> (number? 42)
;=> #t
kaappi> (number? 3.14)
;=> #t
kaappi> (number? 2/3)
;=> #t
kaappi> (number? 1+2i)
;=> #t
kaappi> (number? "42")
;=> #f
See also: integer?, real?, complex?,
Numbers and Arithmetic
integer?¶
Syntax: (integer? obj)
Returns #t if obj is an integer. This includes exact integers
(fixnums and bignums) as well as flonums whose value is an integer (e.g.,
3.0). Rationals whose denominator is 1 also satisfy this predicate.
kaappi> (integer? 42)
;=> #t
kaappi> (integer? 3.0)
;=> #t
kaappi> (integer? 3.5)
;=> #f
kaappi> (integer? 2/3)
;=> #f
kaappi> (integer? "42")
;=> #f
See also: number?, real?,
Numbers and Arithmetic
real?¶
Syntax: (real? obj)
Returns #t if obj is a real number -- any number that is not complex.
This includes fixnums, bignums, exact rationals, and flonums (even
+inf.0, -inf.0, and +nan.0).
kaappi> (real? 42)
;=> #t
kaappi> (real? 3.14)
;=> #t
kaappi> (real? 2/3)
;=> #t
kaappi> (real? 1+2i)
;=> #f
kaappi> (real? +inf.0)
;=> #t
See also: number?, complex?, rational?,
Numbers and Arithmetic
complex?¶
Syntax: (complex? obj)
Returns #t if obj is a complex number. In R7RS, every real number is
also a complex number (with zero imaginary part), so complex? returns
#t for all numbers. This predicate is therefore equivalent to
number?.
kaappi> (complex? 1+2i)
;=> #t
kaappi> (complex? 42)
;=> #t
kaappi> (complex? 3.14)
;=> #t
kaappi> (complex? "hello")
;=> #f
See also: number?, real?,
Numbers and Arithmetic
rational?¶
Syntax: (rational? obj)
Returns #t if obj is a rational number. This includes all exact
integers, exact rationals, and finite flonums (since every finite float
can be represented as a ratio of integers). Infinite and NaN flonums
return #f.
kaappi> (rational? 42)
;=> #t
kaappi> (rational? 2/3)
;=> #t
kaappi> (rational? 3.14)
;=> #t
kaappi> (rational? +inf.0)
;=> #f
kaappi> (rational? +nan.0)
;=> #f
See also: number?, real?, integer?,
Numbers and Arithmetic
symbol?¶
Syntax: (symbol? obj)
Returns #t if obj is a symbol, and #f otherwise. Symbols are
interned identifiers -- two symbols with the same name are always eq?.
kaappi> (symbol? 'hello)
;=> #t
kaappi> (symbol? (string->symbol "hello"))
;=> #t
kaappi> (symbol? "hello")
;=> #f
kaappi> (symbol? 42)
;=> #f
string?¶
Syntax: (string? obj)
Returns #t if obj is a string, and #f otherwise. Strings in Kaappi
are sequences of Unicode characters, internally encoded as UTF-8.
kaappi> (string? "hello")
;=> #t
kaappi> (string? "")
;=> #t
kaappi> (string? 'hello)
;=> #f
kaappi> (string? #\a)
;=> #f
See also: Strings
boolean?¶
Syntax: (boolean? obj)
Returns #t if obj is a boolean (#t or #f), and #f otherwise.
kaappi> (boolean? #t)
;=> #t
kaappi> (boolean? #f)
;=> #t
kaappi> (boolean? 0)
;=> #f
kaappi> (boolean? '())
;=> #f
char?¶
Syntax: (char? obj)
Returns #t if obj is a character, and #f otherwise. Characters in
Kaappi represent individual Unicode codepoints.
kaappi> (char? #\a)
;=> #t
kaappi> (char? #\space)
;=> #t
kaappi> (char? "a")
;=> #f
kaappi> (char? 65)
;=> #f
See also: string?
procedure?¶
Syntax: (procedure? obj)
Returns #t if obj is a procedure (a lambda, a built-in primitive, or
a continuation), and #f otherwise.
kaappi> (procedure? car)
;=> #t
kaappi> (procedure? (lambda (x) x))
;=> #t
kaappi> (procedure? +)
;=> #t
kaappi> (procedure? 42)
;=> #f
kaappi> (procedure? '(1 2))
;=> #f
See also: eq?
vector?¶
Syntax: (vector? obj)
Returns #t if obj is a vector, and #f otherwise. Vectors are
fixed-length, indexed sequences of arbitrary Scheme values.
kaappi> (vector? '#(1 2 3))
;=> #t
kaappi> (vector? (vector 'a 'b))
;=> #t
kaappi> (vector? '(1 2 3))
;=> #f
kaappi> (vector? "abc")
;=> #f
See also: Vectors
bytevector?¶
Syntax: (bytevector? obj)
Returns #t if obj is a bytevector, and #f otherwise. Bytevectors
are fixed-length sequences of exact integers in the range 0 to 255.
kaappi> (bytevector? #u8(1 2 3))
;=> #t
kaappi> (bytevector? (make-bytevector 5))
;=> #t
kaappi> (bytevector? '#(1 2 3))
;=> #f
kaappi> (bytevector? "abc")
;=> #f
See also: Bytevectors
port?¶
Syntax: (port? obj)
Returns #t if obj is a port (input port, output port, or
input/output port), and #f otherwise.
kaappi> (port? (current-input-port))
;=> #t
kaappi> (port? (current-output-port))
;=> #t
kaappi> (port? "not-a-port")
;=> #f
See also: input-port?,
output-port?
hash-table?¶
Syntax: (hash-table? obj)
Returns #t if obj is a hash table, and #f otherwise. Hash tables
in Kaappi are available via SRFI-69 and SRFI-125.
kaappi> (hash-table? (make-hash-table))
;=> #t
kaappi> (hash-table? '((a . 1) (b . 2)))
;=> #f
kaappi> (hash-table? '#(1 2))
;=> #f
promise?¶
Syntax: (promise? obj)
Returns #t if obj is a promise created by delay or
delay-force (also called make-promise), and #f otherwise.
Promises represent deferred computations that are forced with force.
kaappi> (promise? (delay 42))
;=> #t
kaappi> (promise? (make-promise 42))
;=> #t
kaappi> (promise? 42)
;=> #f
error-object?¶
Syntax: (error-object? obj)
Returns #t if obj is an error object created by error or
error-object, and #f otherwise. Error objects carry a message, an
irritant list, and optionally a type tag. They are typically caught with
guard or with-exception-handler.
kaappi> (guard (e (#t (error-object? e)))
(error "boom" 'details))
;=> #t
kaappi> (error-object? "not an error")
;=> #f
kaappi> (error-object? 42)
;=> #f
See also: error,
error-object-message,
Control Flow