Predicate Procedures

Overview

Predicate procedures are procedures that test an object for a specific property and return a boolean value — either #t (true) or #f (false). By convention, the names of predicate procedures end with a question mark ?.

Type Predicates

The most fundamental predicates are the type predicates, which test whether an object belongs to a particular type. Every first-class type in this implementation has a corresponding type predicate: number?, boolean?, null?, pair?, list?, procedure?, symbol?, string?, char?, vector?, bytevector?, port?, set?, hash?, and eof-object?. These are the primary tool for runtime type dispatch and defensive programming.

Note that list? is stricter than pair?: a pair is any cons cell, whereas a list is specifically a chain of pairs terminated by the empty list (). An improper list such as (1 . 2) satisfies pair? but not list?. The empty list () satisfies null? and list? but not pair?.

Numeric Tower Predicates

The numeric type predicates — complex?, real?, rational?, integer?, exact-integer?, and bigint? — reflect the structure of the numeric tower. The tower is hierarchical: every integer is rational, every rational is real, and every real is complex. Consequently these predicates are not mutually exclusive: (rational? 42) and (integer? 42) are both #t. The key distinctions are:

  • complex? is equivalent to number? — all numbers are complex.

  • real? returns #t for any number with a zero imaginary part.

  • rational? returns #t for exact numbers and finite inexact reals.

  • integer? follows the tower definition: (integer? 3.0) is #t since 3.0 has no fractional part, even though it is inexact.

  • exact-integer? is the strictest integer test: it returns #t only for exact integers, excluding inexact integers like 3.0.

  • bigint? distinguishes arbitrary-precision integers from native 64-bit integers; note that both satisfy integer? and exact-integer?.

The exactness predicates exact? and inexact? test whether a number’s value is represented exactly. Exact numbers include all integers, rationals, and bignums. Inexact numbers include all floating-point reals and any complex number with at least one inexact component.

Numeric Value Predicates

The numeric value predicates — zero?, positive?, negative?, odd?, and even? — test properties of a number’s value rather than its type. positive? and negative? require a real argument and will raise an error if given a complex number with a non-zero imaginary part, since the concepts of positive and negative are not defined for the complex numbers. odd? and even? require an integer argument per the numeric tower definition, which means (odd? 3.0) is valid and returns #t.

Boolean Value Predicates

The procedures true? and false? test for the literal boolean objects #t and #f respectively. These are distinct from the general notion of truthiness used in conditional expressions: in Scheme, every value except #f is considered true in a boolean context, so (if 0 'yes 'no) yields 'yes. By contrast, (true? 0) returns #f, since 0 is not the literal #t object. These procedures are not part of R7RS and are provided as a convenience.

Predicate Procedures

Type-Identity Procedures

number?

(number? obj)

Returns #t if obj is a number of any numeric type (integer, rational, real, or complex), #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a number, #f otherwise.

Return type:

boolean

Example:

--> (number? 42)
#t
--> (number? 1/3)
#t
--> (number? 3.14)
#t
--> (number? 1+2i)
#t
--> (number? "42")
#f

boolean?

(boolean? obj)

Returns #t if obj is a boolean (#t or #f), #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a boolean, #f otherwise.

Return type:

boolean

Example:

--> (boolean? #t)
#t
--> (boolean? #f)
#t
--> (boolean? 0)
#f

null?

(null? obj)

Returns #t if obj is the empty list (), #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is the empty list, #f otherwise.

Return type:

boolean

Example:

--> (null? '())
#t
--> (null? '(1 2 3))
#f
--> (null? #f)
#f

pair?

(pair? obj)

Returns #t if obj is a pair, #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a pair, #f otherwise.

Return type:

boolean

Example:

--> (pair? '(1 2))
#t
--> (pair? '(1 . 2))
#t
--> (pair? '())
#f
--> (pair? 42)
#f

list?

(list? obj)

Returns #t if obj is a proper list, #f otherwise. A proper list is either the empty list or a chain of pairs terminated by the empty list. Improper lists and circular lists return #f.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a proper list, #f otherwise.

Return type:

boolean

Example:

--> (list? '(1 2 3))
#t
--> (list? '())
#t
--> (list? '(1 . 2))
#f
--> (list? 42)
#f

procedure?

(procedure? obj)

Returns #t if obj is a procedure (either a lambda or a built-in procedure), #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a procedure, #f otherwise.

Return type:

boolean

Example:

--> (procedure? car)
#t
--> (procedure? (lambda (x) x))
#t
--> (procedure? 42)
#f

symbol?

(symbol? obj)

Returns #t if obj is a symbol, #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a symbol, #f otherwise.

Return type:

boolean

Example:

--> (symbol? 'foo)
#t
--> (symbol? "foo")
#f
--> (symbol? 42)
#f

string?

(string? obj)

Returns #t if obj is a string, #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a string, #f otherwise.

Return type:

boolean

Example:

--> (string? "hello")
#t
--> (string? #\h)
#f
--> (string? 'hello)
#f

char?

(char? obj)

Returns #t if obj is a character, #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a character, #f otherwise.

Return type:

boolean

Example:

--> (char? #\a)
#t
--> (char? "a")
#f
--> (char? 97)
#f

vector?

(vector? obj)

Returns #t if obj is a vector, #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a vector, #f otherwise.

Return type:

boolean

Example:

--> (vector? #(1 2 3))
#t
--> (vector? '(1 2 3))
#f
--> (vector? 42)
#f

bytevector?

(bytevector? obj)

Returns #t if obj is a bytevector, #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a bytevector, #f otherwise.

Return type:

boolean

Example:

--> (bytevector? #u8(1 2 3))
#t
--> (bytevector? #(1 2 3))
#f
--> (bytevector? 42)
#f

port?

(port? obj)

Returns #t if obj is a port, #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a port, #f otherwise.

Return type:

boolean

Example:

--> (port? (current-input-port))
#t
--> (port? "myfile.txt")
#f

set?

(set? obj)

Returns #t if obj is a set, #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a set, #f otherwise.

Return type:

boolean

Example:

--> (set? #{1 2 3})
#t
--> (set? (set 1 2 3))
#t
--> (set? '(1 2 3))
#f
--> (set? #[1 "one"])
#f

hash?

(hash? obj)

Returns #t if obj is a hash, #f otherwise.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a hash, #f otherwise.

Return type:

boolean

Example:

--> (hash? #["a" 1 "b" 2])
#t
--> (hash? (hash "a" 1 "b" 2))
#t
--> (hash? #{1 2 3})
#f
--> (hash? '((a . 1) (b . 2)))
#f

eof-object?

(eof-object? obj)

Returns #t if obj is the end-of-file object, #f otherwise. The end-of-file object is returned by input procedures when the end of an input stream is reached.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is the end-of-file object, #f otherwise.

Return type:

boolean

Example:

--> (eof-object? (read (open-input-string "")))
#t
--> (eof-object? "")
#f

Numeric identity procedures

exact?

(exact? z)

Returns #t if z is an exact number, #f otherwise. For complex numbers, returns #t only if both the real and imaginary parts are exact.

Parameters:

z (number) – A number to test.

Returns:

#t if z is exact, #f otherwise.

Return type:

boolean

Example:

--> (exact? 42)
#t
--> (exact? 1/3)
#t
--> (exact? 3.14)
#f
--> (exact? 1+2i)
#t
--> (exact? 1+2.0i)
#f

inexact?

(inexact? z)

Returns #t if z is an inexact number, #f otherwise. For complex numbers, returns #t if either the real or imaginary part is inexact.

Parameters:

z (number) – A number to test.

Returns:

#t if z is inexact, #f otherwise.

Return type:

boolean

Example:

--> (inexact? 3.14)
#t
--> (inexact? 42)
#f
--> (inexact? 1/3)
#f
--> (inexact? 1.0+2.0i)
#t

complex?

(complex? obj)

Returns #t if obj is a number, #f otherwise. Per R7RS, all numbers are complex numbers, so this procedure is equivalent to number?.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a number, #f otherwise.

Return type:

boolean

Example:

--> (complex? 42)
#t
--> (complex? 1/3)
#t
--> (complex? 1+2i)
#t
--> (complex? "hello")
#f

real?

(real? obj)

Returns #t if obj is a real number, #f otherwise. Integers, rationals, and reals all return #t. A complex number returns #t only if its imaginary part is exactly zero.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a real number, #f otherwise.

Return type:

boolean

Example:

--> (real? 42)
#t
--> (real? 1/3)
#t
--> (real? 3.14)
#t
--> (real? 1+0i)
#t
--> (real? 1+2i)
#f
--> (real? "hello")
#f

rational?

(rational? obj)

Returns #t if obj is a rational number, #f otherwise. Exact integers and rationals always return #t. Inexact reals return #t if they are finite. A complex number returns #t only if its real part is exact and its imaginary part is zero. Non-numbers return #f without raising an error.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a rational number, #f otherwise.

Return type:

boolean

Example:

--> (rational? 42)
#t
--> (rational? 1/3)
#t
--> (rational? 3.14)
#t
--> (rational? +inf.0)
#f
--> (rational? +nan.0)
#f
--> (rational? "hello")
#f

integer?

(integer? obj)

Returns #t if obj is an integer, #f otherwise. This follows the R7RS numeric tower definition: a real number with no fractional part is considered an integer, so (integer? 3.0) returns #t. Non-numbers return #f without raising an error.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is an integer, #f otherwise.

Return type:

boolean

Example:

--> (integer? 42)
#t
--> (integer? 3.0)
#t
--> (integer? 3.5)
#f
--> (integer? 1/3)
#f
--> (integer? "hello")
#f

exact-integer?

(exact-integer? obj)

Returns #t if obj is both an exact number and an integer, #f otherwise. Unlike integer?, this returns #f for inexact integers such as 3.0.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is an exact integer, #f otherwise.

Return type:

boolean

Example:

--> (exact-integer? 42)
#t
--> (exact-integer? 3.0)
#f
--> (exact-integer? 1/3)
#f
--> (exact-integer? "hello")
#f

bigint?

(bigint? obj)

Returns #t if obj is a bignum (an exact integer too large to be represented as a native 64-bit integer), #f otherwise. This is a non-standard predicate specific to this implementation.

Note that (integer? obj) and (exact-integer? obj) both return #t for bignums; bigint? is provided for the rare cases where code needs to distinguish between native integers and arbitrary-precision ones.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is a bignum, #f otherwise.

Return type:

boolean

Example:

--> (bigint? 42)
#f
--> (bigint? 99999999999999999999999999999)
#t
--> (bigint? (expt 2 128))
#t
--> (bigint? 1/3)
#f

Numeric predicate procedures

zero?

(zero? z)

Returns #t if z is zero, #f otherwise. For complex numbers, returns #t only if both the real and imaginary parts are zero.

Parameters:

z (number) – A number to test.

Returns:

#t if z is zero, #f otherwise.

Return type:

boolean

Example:

--> (zero? 0)
#t
--> (zero? 0.0)
#t
--> (zero? 0+0i)
#t
--> (zero? 1)
#f

positive?

(positive? x)

Returns #t if x is greater than zero, #f otherwise. x must be a real number; an error is raised if x is a complex number with a non-zero imaginary part.

Parameters:

x (real) – A real number to test.

Returns:

#t if x is greater than zero, #f otherwise.

Return type:

boolean

Example:

--> (positive? 1)
#t
--> (positive? 0)
#f
--> (positive? -1)
#f
--> (positive? 0.1)
#t

negative?

(negative? x)

Returns #t if x is less than zero, #f otherwise. x must be a real number; an error is raised if x is a complex number with a non-zero imaginary part.

Parameters:

x (real) – A real number to test.

Returns:

#t if x is less than zero, #f otherwise.

Return type:

boolean

Example:

--> (negative? -1)
#t
--> (negative? 0)
#f
--> (negative? 1)
#f
--> (negative? -0.1)
#t

odd?

(odd? n)

Returns #t if n is an odd integer, #f otherwise. n must be an integer; an error is raised if n is a non-integer number such as a rational or inexact real with a fractional part.

Parameters:

n (integer) – An integer to test.

Returns:

#t if n is odd, #f otherwise.

Return type:

boolean

Example:

--> (odd? 1)
#t
--> (odd? 2)
#f
--> (odd? -3)
#t
--> (odd? 3.0)
#t

even?

(even? n)

Returns #t if n is an even integer, #f otherwise. n must be an integer; an error is raised if n is a non-integer number such as a rational or inexact real with a fractional part.

Parameters:

n (integer) – An integer to test.

Returns:

#t if n is even, #f otherwise.

Return type:

boolean

Example:

--> (even? 2)
#t
--> (even? 3)
#f
--> (even? 0)
#t
--> (even? 4.0)
#t

Boolean Predicates

false?

(false? obj)

Returns #t if obj is the literal boolean #f, #f otherwise. Note that this tests for the literal #f object specifically, not general falsiness — in this implementation, as in R7RS, #f is the only false value, but this procedure is distinct from simply using not.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is #f, #f otherwise.

Return type:

boolean

Example:

--> (false? #f)
#t
--> (false? #t)
#f
--> (false? 0)
#f
--> (false? '())
#f

true?

(true? obj)

Returns #t if obj is the literal boolean #t, #f otherwise. Note that this tests for the literal #t object specifically, not general truthiness — any non-#f value is truthy in Scheme, but this procedure returns #t only for the boolean #t itself.

Parameters:

obj (any) – The object to test.

Returns:

#t if obj is #t, #f otherwise.

Return type:

boolean

Example:

--> (true? #t)
#t
--> (true? #f)
#f
--> (true? 1)
#f
--> (true? '(1 2 3))
#f