#
Chapter 3
Basic Data Extensions

## 3.1 Void and Undefined

MzScheme returns the unique void value -- printed as `#<void>` -- for expressions that have unspecified results in R5RS. The procedure ``void`` takes any number of arguments and returns void:

- `(void``` `v``` `···``)` returns void.

- `(void?``` `v``)` returns `#t` if `v` is void, `#f` otherwise.

Variables bound by `letrec-values` that are accessible but not yet initialized are bound to the unique undefined value, printed as `#<undefined>`.

## 3.2 Booleans

Unless otherwise specified, two instances of a particular MzScheme data type are ``equal?`` only when they are ``eq?``. Two values are ``eqv?`` only when they are either ``eq?``, `=` and have the same exactness, or both `+nan.0`.

The ``andmap`` and ``ormap`` procedures apply a test procedure to the elements of a list, returning immediately when the result for testing the entire list is determined. The arguments to ``andmap`` and ``ormap`` are the same as for ``map``, but a single boolean value is returned as the result, rather than a list:

- `(andmap``` `proc list``` `···`1`)` applies `proc` to elements of the `list`s from the first elements to the last, returning `#f` as soon as any application returns `#f`. If no application of `proc` returns `#f`, then the result of the last application of `proc` is returned. If the `list`s are empty, then `#t` is returned.

- `(ormap``` `proc list``` `···`1`)` applies `proc` to elements of the `list`s from the first elements to the last. If any application returns a value other than `#f`, that value is immediately returned as the result of the ``ormap`` application. If all applications of `proc` return `#f`, then the result is `#f`. If the `list`s are empty, then `#f` is returned.

Examples:

    (andmap positive? '(1 2 3)) ; => #t
    (ormap eq? '(a b c) '(a b c)) ; => #t
    (andmap positive? '(1 2 a)) ; => raises exn:application:type
    (ormap positive? '(1 2 a)) ; => #t
    (andmap positive? '(1 -2 a)) ; => #f
    (andmap + '(1 2 3) '(4 5 6)) ; => 9
    (ormap + '(1 2 3) '(4 5 6)) ; => 5

## 3.3 Numbers

A number in MzScheme is one of the following:

- a fixnum exact integer (30 bits2 plus a sign bit)

- a bignum exact integer (cannot be represented in a fixnum)

- a fraction exact rational (represented by two exact integers)

- a flonum inexact rational (double-precision floating-point number)

- a complex number; either the real and imaginary parts are both exact or inexact, or the number has an exact zero real part and an inexact imaginary part; a complex number with an inexact zero imaginary part is a real number

MzScheme extends the number syntax of R5RS in two ways:

- All input radixes (`#b`, `#o`, `#d`, and `#x`) allow ``decimal'' numbers that contain a period or exponent marker. For example, `#b1.1` is equivalent to `1.5`. In hexadecimal numbers, ``e`` and `d` always stand for a hexadecimal digit, not an exponent marker.

- The following are inexact numerical constants: `+inf.0` (infinity), `-inf.0` (negative infinity), `+nan.0` (not a number), and `-nan.0` (same as `+nan.0`). These names can also be used within complex constants, as in `-inf.0+inf.0i`.

The special inexact numbers `+inf.0`, `-inf.0`, and `+nan.0` have no exact form. Dividing by an inexact zero returns `+inf.0` or `-inf.0`, depending on the sign of the dividend. The infinities are integers, and they answer `#t` for both `even?` and `odd?`. The `+nan.0` value is not an integer and is not `=` to itself, but `+nan.0` is `eqv?` to itself.3 Similarly, `(= 0.0 -0.0)` is `#t`, but `(`eqv?` 0.0 -0.0)` is `#f`.

All multi-argument arithmetic procedures operate pairwise on arguments from left to right.

The `string->number` procedure works on all number representations and exact integer radix values in the range `2` to `16` (inclusive). The `number->string` procedure accepts all number types and the radix values `2`, `8`, `10`, and `16`; however, if an inexact number is provided with a radix other than `10`, the `exn:application:mismatch` exception is raised.

The ``add1`` and ``sub1`` procedures work on any number:

- `(add1``` `z``)` returns `z` + 1.

- `(sub1``` `z``)` returns `z` `-` 1.

The following procedures work on integers:

- `(quotient/remainder``` `n1 n2``)` returns two values: `(`quotient` n1 n2)` and `(`remainder` n1 n2)`.

- `(integer-sqrt``` `n``)` returns the integer square-root of `n`. For positive `n`, the result is the largest positive integer bounded by the `(`sqrt` n)`. For negative `n`, the result is `(* (`integer-sqrt` (- n)) 0+i)`.

- `(integer-sqrt/remainder``` `n``)` returns two values: `(`integer-sqrt` n)` and `(- n (`expt` (`integer-sqrt` n) 2))`.

The following procedures work on exact integers in their (semi-infinite) two's complement representation:

- `(bitwise-ior``` `n``` `···`1`)` returns the bitwise ``inclusive or'' of the `n`s.

- `(bitwise-and``` `n``` `···`1`)` returns the bitwise ``and'' of the `n`s.

- `(bitwise-xor``` `n``` `···`1`)` returns the bitwise ``exclusive or'' of the `n`s.

- `(bitwise-not``` `n``)` returns the bitwise ``not'' of `n`.

- `(arithmetic-shift``` `n m``)` returns the bitwise ``shift'' of `n`. The integer `n` is shifted left by `m` bits; i.e., `m` new zeros are introduced as rightmost digits. If `m` is negative, `n` is shifted right by `-` `m` bits; i.e., the rightmost `m` digits are dropped.

The ``random`` procedure generates pseudo-random integers:

- `(random``` `k``)` returns a random exact integer in the range `0` to `k` `-` 1 where `k` is an exact integer between 1 and 231 `-` 1, inclusive. The number is provided by the current pseudo-random number generator, which maintains an internal state for generating numbers.4

- `(random-seed``` `k``)` seeds the current pseudo-random number generator with `k`, an exact integer between 0 and 231 `-` 1, inclusive. Seeding a generator sets its internal state deterministically; seeding a generator with a particular number forces it to produce a sequence of pseudo-random numbers that is the same across runs and across platforms.

- `(current-pseudo-random-generator``)` returns the current pseudo-random number generator, and `(current-pseudo-random-generator``` `generator``)` sets the current generator to `generator`. See also section 7.7.1.10.

- `(make-pseudo-random-generator``)` returns a new pseudo-random number generator. The new generator is seeded with a number derived from `(`current-milliseconds`)`.

- `(pseudo-random-generator?``` `v``)` returns `#t` if `v` is a pseudo-random number generator, `#f` otherwise.

The following procedures convert between Scheme numbers and common machine byte representations:

- `(integer-byte-string->integer``` `string signed?``` [`big-endian?`]`)` converts the machine-format number encoded in `string` to an exact integer. The `string` must contain either 2, 4, or 8 characters. If `signed?` is true, then the string is decoded as a two's-complement number, otherwise it is decoded as an unsigned integer. If `big-endian?` is true, then the first character's ASCII value provides the most significant eight bits of the number, otherwise the first character provides the least-significant eight bits, and so on. The default value of `big-endian?` is the result of ``system-big-endian?``.

- `(integer->integer-byte-string``` `n size-n signed?``` [`big-endian? to-string`]`)` converts the exact integer `n` to a machine-format number encoded in a string of length `size-n`, which must be 2, 4, or 8. If `signed?` is true, then the number is encoded with two's complement, otherwise it is encoded as an unsigned bit stream. If `big-endian?` is true, then the most significant eight bits of the number are encoded in the first character of the resulting string, otherwise the least-significant bits are encoded in the first character, and so on. The default value of `big-endian?` is the result of ``system-big-endian?``.

  If `to-string` is provided, it must be a mutable string of length `size-n`; in that case, the encoding of `n` is written into `to-string`, and `to-string` is returned as the result. If `to-string` is not provided, the result is a newly allocated string.

  If `n` cannot be encoded in a string of the requested size and format, the `exn:misc:application` exception is raised. If `to-string` is provided and it is not of length `size-n`, the `exn:misc:application` exception is raised.

- `(floating-point-byte-string->real``` `string``` [`big-endian?`]`)` converts the IEEE floating-point number encoded in `string` to an inexact real number. The `string` must contain either 4 or 8 characters. If `big-endian?` is true, then the first character's ASCII value provides the most significant eight bits of the IEEE representation, otherwise the first character provides the least-significant eight bits, and so on. The default value of `big-endian?` is the result of ``system-big-endian?``.

- `(real->floating-point-byte-string``` `x size-n``` [`big-endian? to-string`]`)` converts the real number `x` to its IEEE representation in a string of length `size-n`, which must be 4 or 8. If `big-endian?` is true, then the most significant eight bits of the number are encoded in the first character of the resulting string, otherwise the least-significant bits are encoded in the first character, and so on. The default value of `big-endian?` is the result of ``system-big-endian?``.

  If `to-string` is provided, it must be a mutable string of length `size-n`; in that case, the encoding of `n` is written into `to-string`, and `to-string` is returned as the result. If `to-string` is not provided, the result is a newly allocated string.

  If `to-string` is provided and it is not of length `size-n`, the `exn:misc:application` exception is raised.

- `(system-big-endian?``)` returns `#t` if the native encoding of numbers is big-endian for the machine running MzScheme, `#f` if the native encoding is little-endian.

## 3.4 Characters

MzScheme character values range over the characters for ``extended ASCII'' values 0 to 255 (where the ASCII extensions are platform-specific). The procedure `char->integer` returns the extended ASCII value of a character and `integer->char` takes an extended ASCII value and returns the corresponding character. If `integer->char` is given an integer that is not in 0 to 255 inclusive, the `exn:application:type` exception is raised.

The procedures ``char->latin-1-integer`` and ``latin-1-integer->char`` support conversions between characters in the platform-specific character set and platform-independent Latin-1 (ISO 8859-1) values:

- `(char->latin-1-integer``` `char``)` returns the integer in 0 to 255 inclusive corresponding to the Latin-1 value for `char`, or `#f` if `char` (in the platform-specific character set) has no corresponding character in Latin-1.

- `(latin-1-integer->char``` `k``)` returns the character corresponding to the Latin-1 mapping of `k`, or `#f` if the platform-specific character set does not support the corresponding Latin-1 character. If `k` is not in 0 to 255 inclusive, the `exn:application:type` exception is raised.

For Unix and Mac OS, ``char->latin-1-integer`` and ``latin-1-integer->char`` are the same as ``char->integer`` and ``integer->char``. For Windows, the platform-specific set and Latin-1 match except for the range `#x80` to `#x9F` (which are unprintable control characters in Latin-1).

The character comparison procedures -- `char=?`, `char<?`, `char-ci=?`, etc. -- take two or more character arguments and check the arguments pairwise (like the numerical comparison procedures). Two characters are `eq?` whenever they are `char=?`. The expression `(`char<?` char1 char2)` produces the same result as `(< (`char->integer` char1) (`char->integer` char2))`, etc. The procedures `char-whitespace?`, `char-alphabetic?`, `char-numeric?`, `char-upper-case?`, and ``char-upper-case?``, `char-upcase`, and `char-downcase` are fully portable; their results do not depend on the platform or locales.

In addition to the standard character procedures, MzScheme provides the following locale-sensitive procedures (see section 7.7.1.11):

- `(char-locale<?``` `char1 char2``` `···`1`)`

- `(char-locale>?``` `char1 char2``` `···`1`)`

- `(char-locale-ci=?``` `char1 char2``` `···`1`)`

- `(char-locale-ci<?``` `char1 char2``` `···`1`)`

- `(char-locale-ci>?``` `char1 char2``` `···`1`)`

- `(char-locale-whitespace?``` `char``)`

- `(char-locale-alphabetic?``` `char``)`

- `(char-locale-numeric?``` `char``)`

- `(char-locale-upper-case?``` `char``)`

- `(char-locale-lower-case?``` `char``)`

- `(char-locale-upcase``` `char``)`

- `(char-locale-downcase``` `char``)`

For example, since ASCII character 112 is a lowercase ``p'' and Latin-1 character 246 is a lowercase ``ddoto'' (with an umlaut), `(`char-locale<?` (`integer->char` 112) (`integer->char` 246))` tends to produce `#f`, though it always produces `#t` if the current locale is disabled.

## 3.5 Strings

A string can be mutable or immutable. When an immutable string is provided to a procedure like ``string-set!``, the `exn:application:type` exception is raised.

String constants generated by ``read`` are immutable. `(string->immutable-string``` `string``)` returns an immutable string with the same content as `string`, and it returns `string` itself if `string` is immutable. (See also ``immutable?`` in section 3.8.)

`(substring``` `string start-k``` [`end-k`]`)` returns a mutable string, even if the `string` argument is immutable. The `end-k` argument defaults to `(string-length `string`)`

`(string-copy!``` `dest-string dest-start-k src-string``` [`src-start-k src-end-k`]`)` changes the characters of `dest-string` from positions `dest-start-k` (inclusive) to `dest-end-k` (exclsuive) to match the characters in `src-string` from `src-start-k` (inclsuive). If `src-start-k` is not provided, it defaults to `0`. If `src-end-k` is not provided, it defaults to `(`string-length` src-string)`. The strings `dest-string` and `src-string` can be the same string, and in that case the destination region can overlap with the source region; the destination characters after the copy match the source characters from before the copy. If any of `dest-start-k`, `src-start-k`, or `src-end-k` are out of range (taking into acount the sizes of the strings and the source and destination regions), the `exn:fail:contract` exception is raised.

When a string is created with `make-string` without a fill value, it is initialized with the null character (`#\nul`) in all positions.

The string comparison procedures -- `string=?`, `string<?`, `string-ci=?`, etc. -- take two or more string arguments and check the arguments pairwise (like the numerical comparison procedures). String comparisons using the standard functions are fully portable; the results do not depend on the platform or locales.

In addition to the string character procedures, MzScheme provides the following locale-sensitive procedures (see section 7.7.1.11):

- `(string-locale<?``` `string1 string2``` `···`1`)`

- `(string-locale>?``` `string1 string2``` `···`1`)`

- `(string-locale-ci=?``` `string1 string2``` `···`1`)`

- `(string-locale-ci<?``` `string1 string2``` `···`1`)`

- `(string-locale-ci>?``` `string1 string2``` `···`1`)`

## 3.6 Symbols

For information about symbol parsing and printing, see section 14.3 and section 14.4, respectively.

MzScheme provides two ways of generating an uninterned symbol, i.e., a symbol that is not ``eq?``, ``eqv?``, or ``equal?`` to any other symbol, although it may print the same as another symbol:

- `(string->uninterned-symbol``` `string``)` is like `(`string->symbol` `string`)`, but the resulting symbol is a new uninterned symbol. Calling ``string->uninterned-symbol`` twice with the same `string` returns two distinct symbols.

- `(gensym``` [`symbol/string`]`)` creates an uninterned symbol with an automatically-generated name. The optional `symbol/string` argument is a prefix symbol or string.

Regular (interned) symbols are only weakly held by the internal symbol table. This weakness can never affect the result of a ``eq?``, ``eqv?``, or ``equal?`` test, but a symbol placed into a weak box (see section 13.1) or used as the key in a weak hash table (see section 3.12) may disappear.

## 3.7 Vectors

When a vector is created with ``make-vector`` without a fill value, it is initialized with `0` in all positions. A vector can be immutable, such as a vector returned by `syntax-e`, but vectors generated by `read` are mutable. (See also ``immutable?`` in section 3.8.)

`(vector->immutable-vector``` `vec``)` returns an immutable vector with the same content as `vec`, and it returns `vec` itself if `vec` is immutable. (See also ``immutable?`` in section 3.8.)

`(vector-immutable``` `v``` `···`1`)` is like `(vector v `···`1)` except that the resulting vector is immutable. (See also ``immutable?`` in section 3.8.)

## 3.8 Lists

A cons cell can be mutable or immutable. When an immutable cons cell is provided to a procedure like ``set-cdr!``, the `exn:application:type` exception is raised. Cons cells generated by ``read`` are always mutable.

The global variable `null` is bound to the empty list.

`(reverse!``` `list``)` is the same as `(reverse `list`)`, but `list` is destructively reversed using ``set-cdr!`` (i.e., each cons cell in `list` is mutated).

`(append!``` `list``` `···`1`)` is like `(append `list`)`, but it destructively appends the `list`s (i.e., except for the last `list`, the last cons cell of each `list` is mutated to append the lists; empty lists are essentially dropped).

`(list*``` `v``` `···`1`)` is similar to `(`list` `v` `···`1)` but the last argument is used directly as the ``cdr`` of the last pair constructed for the list:

    (list* 1 2 3 4) ; => '(1 2 3 . 4)

`(cons-immutable``` `v1 v2``)` returns an immutable pair whose ``car`` is `v1` and ``cdr`` is `v2`.

`(list-immutable``` `v``` `···`1`)` is like `(`list` v `···`1)`, but using immutable pairs.

`(list*-immutable``` `v``` `···`1`)` is like `(`list*` v `···`1)`, but using immutable pairs.

`(immutable?``` `v``)` returns `#t` if `v` is an immutable cons cell, string, vector, box, or hash table, `#f` otherwise.

The `list-ref` and `list-tail` procedures accept an improper list as a first argument. If either procedure is applied to an improper list and an index that would require taking the ``car`` or ``cdr`` of a non-cons-cell, the `exn:application:mismatch` exception is raised.

The `member`, `memv`, and `memq` procedures accept an improper list as a second argument. If the membership search reaches the improper tail, the `exn:application:mismatch` exception is raised.

The `assoc`, `assv`, and `assq` procedures accept an improperly formed association list as a second argument. If the association search reaches an improper list tail or a list element that is not a pair, the `exn:application:mismatch` exception is raised.

## 3.9 Boxes

MzScheme provides boxes, which are records that have a single field:

- `(box``` `v``)` returns a new mutable box that contains `v`.

- `(box-immutable``` `v``)` returns a new immutable box that contains `v`.

- `(unbox``` `box``)` returns the content of `box`. For any `v`, `(unbox (box `v`))` returns `v`.

- `(set-box!``` `mutable-box v``)` sets the content of `mutable-box` to `v`.

- `(box?``` `v``)` returns `#t` if `v` is a box, `#f` otherwise.

Two boxes are `equal?` if the contents of the boxes are ``equal?``.

A box returned by ``syntax-e`` (see section 12.2.2) is immutable; if ``set-box!`` is applied to such a box, the `exn:application:type` exception is raised. A box produced by `read` (via `#&`) is mutable. (See also ``immutable?`` in section 3.8.)

## 3.10 Procedures

See section 4.6 for information on defining new procedure types.

### 3.10.1 Arity

MzScheme's ``procedure-arity`` procedure returns the input arity of a procedure:

- `(procedure-arity``` `proc``)` returns information about the number of arguments accepted by the procedure `proc`. The result `a` is either:

  - an exact non-negative integer ==> the procedure always takes exactly `a` arguments;

  - an `arity-at-least` 5 instance ==> the procedure takes `(`arity-at-least-value` a)` or more arguments; or

  - a list containing integers and `arity-at-least` instances ==> the procedure takes any number of arguments that can match one of the arities in the list.

- `(procedure-arity-includes?``` `proc k``)` returns `#t` if the procedure can accept `n` arguments (where `k` is an exact, non-negative integer), `#f` otherwise.

Examples:

    (procedure-arity cons) ; => 2
    (procedure-arity list) ; => #<struct:arity-at-least>
    (arity-at-least? (procedure-arity list)) ; => #t
    (arity-at-least-value (procedure-arity list)) ; => 0
    (arity-at-least-value (procedure-arity (lambda (x . y) x))) ; => 1
    (procedure-arity (case-lambda [(x) 0] [(x y) 1])) ; => '(1 2)
    (procedure-arity-includes? cons 2) ; => #t
    (procedure-arity-includes? display 3) ; => #f

When compiling a `lambda` or `case-lambda` expression, MzScheme looks for a `'method-arity-error` property attached to the expression (see section 12.6.2). If it is present with a true value, and if no case of the procedure accepts zero arguments, then the procedure is marked so that an `exn:application:arity` exception involving the procedure will hide the first argument, if one was provided. (Hiding the first argument is useful when the procedure implements a method, where the first argument is implicit in the original source). The property affects only the format of `exn:application:arity` exceptions, not the result of ``procedure-arity``.

### 3.10.2 Primitives

A primitive procedure is a built-in procedure that is implemented in low-level language. Not all built-in procedures are primitives, but almost all R5RS procedures are primitives, as are most of the procedures described in this manual.

- `(primitive?``` `v``)` returns `#t` if `v` is a primitive procedure or `#f` otherwise.

- `(primitive-result-arity``` `prim-proc``)` returns the arity of the result of the primitive procedure `prim-proc` (as opposed to the procedure's input arity as returned by `arity`; see section 3.10.1). For most primitives, this procedure returns `1`, since most primitives return a single value when applied. For information about arity values, see section 3.10.1.

- `(primitive-closure?``` `v``)` returns `#t` if `v` is internally implemented as a primitive closure rather than an simple primitive procedure, `#f` otherwise. This information is intended for use by the `mzc` compiler.

### 3.10.3 Procedure Names

See section 6.2.4 for information about the names of primitives, and the names inferred for `lambda` and `case-lambda` procedures.

## 3.11 Promises

The `force` procedure can only be applied to values returned by `delay`, and promises are never implicitly ``force``d.

`(promise?``` `v``)` returns `#t` if `v` is a promise created by `delay`, `#f` otherwise.

## 3.12 Hash Tables

`(make-hash-table``` [`flag-symbol flag-symbol`]`)` creates and returns a new hash table. If provided, each `flag-symbol` must one of the following:

- `'weak` -- creates a hash table with weakly-held keys (see section 13.1).

- `'equal` -- creates a hash table that compares keys using ``equal?`` instead of ``eq?`` (needed, for example, when using strings as keys).

By default, key comparisons use ``eq?``. If the second `flag-symbol` is redundant, the `exn:application:mismatch` exception is raised.

Two hash tables are ``equal?`` if they are created with the same flags, and if they map the same keys to ``equal?`` values (where ``same key'' means either ``eq?`` or ``equal?``, depending on the way the hash table compares keys).

`(make-immutable-hash-table``` `assoc-list``` [`flag-symbol`]`)` creates an immutable hash table. (See also ``immutable?`` in section 3.8.) The `assoc-list` must be a list of pairs, where the ``car`` of each pair is a key, and the ``cdr`` is the corresponding value. The mappings are added to the table in the order that they appear in `assoc-list`, so later mappings can hide earlier mappings. If the optional `flag-symbol` argument is provided, it must be `'equal`, and the created hash table compares keys with ``equal?``; otherwise, the created table compares keys with ``eq?``.

`(hash-table?``` `v``` [`flag-symbol flag-symbol`]`)` returns `#t` if `v` was created by ``make-hash-table`` or `make-immutable-hash-table` with the given `flag-symbol`s (or more), `#f` otherwise. Each provided `flag-symbol` must be a distinct flag supported by `make-hash-table`; if the second `flag-symbol` is redundant, the `exn:application:mismatch` exception is raised.

`(hash-table-put!``` `hash-table key-v v``)` maps `key-v` to `v` in `hash-table`, overwriting any existing mapping for `key-v`. If `hash-table` is immutable, the `exn:application:type` exception is raised.

`(hash-table-get``` `hash-table key-v``` [`failure-thunk`]`)` returns the value for `key-v` in `hash-table`. If no value is found for `key-v`, then the result of invoking `failure-thunk` (a procedure of no arguments) is returned. If `failure-thunk` is not provided, the `exn:application:mismatch` exception is raised when no value is found for `key-v`.

`(hash-table-remove!``` `hash-table key-v``)` removes the value mapping for `key-v` if it exists in `hash-table`. If `hash-table` is immutable, the `en:application:type` exception is raised.

`(hash-table-map``` `hash-table proc``)` applies the procedure `proc` to each element in `hash-table`, accumulating the results into a list. The procedure `proc` must take two arguments: a key and its value. See the caveat below about concurrent modification.

`(hash-table-for-each``` `hash-table proc``)` applies the procedure `proc` to each element in `hash-table` (for the side-effects of `proc`) and returns void. The procedure `proc` must take two arguments: a key and its value. See the caveat below about concurrent modification.

`(hash-table-count``` `hash-table``)` returns the number of keys mapped by `hash-table`. If `hash-table` is not created with `'weak`, then the result is computed in constant time and atomically. If `hash-table` is created with `'weak`, see the caveat below about concurrent modification.

`(eq-hash-code``` `v``)` returns an exact integer; for any two ``eq?`` values, the returned integer is the same. Furthermore, for the result integer `k` and any other exact integer `j`, `(= k j)` implies `(`eq?` k j)`.

`(equal-hash-code``` `v``)` returns an exact integer; for any two ``equal?`` values, the returned integer is the same. Furthermore, for the result integer `k` and any other exact integer `j`, `(= k j)` implies `(`eq?` k j)`. If `v` contains a cycle through pairs, vectors, boxes, and inspectable structure fields, then `equal-hash-code` applied to `v` will loop indefinitely.

Caveat concerning concurrent modification: A hash table can be manipulated with ``hash-table-get``, ``hash-table-put!``, and ``hash-table-remove!`` concurrently by multiple threads, and the operations are protected by a table-specific semaphore as needed. A few caveats apply, however:

- If a thread is terminated while applying ``hash-table-get``, ``hash-table-put!``, or ``hash-table-remove!`` to a hash table that uses ``equal?`` comparisons, all current and future operations on the hash table block indefinitely.

- The ``hash-table-map``, ``hash-table-for-each``, and `hash-table-count` procedures do not use the table's semaphore. Consequently, if a hash table is extended with new keys by another thread while a map or for-each is in process, arbitrary key-value pairs can be dropped or duplicated in the map, for-each, or count. Similarly, if the map or for-each procedure itself extends the table, arbitrary key-value pairs can be dropped or duplicated. However, key mappings can be deleted or remapped by any thread with no adverse affects (i.e., the change does not affect a traversal if the key has been seen already, otherwise the traversal skips a deleted key or uses the remapped key's new value).

Caveat concerning mutable keys: If a key into an ``equal?``-based hash table is mutated (e.g., a key string is modified with ``string-set!``), then the hash table's behavior for put and get operations becomes unpredictable.

2 30 bits for a 32-bit architecture, 62 bits for a 64-bit architecture.

3 This definition of ``eqv?`` technically contradicts R5RS, but R5RS does not address strange ``numbers'' like `+nan.0`.

4 The random number generator uses a relatively standard Unix `random()` implementation in its degree-seven polynomial mode.

5 All fields of the `arity-at-least` structure type are accessible by all inspectors (see section 4.5).