[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Message a011267 LONG message - part 2
user can distinguish obj1 and obj2, then eq? will return
#!false. On the other hand, it is guaranteed that objects
maintain their identity despite being fetched from or stored
into variables or data structures.
The notion of identity used by eq? is stronger than the notions
of equivalence used by the eqv? and equal? predicates. The
constants #!true and #!false are identical to themselves and are
different from everything else, except that in some
implementations the empty list is identical to #!false for
historical reasons. Two symbols are identical if they print the
same way (except that some implementations may have "uninterned
symbols" that violate this rule). For structured objects such
as pairs and vectors the notion of sameness is defined in terms
of the primitive mutation procedures defined on those objects.
For example, two pairs are the same if and only if a set-car!
operation on one changes the car field of the other. The rules
for identity of numbers are extremely implementation-dependent
and should not be relied on.
Generally speaking, the equal? procedure should be used to
compare lists, vectors, and arrays. The string-equal? procedure
should be used to compare strings, and the =? procedure should
be used to compare numbers. The eqv? procedure is just like eq?
except that it is more inclined to say that two numbers are the
same.
(eq? 'a 'a) --> #!true
(eq? 'a 'b) --> #!false
(eq? '(a) '(a)) --> unspecified
(eq? "a" "a") --> unspecified
(eq? 2 2) --> unspecified
(eq? (cons 'a 'b) (cons 'a 'b)) --> #!false
(let ((x (read)))
(eq? (cdr (cons 'b x)) x))) --> #!true
(eqv? obj1 obj2) essential procedure
eqv? is just like eq? except that if obj1 and obj2 are exact
numbers then eqv? is guaranteed to return #!true if obj1 and
obj2 are equal according to the =? procedure.
(eq? 100000 100000) --> unspecified
(eqv? 100000 100000) --> #!true
See section II.6 for a discussion of exact numbers.
(equal? obj1 obj2) essential procedure
Returns #!true if obj1 and obj2 are identical objects or if they
are equivalent numbers, lists, strings, vectors, or arrays. Two
objects are generally considered equivalent if they print the
same. equal? may not terminate if its arguments are circular
data structures.
(equal? 'a 'a) --> #!true
(equal? '(a) '(a)) --> #!true
(equal? '(a (b) c) '(a (b) c)) --> #!true
(equal? "abc" "abc") --> #!true
(equal? 2 2) --> #!true
(equal? (make-vector 5 'a)
(make-vector 5 'a)) --> #!true
equal? is a blunderbuss of a predicate and should not be used
when a less liberal or more specific predicate will suffice.
II.4. Pairs and lists
Lists are Lisp's -- and therefore Scheme's -- characteristic
data structures. Even Lisp and Scheme programs are lists.
The empty list is a special object that is written as an opening
parenthesis followed by a closing parenthesis:
()
The empty list has no elements, and its length is zero. The
empty list is not a pair.
Larger lists are built out of pairs. A pair (sometimes called a
"dotted pair") is a record structure with two fields called the
car and cdr fields (for historical reasons). Pairs are created
by the constructor procedure cons. The car and cdr fields are
accessed by the selector procedures car and cdr. The car and
cdr fields are assigned by the mutator procedures set-car! and
set-cdr!.
The most general notation used for Scheme pairs is the "dotted"
notation (c1 . c2) where c1 is the value of the car field and
c2 is the value of the cdr field. For example
(4 . 5)
is a pair whose car is 4 and whose cdr is 5.
The dotted notation is not often used, because more streamlined
notations exist for the common case where the cdr is the empty
list or a pair. (c1 . ()) is usually written as (c1). (c1 .
(c2 . c3)) is usually written as (c1 c2 . c3). Usually these
special notations permit a structure to be written without any
dotted pair notation at all. For example
(a . (b . (c . (d . (e . ())))))
would normally be written as
(a b c d e)
When all the dots can be made to disappear as in the example
above, the entire structure is called a proper list. Proper
lists are so common that when people speak of a list, they
usually mean a proper list. For those who prefer an inductive
definition:
1. The empty list is a proper list.
2. If l is a proper list, then any pair whose cdr is
l is also a proper list.
3. There are no other proper lists.
A proper list is therefore either the empty list or a pair from
which the empty list can be obtained by applying the cdr
procedure a finite number of times.
Whether a given pair is a proper list depends upon what is
stored in the cdr field. When the set-cdr! procedure is used,
an object can be a proper list one moment and not the next:
(define x '(a b c)) --> x
(define y x) --> y
(set-cdr! x 4) --> unspecified
x --> (a . 4)
(eq? x y) --> #!true
y --> (a . 4)
A pair object, on the other hand, will always be a pair object.
It is often convenient to speak of a homogeneous (proper) list
of objects of some particular data type, as for example (1 2 3)
is a list of integers. To be more precise, suppose D is some
data type. (Any predicate defines a data type consisting of
those objects of which the predicate is true.) Then
1. The empty list is a list of D.
2. If l is a list of D, then any pair
whose cdr is l and whose car satisfies the data
type D is also a list of D.
3. There are no other lists of D.
(pair? obj) essential procedure
Returns #!true if obj is a pair, otherwise returns #!false.
(pair? '(a . b)) --> #!true
(pair? '(a b c)) --> #!true
(pair? '()) --> #!false
(pair? '#(a b)) --> #!false
(cons obj1 obj2) essential procedure
Returns a newly allocated pair whose car is obj1 and whose cdr
is obj2. The pair is guaranteed to be different (in the sense
of eq?) from every existing object.
(cons 'a '()) --> (a)
(cons '(a) '(b c d)) --> ((a) b c d)
(cons "a" '(b c)) --> ("a" b c)
(cons 'a 3) --> (a . 3)
(cons '(a b) 'c) --> ((a b) . c)
(car pair) essential procedure
Returns the contents of the car field of pair. pair must be a
pair. Note that taking the car of the empty list is an error.
(car '(a b c)) --> a
(car '((a) b c d)) --> (a)
(car '(1 . 2)) --> 1
(car '()) --> error
(cdr pair) essential procedure
Returns the contents of the cdr field of pair. pair must be a
pair. Note that taking the cdr of the empty list is an error.
(cdr '((a) b c d)) --> (b c d)
(cdr '(1 . 2)) --> 2
(cdr '()) --> error
(set-car! pair obj) essential procedure
Stores obj in the car field of pair. pair must be a pair. The
value returned by set-car! is unspecified. This procedure can
be very confusing if used indiscriminately.
(set-cdr! pair obj) essential procedure
Stores obj in the cdr field of pair. pair must be a pair. The
value returned by set-cdr! is unspecified. This procedure can
be very confusing if used indiscriminately.
(caar pair) essential procedure
(cadr pair) essential procedure
(cdar pair) essential procedure
(cddr pair) essential procedure
(caaar pair) essential procedure
(caadr pair) essential procedure
(cadar pair) essential procedure
(caddr pair) essential procedure
(cdaar pair) essential procedure
(cdadr pair) essential procedure
(cddar pair) essential procedure
(cdddr pair) essential procedure
(caaaar pair) essential procedure
(caaadr pair) essential procedure
(caadar pair) essential procedure
(caaddr pair) essential procedure
(cadaar pair) essential procedure
(cadadr pair) essential procedure
(caddar pair) essential procedure
(cadddr pair) essential procedure
(cdaaar pair) essential procedure
(cdaadr pair) essential procedure
(cdadar pair) essential procedure
(cdaddr pair) essential procedure
(cddaar pair) essential procedure
(cddadr pair) essential procedure
(cdddar pair) essential procedure
(cddddr pair) essential procedure
These procedures are compositions of car and cdr, where for
example caddr could be defined by
(define caddr (lambda (x) (car (cdr (cdr x)))))
'() essential constant
#!null constant
() is the empty list. The #!null notation does not have to be
quoted in programs. The '() notation must include the quote,
however, because otherwise it would be a procedure call without
a procedure expression.
Rationale: Because many current Scheme interpreters deal with
expressions as list structures rather than as character strings,
they will treat an unquoted () as though it were quoted. It is
entirely possible, however, that some implementations of Scheme
will be able to detect this error.
(null? obj) essential procedure
Returns #!true if obj is the empty list, otherwise returns
#!false.
(list obj1 ...) essential procedure
Returns a list of its arguments.
(list 'a (+ 3 4) 'c) --> (a 7 c)
(length plist) essential procedure
Returns the length of plist, which must be a proper list.
(length '()) --> 0
(length '(a b c)) --> 3
(length '(a (b) (c d e))) --> 3
(append plist1 plist2) essential procedure
(append plist ...) procedure
Returns a list consisting of the elements of the first plist
followed by the elements of the other plists. All plists should
be proper lists.
(append '(x) '(y)) --> (x y)
(append '(a) '(b c d)) --> (a b c d)
(append '(a (b)) '((c))) --> (a (b) (c))
(append! plist ...) procedure
Like append but may side effect its arguments.
(reverse plist) procedure
Returns a list consisting of the elements of plist in reverse
order. plist must be a proper list.
(reverse '(a b c)) --> (c b a)
(reverse '(a (b c) d (e (f)))) --> ((e (f)) d (b c) a)
(list-ref x n) procedure
Returns the car of (list-tail x n).
(list-tail x n) procedure
Returns the sublist of x obtained by omitting the first n
elements. Could be defined by
(define list-tail
(lambda (x n)
(if (zero? n)
x
(list-tail (cdr x) (- n 1)))))
(last-pair x) procedure
Returns the last pair in the nonempty list x. Could be defined
by
(define last-pair
(lambda (x)
(if (pair? (cdr x))
(last-pair (cdr x))
x)))
(memq obj plist) essential procedure
(memv obj plist) essential procedure
(member obj plist) essential procedure
Finds the first occurrence of obj in the proper list plist and
returns the first sublist of plist beginning with obj. If obj
does not occur in plist, returns #!false. memq uses eq? to
compare obj with the elements of plist, while memv uses eqv? and
member uses equal?.
(memq 'a '(a b c)) --> (a b c)
(memq 'b '(a b c)) --> (b c)
(memq 'a '(b c d)) --> #!false
(memq (list 'a) '(b (a) c)) --> #!false
(memq 101 '(100 101 102)) --> unspecified
(memv 101 '(100 101 102)) --> (101 102)
(member (list 'a) '(b (a) c)) --> ((a) c)
(assq obj alist) essential procedure
(assv obj alist) essential procedure
(assoc obj alist) essential procedure
alist must be a proper list of pairs. Finds the first pair in
alist whose car field is obj and returns that pair. If no pair
in alist has obj as its car, returns #!false. assq uses eq? to
compare obj with the car fields of the pairs in alist, while
assv uses eqv? and assoc uses equal?.
(assq 'a '((a 1) (b 2) (c 3))) --> (a 1)
(assq 'b '((a 1) (b 2) (c 3))) --> (b 2)
(assq 'd '((a 1) (b 2) (c 3))) --> #!false
(assq '(a) '(((a)) ((b)) ((c)))) --> #!false
(assq 5 '((2 3) (5 7) (11 13))) --> unspecified
(assv 5 '((2 3) (5 7) (11 13))) --> (5 7)
(assoc '(a) '(((a)) ((b)) ((c)))) --> ((a))
Rationale: memq, memv, member, assq, assv, assoc do not have
question marks in their names because they return useful values
rather than just #!true.
II.5. Symbols
Symbols are objects whose usefulness rests entirely on the fact
that two symbols are identical (in the sense of eq?) if and only
if their names are spelled the same way. This is exactly the
property that is needed for identifiers in programs, and so most
implementations of Scheme use them internally for that purpose.
Programmers may also use symbols as they use enumerated types in
Pascal.
The rules for writing a symbol are the same as the rules for
writing an identifier (see section I.2). As with identifiers,
different implementations of Scheme use slightly different
rules, but it is always the case that a sequence of characters
that contains no special characters and begins with a character
that cannot begin a number is taken to be a symbol; in addition
+, -, 1+, and -1+ are symbols.
The case in which a symbol is written in unimportant. Some
implementations of Scheme convert any upper case letters to
lower case, and others convert lower case to upper case.
It is guaranteed that any symbol that has been read using the
read procedure and subsequently written out using the write
procedure will read back in as the identical symbol (in the
sense of eq?). The string->symbol procedure, however, can
create symbols for which the write/read invariance may not hold
because their names contain special characters or letters in the
non-standard case.
Rationale: Some implementations of Lisp have a feature known as
"slashification" in order to guarantee write/read invariance for
all symbols, but historically the most important use of this
feature has been to compensate for the lack of a string data
type. Some implementations have "uninterned symbols", which
defeat write/read invariance even in implementations with
slashification and also generate exceptions to the rule that two
symbols are the same if and only if their names are spelled the
same. It is questionable whether these features are worth their
complexity, so they are not standard in Scheme.
(symbol? obj) essential procedure
Returns #!true is obj is a symbol, otherwise returns #!false.
(symbol? 'foo) --> #!true
(symbol? (car '(a b))) --> #!true
(symbol? "bar") --> #!false
(symbol->string symbol) essential procedure
Returns the name of symbol as a string. symbol->string performs
no case conversion. See string->symbol. The following examples
assume the read procedure converts to lower case:
(symbol->string 'flying-fish) --> "flying-fish"
(symbol->string 'Martin) --> "martin"
(symbol->string
(string->symbol "Malvina")) --> "Malvina"
(string->symbol string) essential procedure
Returns the symbol whose name is string. string->symbol can
create symbols with special symbols or upper case letters in
their names, but it is usually a bad idea to create such symbols
because in some implementations of Scheme they cannot be read as
themselves. See symbol->string.
'mISSISSIppi --> mississippi
(string->symbol "mISSISSIppi") --> mISSISSIppi
(eq? 'bitBlt
(string->symbol "bitBlt")) --> #!false
(eq? 'JollyWog
(string->symbol
(symbol->string 'JollyWog))) --> #!true
(string-equal?
"K. Harper, M.D."
(symbol->string
(string->symbol
"K. Harper, M.D."))) --> #!true
II.6. Numbers (part 1)
Numerical computation has traditionally been neglected by the
Lisp community. Until Common Lisp there has been no carefully
thought out strategy for organizing numerical computation, and
with the exception of the MacLisp system there has been little
effort to execute numerical code efficiently. We applaud the
excellent work of the Common Lisp committee and we accept many
of their recommendations. In some ways we simplify and
generalize their proposals in a manner consistent with the
purposes of Scheme.
Scheme's numerical operations treat numbers as abstract data, as
independent of the machine representation as is possible. Thus,
the casual user should be able to write simple programs without
having to know that the implementation may use fixed-point,
floating-point, and perhaps other representations for his data.
Unfortunately, this illusion of uniformity can only be sustained
approximately -- the implementation of numbers will leak out of
our abstraction whenever the user must be in control of
precision, or accuracy, or when he must construct especially
efficient computations. Thus we also must provide escape
mechanisms so that a sophisticated programmer can exercise more
control of the execution of his code and the representation of
his data when it is essential to do so.
We separate out several apparently related issues of
representation -- the abstract numbers, their machine
representation, and the input/output formats of the symbolic
expressions which denote numerical constants. We will use
mathematical words such as NUMBER, COMPLEX, REAL, RATIONAL, and
INTEGER for properties of the abstract numbers, data-structure
names such as FIXNUM, BIGNUM, RATNUM, and FLONUM for machine
representations, and names like INT, FIX, FLO, SCI, RAT, POLAR,
and RECT for input/output formats.
Notations for numbers are the subject of section II.7.
Numbers.
A Scheme system provides data of type NUMBER, which is the most
general numerical type supported by that system. NUMBER is
likely to be a complicated union type implemented in terms of
FIXNUMs, BIGNUMS, FLONUMS, etc. but this should not be apparent
to a naive user. What the user sees is that the obvious
operations on numbers produce the mathematically expected
results, within the limits of the implementation. Thus if the
user divides 3 by 2, he should get something like 1.5 (or, the
exact fraction 3/2). If he adds that result to itself, and if
the implementation can swing it, he should get an exact 3.
Mathematically, numbers may be arranged into a tower of subtypes
with natural projections and injections relating adjacent
members of the tower:
NUMBER
COMPLEX
REAL
RATIONAL
INTEGER
We impose a uniform rule of downward coercion -- a number of one
type is also of a lower type if the injection (up) of the
projection (down) of a number leaves the number unchanged.
Since this tower is a real mathematical entity, Scheme provides
predicates and procedures that access the tower.
Not all Scheme implementations must provide the whole tower, but
they are required to implement a coherent subset, consistent
with the purposes of Scheme.
Exactness.
Numbers are either EXACT or INEXACT. A number is exact if it
was derived from EXACT numbers using only EXACT operations. A
number is INEXACT if it models a quantity known only
approximately, if it was derived using INEXACT ingredients, or
if it was derived using INEXACT operations. Thus INEXACTness is
a contagious property of a number. Some operations, such as the
square root (of non-square numbers) must be INEXACT because of
the finite precision of our representations. Other operations
are inexact because of implementation requirements. We
emphasize that exactness is independent of the position of the
number on the tower. It is perfectly possible to have an
INEXACT INTEGER or an EXACT REAL; 355/113 may be an EXACT
RATIONAL or it may be an INEXACT RATIONAL approximation to pi,
depending on the application.
Operationally, it is the system's responsibility to combine
EXACT numbers using exact methods, such as infinite precision
integer and rational arithmetic, where possible. An
implementation may not be able to do this (if it does not use
infinite precision integers and rationals), but if a number
becomes inexact for implementation reasons there is probably an
important error condition, such as integer overflow, to be
reported. Arithmetic on INEXACT numbers is not so constrained.
The system may use floating point and other flaky representation
strategies for INEXACT numbers. This is not to say that
implementors need not use the best known algorithms for INEXACT
computations -- only that high-quality approximate methods are
allowed. In a system which cannot explicitly distinguish exact
from inexact numbers the system must do its best to maintain
precision. Scheme systems must not burden users with numerical
operations described in terms of hardware and operating-system
dependent representations such as FIXNUM and FLONUM. These
representation issues should not be germane to the user's
problems.
We highly recommend that the IEEE 32-bit and 64-bit
floating-point standards be adopted for implementations that use
floating-point internal representations. To minimize loss of
precision we adopt the following rules: If an implementation
uses several different sizes of floating-point formats, the
results of any operation with a floating-point result must be
expressed in the largest format used to express any of the
floating-point arguments to that operation. It is desirable
(but not required) for potentially irrational operations such as
sqrt, when applied to EXACT arguments, to produce EXACT answers
when that is possible (eg. sqrt[4]=2, exactly). If an EXACT
number (or an INEXACT number represented as a FIXNUM, a BIGNUM,
or a RATNUM) is operated upon so as to produce an INEXACT result
(as by sqrt), and if the result is represented as a FLONUM, then
the largest available format FLONUM must be used; but if the
result is expressed as a RATNUM then the rational approximation
must have at least as much precision as the largest available
format FLONUM. (Note that this last rule is much stronger than
that used in Common Lisp. Consider the result of the square
root of a rational, for example.)
Numerical operations.
Scheme provides the usual set of operations for manipulating
numbers. In general, numerical operations require numerical
arguments. For succintness we let the following meta-symbols
range over the indicated types of object in our descriptions,
and we let these meta-symbols specify the types of the arguments
to numeric operations. It is an error for an operation to be
presented with an argument that it is not specified to handle.
obj any arbitrary object
z, z1, ... zi, ... complex, real, rational, integer
x, x1, ... xi, ... real, rational, integer
q, q1, ... qi, ... rational, integer
n, n1, ... ni, ... integer
(number? obj) essential procedure
(complex? obj) essential procedure
(real? obj) essential procedure
(rational? obj) essential procedure
(integer? obj) essential procedure
These numerical type predicates can be applied to any kind of
argument. They return true if the object is of the named type.
In general, if a type predicate is true of a number then all
higher type predicates are also true of that number. Not every
system supports all of these types; it is entirely possible to
have a Scheme system that has only INTEGERs. Nonetheless every
implementation of Scheme must have all of these predicates.
(zero? z) essential procedure
(positive? x) essential procedure
(negative? x) essential procedure
(odd? n) essential procedure
(even? n) essential procedure
(exact? z) essential procedure
(inexact? z) essential procedure
These numerical predicates test a number for a particular
property. They return a boolean value.
(= z1 z2) essential procedure
(=? z1 z2) essential procedure
(= z1 z2 z3 ...) procedure
(=? z1 z2 z3 ...) procedure
(< x1 x2) essential procedure
(<? x1 x2) essential procedure
(< x1 x2 x3 ...) procedure
(<? x1 x2 x3 ...) procedure
(> x1 x2) essential procedure
(>? x1 x2) essential procedure
(> x1 x2 x3 ...) procedure
(>? x1 x2 x3 ...) procedure
(<= x1 x2) essential procedure
(<=? x1 x2) essential procedure
(<= x1 x2 x3 ...) procedure
(<=? x1 x2 x3 ...) procedure
(>= x1 x2) essential procedure
(>=? x1 x2) essential procedure
(>= x1 x2 x3 ...) procedure
(>=? x1 x2 x3 ...) procedure
The numerical comparison predicates have redundant names (with
and without the terminal "?") to make all populations happy.
They optionally take many arguments, as in Common Lisp, to
facilitate range checks. These procedures return true if their
arguments are (respectively): numerically equal, monotonically
increasing, monotonically decreasing, monotonically
nondecreasing, or monotonically nonincreasing. Warning: On
INEXACT numbers equality tests will give unreliable results;
other numerical comparisons are only heuristically useful (ask a
numerical analyst about this!).
(max x1 x2) essential procedure
(max x1 x2 ...) procedure
(min x1 x2) essential procedure
(min x1 x2 ...) procedure
Returns the maximum or minimum of its arguments, respectively.
(+ z1 z2) essential procedure
(+ z1 ...) procedure
(* z1 z2) essential procedure
(* z1 ...) procedure
These procedures return the sum or product of their arguments.
(+ 3 4) --> 7
(+ 3) --> 3
(+) --> 0
(* 4) --> 4
(*) --> 1
(- z1 z2) essential procedure
(- z1 z2 ...) procedure
(/ z1 z2) essential procedure
(/ z1 z2 ...) procedure
With two or more arguments, these procedures return the
difference or (complex) quotient of their arguments, associating
to the left. With one argument, however, they return the
additive or multiplicative inverse of their argument.
(- 3 4) --> -1
(- 3 4 5) --> -6
(- 3) --> -3
(/ 3 4 5) --> 3/20
(/ 3) --> 1/3
(1+ z) procedure
(-1+ z) procedure
These procedures return the result of adding or subtracting 1 to
their argument.
(abs z) essential procedure
Returns the magnitude of its argument.
(abs -7) --> 7
(abs -3+4i) --> 5
(quotient n1 n2) essential procedure
(remainder n1 n2) essential procedure
(modulo n1 n2) procedure
In general, these are intended to implement number-theoretic
(integer) division, where for positive integers n1 and n2 if n3
and n4 are integers such that
n1 = n3 * n2 + n4 and 0 <= n4 < n2
then
(quotient n1 n2) --> n3
(remainder n1 n2) --> n4
(modulo n1 n2) --> n4
remainder and modulo differ on negative arguments as do the
Common Lisp rem and mod procedures -- the remainder always has
the sign of the dividend, the modulo always has the sign of the
divisor:
(modulo 13 4) --> 1
(remainder 13 4) --> 1
(modulo -13 4) --> 3
(remainder -13 4) --> -1
(modulo 13 -4) --> -3
(remainder 13 -4) --> 1
(modulo -13 -4) --> -1
(remainder -13 -4) --> -1
(gcd n1 ...) procedure
(lcm n1 ...) procedure
These procedures return the greatest common divisor or least
common multiple of their arguments. The arguments to lcm should
be nonzero. The result is always non-negative.
(gcd 32 -36) --> 4
(gcd) --> 0
(lcm 32 -36) --> 288
(lcm) --> 1
(floor x) procedure
(ceiling x) procedure
(truncate x) procedure
(round x) procedure
(rationalize x y) procedure
(rationalize x) procedure
These procedures create integers and rationals. Their results
are not EXACT -- in fact, their results are clearly INEXACT,
though they can be made EXACT with an explicit exactness
coercion.
floor returns the largest integer not larger than x. ceiling
returns the smallest integer not smaller than x. truncate
returns the integer of maximal absolute value not larger than x.
round returns the closest integer to x, rounding to even when x
is halfway between two integers. With two arguments,
rationalize produces the best rational approximation to x within
the tolerance specified by y. With one argument, rationalize
produces the best rational approximation to x, preserving all of
the precision in its representation.
(exp z) procedure
(log z) procedure
(expt z1 z2) procedure
(sqrt z) procedure
(sin z) procedure
(cos z) procedure
(tan z) procedure
(asin z) procedure
(acos z) procedure
(atan z1 z2) procedure
These procedures are part of every implementation that supports
real numbers. Their meanings conform with the Common Lisp
standard. (Be careful of the branch cuts if complex numbers are
allowed.)
(make-rectangular x1 x2) procedure
(make-polar x3 x4) procedure
(real-part z) procedure
(imag-part z) procedure
(magnitude z) procedure
(angle z) procedure
These procedures are part of every implementation that supports
complex numbers. Suppose x1, x2, x3, and x4 are real numbers
and z is a complex number such that
z = x1 + x2 i = x3 * e ^ (x4 i)
Then make-rectangular and make-polar return z, real-part returns
x1, imag-part returns x2, magnitude returns x3, and angle
returns x4.
(exact->inexact z) procedure
(inexact->exact z) procedure
exact->inexact returns an inexact representation of z, which is
a pretty harmless thing to do. inexact->exact returns an exact
representation of z; be sure you know what you are doing here!
II.7. Numbers (part 2)
Numerical Input and Output.
Scheme allows all of the traditional ways of expressing
numerical constants, though any particular implementation may
support only some of them. These expressions are intended to be
purely notational; any kind of number may be expressed in any
form that the user deems convenient. Of course, expressing 1/7
as a limited-precision decimal fraction will not exactly express
the number, but this approximate expression may be just what the
user wants to see.
The expressions of numerical constants can be specified using
formats. The system provides a procedure, number->string, which
takes a number and a format and which produces a string which is
the printed expression of the given number in the given format.
(number->string number format) procedure
This procedure will mostly be used by sophisticated users and in
system programs. In general, a naive user will need to know
nothing about the formats because the system printer will have
reasonable default formats for all types of NUMBERs. The system
reader will construct reasonable default numerical types for
numbers expressed in each of the formats it recognizes. If a
user needs control of the coercion from strings to numbers he
will use string->number, which takes a string, an exactness, and
a radix and which produces a number of the maximally precise
applicable type expressed by the given string.
(string->number string exactness radix) procedure
The exactness is a symbol, either E (for EXACT) or I (for
INEXACT). The radix is also a symbol: B for binary, O for
octal, D for decimal, and X for hexadecimal. Returns a number
parsed from the string.
Formats may have parameters. For example, the (SCI 5 2) format
specifies that a number is to be expressed in Fortran scientific
format with 5 significant places and two places after the radix
point.
The following are all numerical constant expressions. The
comment shows the format that was used to produce the
expression:
123 +123 -123 ; (INT)
12345678901234567890123456789 ; A big one!
355/113 -355/113 +355/113 ; (RAT)
+123.45 -123.45 ; (FIX 2)
3.14159265358979 ; (FIX 14)
3.14159265358979 ; (FLO 15)
123.450 ; (FLO 6)
-123.45E-1 ; (SCI 5 2)
123E3 123E-3 -123E-3 ; (SCI 3 0)
-1+2i ; (RECT (INT) (INT))
1.2@1.570796 ; (POLAR (FIX 1) (FLO 7))
A numerical constant may be specified with an explicit radix by
a prefix. The prefixes are: #B (binary), #O (octal), #D
(decimal), #X (hex). A format may specify that a number be
expressed in a particular radix. The radix prefix may be
suppressed. For example, one may express a complex number in
polar form with the magnitude in octal and the angle in decimal
as follows:
#o1.2@#d1.570796327 ; (POLAR (FLO 2 (RADIX O)) (FLO (RADIX D)))
#o1.2@1.570796327 ; (POLAR (FLO 2 (RADIX O)) (FLO (RADIX D S))
A numerical constant may be specified to be either EXACT or
INEXACT by a prefix. The prefixes are: #I (inexact), #E
(exact). An exactness prefix may appear before or after any
radix prefix that is used. A format may specify that a number
be expressed with an explicit exactness prefix, or it may force
the exactness to be suppressed. For example, the following are
ways to output an inexact value for pi:
#I355/113 ; (RAT (EXACTNESS))
355/113 ; (RAT (EXACTNESS S))
#I3.1416 ; (FIX 4 (EXACTNESS))
An attempt to produce more digits than are available in the
internal machine representation of a number will be marked with
a "#" filling the extra digits. This is not a statement that
the implementation knows or keeps track of the significance of a
number, just that the machine will flag attempts to produce 20
digits of a number which has only 15 digits of machine
representation:
3.14158265358979##### ; (FLO 20 (EXACTNESS S))
In systems with both single and double precision FLONUMs one may
want to specify which size we want to use to internally
represent a constant. For example, we may want a constant that
is pi rounded to the single precision length, or we might want a
long number which has the value 6/10. In either case, we are
specifying an explicit way to represent an INEXACT number. For
this purpose, we allow one to express a number with a prefix
which indicates short or long FLONUM representation:
#S3.14159265358979 ; Round to short -- 3.141593
#L.6 ; Extend to long -- .600000000000000
Details of formats.
The format of a number is notated as a list beginning with a
format descriptor, such as SCI. Following the descriptor are
parameters used by that descriptor, such as the number of
significant digits to be used. Parameters which are omitted are
defaulted. Next, one may specify modifiers, such as RADIX or
EXACTNESS, which themselves may be parameterized. The format
descriptors are:
(INT)
Express as an integer. The radix point is implicit. If there are
not enough significant places, as in trying to express 6.0238E23
(internally represented as a 7 digit FLONUM) as an integer we would
get "6023800################".
(RAT n)
Express as a rational fraction. n specifies the largest
denominator to be used in constructing a rational approximation to
the number being expressed. If n is omitted it defaults to
infinity.
(FIX n)
Express with a fixed radix point. n specifies the number of
places to the right of the radix point. n defaults to the size of a
single-precision FLONUM. If there are not enough significant
places, as in trying to express 6.0238E23 (internally represented
as a 7 digit FLONUM) as a (FIX 2) we would get
"6023800################.##".
(FLO n)
Express with a floating radix point. n specifies the total number
of places to be displayed. n defaults to the size of a single-
precision FLONUM. If the number is out of range, it is converted
to (SCI). (FLO H) allows the system to heuristically express a FLO
for human consumption (as in the MacLisp printer).
(SCI n m)
Express in exponential notation. n specifies the total number of
places to be displayed. n defaults to the size of a single-
precision FLONUM. m specifies the number of places to the right of
the radix point. m defaults to n-1. (SCI H) does heuristic
expression.
(RECT r i)
Express as a rectangular form complex number. r and i are formats
for the real and imaginary parts respectively. They default to