[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

*To*: scheme@MIT-MC.ARPA*Subject*: Message a011267 LONG message - part 2*From*: "Charlotte D. Mooers" <postmaster@CSNET-SH.ARPA>*Date*: 19 Mar 85 07:51:18 EST (Tue)*Reply-to*: cic@CSNET-SH.ARPA

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

- Prev by Date:
**Message a011267 LONG message - part 2** - Next by Date:
**Message a011267 LONG message - part 3** - Prev by thread:
**Message a011267 LONG message - part 2** - Next by thread:
**Message a011267 LONG message - part 3** - Index(es):