This document has two parts:
The best ways to locate things in this document are probably either to scroll haphazardly, or to use your HTML browser's "find" command to search for the term, concept or identifier that you are interested in, or for some other likely word.
This portion of the document is a command summary of the procedures, special forms, macros, and the like, that are provided as part of Wraith Scheme. It includes all of the standard Scheme stuff that Wraith Scheme provides, and also includes many other items that I have provided as enhancements.
The command summary is a supplement to the "R5 report", but definitely not a substitute for it.
The descriptions herein are specific to Wraith Scheme. Wraith Scheme generally follows the "R5" Scheme report, but there are many places in that report where some behavior of Scheme is left undefined, or is allowed to be implementation-dependent. In those cases, this document describes what Wraith Scheme does. For example, the R5 report often does not define the return values of procedures that are called for side effects: Wraith Scheme generally returns #t from such procedures, and the descriptions herein so indicate.
The command summary is arranged alphabetically, with a few exceptions. First, procedures that are enhancements -- that is, they are not part of R5 Scheme -- are listed at the very end. Their identifiers all begin with either "e::" or "c::". The procedures that begin with "e::" come before the procedures that begin with "c::".
Second, a few closely-related groups of procedures are presented together. They are:
Wraith Scheme does contain procedures and such that are not documented here; I have omitted many things used internally by the compiler, macro-generator, and so on, because they are complicated and more than likely to change in subsequent releases. I do not personally regard them as secrets. If you find something undocumented that you would like to know more about, send me EMail and ask, but don't count on any undocumented feature continuing to exist in future releases of Wraith Scheme.
General notes about the command summary entries:
And now, on to the command summary itself ...
Type:
Procedure.
Operation:
Arithmetic multiplication.
Arguments:
Zero or more numbers.
Side Effects:
None.
Returned Value:
A number: With two or more arguments, returns their product. With one argument, returns just the argument. With no arguments, returns 1.
For Example:
(* 2 3) ;; ==> 6 (* 1 2 3 4 5) ;; ==> 120 (* 2.5) ;; ==> 2.5 (*) ;; ==> 1
Type:
Procedure.
Operation:
Arithmetic addition.
Arguments:
Zero or more numbers.
Side Effects:
None.
Returned Value:
A number: The sum of its arguments, or 0 if there are no arguments.
For Example:
(+ 2 3) ;; ==> 5 (+ 1 2 3 4 5) ;; ==> 15 (+ 2.5) ;; ==> 2.5 (+) ;; ==> 0
Type:
Procedure.
Operation:
Arithmetic subtraction.
Arguments:
One or more numbers.
Side Effects:
None.
Returned Value:
A number: With two or more arguments, returns the first argument minus the sum of all the rest. With one argument, returns the argument subtracted from zero.
For Example:
(- 2 3) ;; ==> -1 (- 1 2 3 4 5) ;; ==> -13 (- 2.5) ;; ==> -2.5 (-) ;; ==> <error>
Type:
Procedure.
Operation:
Arithmetic division.
Arguments:
One or more numbers.
Side Effects:
None.
Returned Value:
A number: With two or more arguments, returns the first argument divided by the product of all the rest. With one argument, returns its reciprocal. Reports an error on any attempt to divide by zero.
For Example:
(/ 6 3) ;; ==> 2 (/ 3 4 5) ;; ==> 0.15 (/ .5) ;; ==> 2. (/) ;; ==> <error> (/ 0) ;; ==> <error> (/ 2 0) ;; ==> <error> (/ 2 3 4 0 5) ;; ==> <error>
Type:
Procedure.
Operation:
Arithmetic comparison: Less-than.
Arguments:
Two or more numbers.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, each argument is less than the one to its right. Otherwise, returns #f. Ignores the exactness of the arguments.
For Example:
(< 2 3) ;; ==> #t (< 3 2) ;; ==> #f (< 2 2) ;; ==> #f (< 2 3 4) ;; ==> #t (< 4 3 2) ;; ==> #f
Type:
Procedure.
Operation:
Arithmetic comparison: Less-than or equal to.
Arguments:
Two or more numbers
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, each argument is less than or equal to the one to its right. Otherwise, returns #f. Ignores the exactness of the arguments.
For Example:
(<= 2 3) ;; ==> #t (<= 3 2) ;; ==> #f (<= 2 2) ;; ==> #t (<= 2 3 4) ;; ==> #t (<= 4 3 2) ;; ==> #f
Type:
Procedure.
Operation:
Arithmetic comparison: Equality
Arguments:
Two or more numbers.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, all arguments are arithmetically equal. Otherwise, returns #f. Ignores the exactness of the arguments.
For Example:
(= 2 3) ;; ==> #f (= 3 2) ;; ==> #f (= 2 2) ;; ==> #t (= 2 3 4) ;; ==> #f (= 4 3 2) ;; ==> #f (= 4 (+ 2 2) (/ 20 5)) ;; ==> #t
Type:
Procedure.
Operation:
Arithmetic comparison: Greater than.
Arguments:
Two or more numbers.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, each argument is greater than the one to its right. Otherwise, returns #f. Ignores the exactness of the arguments.
For Example:
(> 2 3) ;; ==> #f (> 3 2) ;; ==> #t (> 2 2) ;; ==> #f (> 2 3 4) ;; ==> #f (> 4 3 2) ;; ==> #t
Type:
Variables, one for each kitten.
Operation:
The operation of Wraith Scheme sets or binds these variables to the third-from last quantity whose value was printed out by the "print" part of the top-level read-eval-print loop of the kitten in question. That is, in kitten 0 for example, the variable is the previous value of >**<, which is in turn the previous value of >*<, which is the most recent quantity printed out by the read-eval-print loop. These quantities are updated after the print has taken place; they may be used while Wraith Scheme is evaluating an expression in the "read" part of the read-eval-print loop. They form part of a rudimentary command-history mechanism that is contained within Wraith Scheme.
Each of these variables may be read by any Wraith Scheme process, not just the one in whose top-level loop it is bound.
Arguments:
(Does not apply.)
Side Effects:
(Does not apply.)
Returned Value:
(Does not apply.)
For Example:
;; In kitten 0: (+ 0 1) (+ 0 2) (+ 0 3) ;; At this point, and continuing through the ;; evaluation of the next Scheme expression, >***< ;; has the value 1.
Type:
Variables, one for each kitten.
Operation:
The operation of Wraith Scheme sets or binds these variables to the second-from last quantity whose value was printed out by the "print" part of the top-level read-eval-print loop of the kitten in question. That is, in kitten 0 for example, the variable is the previous value of >*<, which is the most recent quantity printed out by the read-eval-print loop. These quantities are updated after the print has taken place; they may be used while Wraith Scheme is evaluating an expression in the "read" part of the read-eval-print loop. They form part of a rudimentary command-history mechanism that is contained within Wraith Scheme.
Each of these variables may be read by any Wraith Scheme process, not just the one in whose top-level loop it is bound.
Arguments:
(Does not apply.)
Side Effects:
(Does not apply.)
Returned Value:
(Does not apply.)
For Example:
;; In kitten 0: (+ 0 1) (+ 0 2) (+ 0 3) ;; At this point, and continuing through the ;; evaluation of the next Scheme expression, >**< ;; has the value 2.
Type:
Variables, one for each kitten.
Operation:
The operation of Wraith Scheme sets or binds these variables to the last quantity whose value was printed out by the "print" part of the top-level read-eval-print loop of the kitten in question. These quantities are updated after the print has taken place; they may be used while Wraith Scheme is evaluating an expression in the "read" part of the read-eval-print loop. They form part of a rudimentary command-history mechanism that is contained within Wraith Scheme.
Each of these variables may be read by any Wraith Scheme process, not just the one in whose top-level loop it is bound.
Arguments:
(Does not apply.)
Side Effects:
(Does not apply.)
Returned Value:
(Does not apply.)
For Example:
;; In kitten 0: (+ 0 1) (+ 0 2) (+ 0 3) ;; At this point, and continuing through the ;; evaluation of the next Scheme expression, >*< ;; has the value 3.
Type:
Variables, one for each kitten.
Operation:
The operation of Wraith Scheme sets or binds these variables to the third-from last Scheme expression that was passed as input to the "read" part of the top-level read-eval-print loop of the kitten in question. That is, in kitten 0 for example, the variable is the previous value of >++<, which is in turn the previous value of >+<, which is the most recent quantity provided as input to the read-eval-print loop. These quantities are updated after the print has taken place; they may be used while Wraith Scheme is evaluating an expression in the "read" part of the read-eval-print loop. They form part of a rudimentary command-history mechanism that is contained within Wraith Scheme.
Each of these variables may be read by any Wraith Scheme process, not just the one in whose top-level loop it is bound.
Arguments:
(Does not apply.)
Side Effects:
(Does not apply.)
Returned Value:
(Does not apply.)
For Example:
;; In kitten 0: (+ 0 1) (+ 0 2) (+ 0 3) ;; At this point, and continuing through the ;; evaluation of the next Scheme expression, >+++< ;; has the value (+ 0 1).
Type:
Variables, one for each kitten.
Operation:
The operation of Wraith Scheme sets or binds these variables to the second-from last Scheme expression that was passed as input to the "read" part of the top-level read-eval-print loop of the kitten in question. That is, in kitten 0 for example, the variable is the previous value of >+<, which is the most recent quantity provided as input to the read-eval-print loop. These quantities are updated after the print has taken place; they may be used while Wraith Scheme is evaluating an expression in the "read" part of the read-eval-print loop. They form part of a rudimentary command-history mechanism that is contained within Wraith Scheme.
Each of these variables may be read by any Wraith Scheme process, not just the one in whose top-level loop it is bound.
Arguments:
(Does not apply.)
Side Effects:
(Does not apply.)
Returned Value:
(Does not apply.)
For Example:
;; In kitten 0: (+ 0 1) (+ 0 2) (+ 0 3) ;; At this point, and continuing through the ;; evaluation of the next Scheme expression, >++< ;; has the value (+ 0 2).
Type:
Variables, one for each kitten.
Operation:
The operation of Wraith Scheme sets or binds these variables to the last Scheme expression that was passed as input to the "read" part of the top-level read-eval-print loop of the kitten in question. These quantities are updated after the print has taken place; they may be used while Wraith Scheme is evaluating an expression in the "read" part of the read-eval-print loop. They form part of a rudimentary command-history mechanism that is contained within Wraith Scheme.
Each of these variables may be read by any Wraith Scheme process, not just the one in whose top-level loop it is bound.
Arguments:
(Does not apply.)
Side Effects:
(Does not apply.)
Returned Value:
(Does not apply.)
For Example:
;; In kitten 0: (+ 0 1) (+ 0 2) (+ 0 3) ;; At this point, and continuing through the ;; evaluation of the next Scheme expression, >+< ;; has the value (+ 0 3).
Type:
Variables, one for each kitten.
Operation:
While Wraith Scheme is evaluating a Scheme expression that was provided as input to the "read" part of the top-level read-eval-print loop of kitten 0, for example, ">-<" is bound to that expression itself. This value will become the value of ">+<" after the expression has been evaluated and its result printed.
Each of these variables may be read by any Wraith Scheme process, not just the one in whose top-level loop it is bound.
Arguments:
(Does not apply.)
Side Effects:
(Does not apply.)
Returned Value:
(Does not apply.)
For Example:
;; In kitten 0: (+ 0 1) (+ 0 2) (+ 0 3) ;; At this point, the value of >-< is undefined. ;; But suppose you type (define a (list >-<)) ;; and then type return. Then, while the "define" ;; is being evaluated, >-< will have the value ;; (define a (list >-<)), so when you subsequently ;; type a ;; Wraith Scheme will print ((define a (list >-<)))
Type:
Procedure.
Operation:
Arithmetic comparison: Greater than or equal to.
Arguments:
Two or more numbers.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, each argument is greater than or equal to the one on its right. Otherwise, returns #f. Ignores the exactness of the arguments.
For Example:
(>= 2 3) ;; ==> #f (>= 3 2) ;; ==> #t (>= 2 2) ;; ==> #t (>= 2 3 4) ;; ==> #f (>= 4 3 2) ;; ==> #t
Type:
Procedure.
Operation:
Arithmetic absolute value.
Arguments:
One number.
Side Effects:
None.
Returned Value:
A number: The absolute value of the argument.
For Example:
(abs 3) ;; ==> 3 (abs -3) ;; ==> 3
Type:
Procedure.
Operation:
Mathematical inverse cosine, or arc-cosine, function.
Arguments:
One number, in the range [-1, 1].
Side Effects:
None.
Returned Value:
A number: A number in the range [0, pi], taken as an angle in radians, whose cosine is the argument.
For Example:
(acos 1) ;; ==> 0 (acos 0) ;; ==> 1.5707963267948966 (acos -1) ;; ==> 3.1415926535897931
Type:
Operation:
Boolean and.
Arguments:
Zero or more Scheme objects of any kind.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, all the arguments are true. (Recall that the only Scheme object that is false is #f.) With no arguments, returns #t. Otherwise, returns #f.
This macro operates by evaluating its arguments one at a time, from left to right. When and if any argument evaluates to false, "and" returns false immediately, without evaluating any more arguments.
For Example:
(and) ;; ==> #t (and #t) ;; ==> #t (and #f) ;; ==> #f (and #t #t) ;; ==> #t (and #f #t) ;; ==> #f (define (foo) (begin (display "foo ") #f)) ;; ==> foo (define (bar) (begin (display "bar ") #t)) ;; ==> bar (and (foo) (bar)) ;; ==> foo #f ;; It didn't print "bar".
Type:
Procedure.
Operation:
Appends lists; that is, glues them together, head-to-tail. The last object "glued" need not be a list.
Arguments:
One or more arguments: All but the last of these must be proper lists. (A proper list is one that has finite length and is terminated by the empty list.) The last argument may be any Scheme object.
Side Effects:
None.
Returned Value:
Any Scheme object: With one argument, returns the argument. With more than one argument, builds a list from all but the last argument, by making copies of all of these lists and joining them in order, then makes the last argument be the cdr of the list so constructed, and returns that list.
For Example:
(append 1) ;; ==> 1 (append (list 1 2) (list 3 4)) ;; ==> (1 2 3 4) (append (list 1 2) 3) ;; ==> (1 2 . 3) (define a (list 1 2 3)) ;; ==> a (define b (list 4 5 6)) ;; ==> b (define ab (append a b)) ;; ==> ab a ;; ==> (1 2 3) ;; Not (1 2 3 4 5 6) b ;; ==> (4 5 6) ab ;; ==> (1 2 3 4 5 6) ;; But: (set-cdr! (cddr b) 7) ;; ==> #t b ;; ==> (4 5 6 . 7) ab ;; ==> (1 2 3 4 5 6 . 7) (define c (list 1)) ;; ==> c (set-cdr! c c) ;; ==> #t c ;; ==> (1 1 1 1 1 1 1 1 1 1 1 ... ) (append c ab) ;; ==> <error> ;; c is not a proper list.
Type:
Procedure.
Operation:
Calls a procedure with a list of arguments.
Arguments:
Two or more arguments: The first must be a procedure, the last must be a proper list, and each of the others, if any, may be any Scheme object.
Side Effects:
None by itself, though the procedure applied may cause side effects of its own.
Returned Value:
Any Scheme object: Calls the given procedure -- the first argument -- with a list of arguments built as follows:
With two arguments, as in (apply proc args), where args is a list, "proc" is called with "args" as its arguments.
With more than two arguments, as in (apply proc arg1 arg2 ... argn args), "proc" is called with the argument list (append (list arg1 arg2 ... argn) args).
For Example:
(apply + (list 1 2)) ;; ==> 3 ;; Equivalent to (+ 1 2) (apply + 1 2 (list 3 4)) ;; ==> 10 ;; Equivalent to ;; (+ 1 2 3 4), and to ;; (apply + (list 1 2 3 4)
Type:
Procedure.
Operation:
Mathematical inverse sine, or arc-sine, function.
Arguments:
One number, in the range [-1, 1].
Side Effects:
None.
Returned Value:
A number: A number in the range [-pi/2, pi/2], taken as an angle in radians, whose sine is the argument.
For Example:
(asin 1) ;; ==> 1.5707963267948966 (acos 0) ;; ==> 0 (acos -1) ;; ==> -1.5707963267948966
Type:
Procedure.
Operation:
Look up a key-value pair in a list thereof, using "equal?" as the predicate for testing for the presence of the key.
Arguments:
Two arguments: The first may be any Scheme object; the second must be a proper list of pairs.
Side Effects:
None.
Returned Value:
A pair: Returns the first pair in the second argument whose car is "equal?" to the first argument, or returns #f if there is no such pair.
For Example:
(assoc 1 '((1 2) (3 4))) ;; ==> (1 2) (assoc 3 '((1 2) (3 4))) ;; ==> (3 4) (assoc 42 '((1 2) (3 4))) ;; ==> #f
Type:
Procedure.
Operation:
Look up a key-value pair in a list thereof, using "eq?" as the predicate for testing for the presence of the key.
Arguments:
Two arguments: The first may be any Scheme object; the second must be a proper list of pairs.
Side Effects:
None.
Returned Value:
A pair: Returns the first pair in the second argument whose car is "eq?" to the first argument, or returns #f if there is no such pair.
For Example:
(assq 1 '((1 2) (3 4))) ;; ==> (1 2) (assq 3 '((1 2) (3 4))) ;; ==> (3 4) (assq 42 '((1 2) (3 4))) ;; ==> #f (assq (list 1 2) '(((1 2) 'foo) ((3 4) 'bar))) ;; ==> #f (define a (list 1 2)) ;; ==> a (define pair-list (list (list a 'foo) (list (list 3 4) 'bar))) ;; ==> pair-list pair-list ;; ==> (((1 2) foo) ((3 4) bar)) (assq a pair-list) ;; ==> ((1 2) foo) ;; The two "(1 2)"s refer ;; to the same object.
Type:
Procedure.
Operation:
Look up a key-value pair in a list thereof, using "eqv?" as the predicate for testing for the presence of the key.
Arguments:
Two arguments: The first may be any Scheme object; the second must be a proper list of pairs.
Side Effects:
None.
Returned Value:
A pair: Returns the first pair in the second argument whose car is "eqv?" to the first argument, or returns #f if there is no such pair.
For Example:
(assv 1 '((1 2) (3 4))) ;; ==> (1 2) (assv 3 '((1 2) (3 4))) ;; ==> (3 4) (assv 42 '((1 2) (3 4))) ;; ==> #f (assv (list 1 2) '(((1 2) 'foo) ((3 4) 'bar))) ;; ==> #f (define a (list 1 2)) ;; ==> a (define pair-list (list (list a 'foo) (list (list 3 4) 'bar))) ;; ==> pair-list pair-list ;; ==> (((1 2) foo) ((3 4) bar)) (assv a pair-list) ;; ==> ((1 2) foo)
Type:
Procedure.
Operation:
Mathematical inverse tangent, or arc-tangent, with one or two arguments. The two-argument version is called "atan2" by some.
Arguments:
One or two numbers.
Side Effects:
None.
Returned Value:
A number: With one argument, returns a number in the range [-pi/2, pi/2], taken as an angle in radians, whose tangent is the argument.
With two numbers, takes the arguments to be the coordinates of a point in the x/y plane, with the first argument being y and the second argument being x, and returns a number in the range (-pi, pi] which is the angle between the positive x-axis and the radius vector to that point. (The angle returned is negative if, and only if, y is negative.)
Note that (atan 0 0) returns 0. (The "R5" Scheme report appears to indicate that (atan 0 0) should return a value, but does not indicate what it should be.)
For Example:
(atan 1000) ;; ==> 1.5697963271282296 (atan -1000) ;; ==> -1.5697963271282296 (atan -1 0) ;; ==> -1.5707963267948966 (atan 0 -1) ;; ==> 3.1415926535897931 (atan -0.0000000001 -1000000000) ;; ==> -3.1415926535897931 (atan 0 0) ;; ==> 0
Type:
Operation:
Evaluate a sequence of Scheme expressions in the order given.
Arguments:
One or more Scheme expressions of any kind.
Side Effects:
None.
Returned Value:
Any Scheme object: Causes the evaluation each of its arguments in turn, and returns whatever resulted from the evaluation of the last argument.
Note that "begin" does not create a new environment: Each evaluation that "begin" causes takes place in the environment where the "begin" was encountered.
For Example:
(begin 1 2 3 4) ;; ==> 4 (begin (display "first ") (display "second ")) ;; ==> first second #t ;; In the top-level loop ... (begin (define a 42) (define b 137)) ;; ==> b a ;; ==> 42 b ;; ==> 137
Type:
Procedure.
Operation:
Test whether its argument is a boolean.
Arguments:
One Scheme object of any kind.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is either #t or #f. Returns #f otherwise.
For Example:
(boolean? #t) ;; ==> #t (boolean? #f) ;; ==> #t (boolean 'whatever) ;; ==> #f
Type:
Procedure.
Operation:
Creates an unnamed procedure of one argument, which encapsulates the current continuation in such a way that when that unnamed procedure is subsequently called, it will change the continuation that was present when the unnamed procedure was called to the continuation which is encapsulated. The unnamed procedure is passed as an argument to the procedure which is the argument to "call-with-current-continuation".
A continuation is in essence the entire internal state of the Scheme system. Thus when the unnamed procedure is called, it restores that state to whatever the state was when the unnamed procedure was created. If "call-with-current-continuation" was called during the middle of the execution of a particular Scheme procedure -- let's suppose that its name is "foo" -- then when the unnamed procedure thereby created is called, it will be as if "foo" was still running; "foo" will pick up right where "call-with-current-continuation" was called.
Recall that the unnamed procedure takes one argument. When it is called, whatever argument it was given appears in the restored continuation as if it had been returned from "call-with-current-continuation".
See the examples below for more details.
There is one rather technical caveat about the operation of "call-with-current-continuation": When the environment -- a complicated table of variable identifiers and their values -- is encapsulated into the current continuation, it is not copied; what is placed in the continuation is a reference, a pointer to the real environment. It is entirely possible that other Scheme procedures, such as "set!", will modify the real environment before the unnamed function created by "call-with-current-continuation" is called. Since the environment may have been modified, it is not correct to say that calling the unnamed function is guaranteed to restore the internal state of Scheme to what it was when the unnamed function was created.
The reason why the environment is not copied is that environments may be very large objects: They include everything in Scheme's memory that is not garbage. Thus there will often not be enough memory available to make a copy.
Arguments:
One argument, which must be a procedure that itself takes one argument.
Side Effects:
Saves the current state of Scheme in such a way that it can subsequently be restored at will.
Returned Value: Any Scheme object, or may never return:
The value returned will be either what the argument to "call-with-current-continuation" returns, or will be whatever value was passed to the unnamed procedure when -- and if -- that unnamed procedure was itself called.
For Example:
This first example is rather trivial. In it, the unnamed procedure prepared by "call-with-current-continuation" is passed as an argument to the predicate "procedure?", which does not call it -- "procedure?" simply affirms that that unnamed procedure is in fact a procedure, by returning #t.
(call-with-current-continuation procedure?) ;; ==> #t
The second example is from the "R5" report. Let's discuss it in detail.
(call-with-current-continuation (lambda (exit) (for-each (lambda (x) (if (negative? x) (exit x))) '(54 0 37 -3 245 19)) #t)) ;; ==> -3
The procedure which is the argument to "call-with-current-continuation" begins on the second line of the example; it is the lambda expression that starts with "(lambda (exit) ...". The unnamed procedure created by "call-with-current-continuation" is passed to that lambda expression as an argument, and the lambda gives the unnamed procedure a name -- "exit".
The lambda expression itself uses the "for-each" procedure with another, shorter lambda expression, to test each number in the list of six numbers in the sixth line, to see whether it is negative. If the number is not negative, nothing happens -- the lambda expression goes on to the next number. If no number were negative, the "for-each" procedure that is running the test would end, and the outer lambda expression would returns #t, from the seventh line, so that "call-with-current-continuation" would thereby returns #t.
However, one of the numbers -- the fourth one -- is in fact negative; it's -3. When the test encounters it, the "if" will call "exit" with a value of -3. Since "exit" has as value the unnamed procedure originally created by "call-with-current-continuation", "exit" will immediately restore the continuation where it was created, and in effect, "call-with-current-continuation" will returns immediately, with a value of -3.
There are perhaps easier ways to find the first negative number in a list. Notwithstanding, this example illustrates how "call-with-current-continuation" can be used to returns a meaningful value from deep within a function, without somehow going back through all the intervening code. This facility is useful, for example, in reporting errors in a complicated process.
Continuations are complicated and confusing. It is unlikely that any introduction to them that is as short as this one can succeed in describing continuations adequately to a person who is not already familiar with them.
Type:
Procedure.
Operation:
Open a port to an input file and call a procedure with the port as argument.
Arguments:
One or two arguments. The last should be a procedure that takes one argument. The first, if present, should be a string naming a file. If there is only one argument, Wraith Scheme will use the Wraith Scheme Dialog Panel to obtain the name of the file.
Side Effects:
None.
Returned Value:
Any Scheme object, or may not return: The called procedure need not return, but if it does, "call-with-input-file" will returns whatever the procedure returns.
For Example:
(call-with-input-file "foo" (read-char)) ;; ==> Read and returns one character from "foo". (call-with-input-file (read-char)) ;; ==> Read and return one character from a file pathname obtained from the user via the Wraith Scheme Dialog Panel
Type:
Procedure.
Operation:
Open a port to an output file and call a procedure with the port as argument.
Arguments:
One or two arguments. The last should be a procedure that takes one argument. The first, if present, should be a string naming a file. If there is only one argument, Wraith Scheme will use the Wraith Scheme Dialog Panel to obtain the name of the file.
Side Effects:
None.
Returned Value:
Any Scheme object, or may not return: The called procedure need not return, but if it does, "call-with-input-file" will return whatever the procedure returns.
For Example:
(call-with-output-file "foo" (write 1)) ;; ==> Write "1" to "foo" and return #t. (call-with-output-file (write 1)) ;; ==> Write "1" to a file whose pathname will be obtained from the user via the Wraith Scheme Dialog Panel
Type:
Procedure.
Operation:
Allow a procedure which returns multiple values to pass them as arguments to another procedure.
Arguments:
Two procedures. The first may return multiple values, via the "values" procedure. The second is the procedure to which the multiple values are intended to be passed; it will receive them as if they had been entered as individual arguments with the usual procedure-call syntax.
Side Effects:
None.
Returned Value:
Any Scheme object, or may not return: "call-with-values" in effect passes control to its second argument, and returns if and only if that procedure does, returning whatever that procedure returns.
For Example:
;; Here is a fancy way to add up the integers ;; from one through ten: This example passes ;; the list returned by "values" to "+", just ;; as if you had entered ;; ;; (+ 1 2 3 4 5 6 7 8 9 10) (call-with-values (lambda () (values 1 2 3 4 5 6 7 8 9 10)) +) ;; ==> 55 ;; We could equally well just list the numbers: (call-with-values (lambda () (values 1 2 3 4 5 6 7 8 9 10)) list) ;; ==> (1 2 3 4 5 6 7 8 9 10) ;; This rather cute example is from the R5 report: ;; Remember that the procedure call "(*)" returns "1". (call-with-values * +) ;; ==> 1
Type:
Procedure.
Operation:
Obtain the car of a pair.
Arguments:
One pair.
Side Effects:
None.
Returned Value:
Any Scheme object: The car of the argument.
For Example:
(car '(1 2)) ;; ==> 1 (car '(1 . 2)) ;; ==> 1 (car '(1)) ;; ==> 1 (car (list 1 2 3 4 5 6)) ;; ==> 1
Type:
Procedure.
Operation:
Obtain the cdr of a pair.
Arguments:
One pair.
Side Effects:
None.
Returned Value: Any Scheme object:
The cdr of the argument.
For Example:
(cdr '(1 2)) ;; ==> (2) (cdr '(1 . 2)) ;; ==> 2 (cdr '(1)) ;; ==> () (cdr (list 1 2 3 4 5 6)) ;; ==> (2 3 4 5 6)
caaar   caadr   cadar   caddr  
cdaar   cdadr   cddar   cdddr  
caaaar   caaadr   caadar   caaddr  
cadaar   cadadr   caddar   cadddr  
cdaaar   cdaadr   cdadar   cdaddr  
cddaar   cddadr   cdddar   cddddr  
Type:
Procedures.
Operation:
Convenience procedures for accessing components of nested pairs.
Arguments:
One argument, which must be a pair, and whose car and cdr may also have specific type requirements, depending on the procedure.
Side Effects:
None.
Returned Value:
Any Scheme object:
Each of these procedures is a combination (technically, a composition) of from two to four applications of either "car" or "cdr". Two easy ways of figuring out which combination is intended are as follows:
Split the procedure name into individual letters, drop the initial "c" and the final "r", change each "a" into "the car of" and change each "d" into "the cdr of". Thus for example
cadar
becomes
c a d a r
which becomes
a d a
which becomes
the car of the cdr of the car of
And "(cadar x)" does indeed return the car of the cdr of the car of x.
Alternatively, in a particular procedure call, split the procedure name into individual letters, drop the initial "c" and the final "r", change each "a" into "car" and change each "d" into "cdr", and add enough parentheses to make sense. Thus for example:
(cadar x)
becomes
(c a d a r x)
which becomes
(a d a x)
which becomes
(car cdr car x)
which becomes
(car (cdr (car x)))
And "(cadar x)" does indeed return what "(car (cdr (car x)))" would.
Each of these procedures will report an error if its argument does not possess the correct pair structure to have the element that the procedure is intended to retrieve. Thus "(caddr (list 1 2))" will report an error, because "(list 1 2)" does not have a caddr.
For Example:
(define a (list 1 2 3 4 5 6)) ;; ==> a (cadr a) ;; ==> 2 (cddr a) ;; ==> (3 4 5 6) (cdar a) ;; ==> <error> (caar a) ;; ==> <error> (cdddr a) ;; ==> (4 5 6) (cddddr a) ;; ==> (5 6) (cadddr a) ;; ==> 4 (define b (list (list (list (list 'a))) 2 3 4)) ;; ==> b b ;; ==> ((((a))) 2 3 4) (car b) ;; ==> (((a))) (caar b) ;; ==> ((a)) (caaar b) ;; ==> (a) (caaaar b) ;; ==> a ;; et cetera ad nauseam
Type:
Operation:
Evaluates an expression -- the "key" -- and compares the result (using "eqv?") to each element in the car of each of a series of lists -- the case clauses -- in turn. If a match is found, evaluates each element of the cdr of that case clause in left-to-right order, and returns whatever results from the evaluation of the last element.
If there is no match, there may be an "else" clause -- whose car is just "else" -- as the last clause of the case. If there is an "else" clause, evaluates each element of the cdr of the else clause in left-to-right order, and returns whatever results from the evaluation of the last element. If there is no match, and no else clause, returns #t.
Arguments:
One Scheme expression, followed by one or more proper lists, each of which has as its car either a proper list, or the symbol "else". The symbol "else" may only appear as the car of the last proper list of the "case" expression, and that last proper list need not necessarily begin with "else".
Side Effects:
None in its own right, but the evaluation of items in the clauses may cause arbitrary side effects.
Returned Value:
Arbitrary, depending on the clauses; may not return at all, depending on the clauses.
For Example:
(case (+ 1 0) ((1 3) 'first) ((2 3) 'second) (else 'third) ) ;; ==> first (case 2 ((1 3) 'first) ((2 3) 'second) (else 'third) ) ;; ==> second (case 3 ((1 3) 'first) ((2 3) 'second) (else 'third) ) ;; ==> first (case 4 ((1 3) 'first) ((2 3) 'second) (else 'third) ) ;; ==> third (case 4 ((1 3) 'first) ((2 3) 'second) ) ;; ==> #t
Type:
Procedure.
Operation:
Arithmetic round up.
Arguments:
One number.
Side Effects:
None.
Returned Value:
An integer: The smallest integer not smaller than the argument.
For Example:
(ceiling -6.5) ;; ==> -6. (ceiling 4) ;; ==> 4
Type:
Procedure.
Operation:
Convert a character to the integer that represents it; Wraith Scheme uses the ASCII standard for representing characters by integers.
Arguments:
One character.
Side Effects:
None.
Returned Value:
An integer: The integer whose ASCII character is the argument.
For Example:
(char->integer #\C) ;; ==> 67 (char->integer #\newline) ;; ==> 10
Type:
Procedure.
Operation:
Test whether the argument is a letter of the alphabet.
Arguments:
One character/
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a letter of the alphabet, in either upper case or lower case. Otherwise, returns false.
For Example:
(char-alphabetic? #\a) ;; ==> #t (char-alphabetic? #\!) ;; ==> #f
Type:
Procedure.
Operation:
Case-independently test the whether the integer representation of the first argument is less than or equal to the integer representation of the second. Wraith Scheme implements case-independence by converting any argument that is an upper-case letter to lower case before proceeding with the comparison.
Arguments:
Two characters.
Side Effects:
None.
Returned Value:
A boolean: Converts any argument that is an upper-case letter to lower case, and returns #t if, and only if, the integer whose ASCII character then represents the first argument is less than or equal to the integer whose ASCII character then represents the second argument. Otherwise, returns #f.
For Example:
(char-ci<=? #\a #\A) ;; ==> #t (char-ci<=? #\A #\b) ;; ==> #t (char-ci<=? #\a #\B) ;; ==> #t (char-ci<=? #\B #\a) ;; ==> #f (char-ci<=? #\b #\A) ;; ==> #f (char-ci<=? #\a #\[) ;; ==> #f (char-ci<=? #\A #\[) ;; ==> #f
Type:
Procedure.
Operation:
Case-independently test the whether the integer representation of the first argument is less than the integer representation of the second. Wraith Scheme implements case-independence by converting any argument that is an upper-case letter to lower case before proceeding with the comparison.
Arguments:
Two characters.
Side Effects:
None.
Returned Value:
A boolean: Converts any argument that is an upper-case letter to lower case, and returns #t if, and only if, the integer whose ASCII character then represents the first argument is less than the integer whose ASCII character then represents the second argument. Otherwise, returns #f.
For Example:
(char-ci<? #\a #\A) ;; ==> #f (char-ci<? #\A #\b) ;; ==> #t (char-ci<? #\a #\B) ;; ==> #t (char-ci<? #\B #\a) ;; ==> #f (char-ci<? #\b #\A) ;; ==> #f (char-ci<? #\a #\[) ;; ==> #f (char-ci<? #\A #\[) ;; ==> #f
Type:
Procedure.
Operation:
Case-independently test the whether the integer representation of the first argument is equal to the integer representation of the second. Wraith Scheme implements case-independence by converting any argument that is an upper-case letter to lower case before proceeding with the comparison.
Arguments:
Two characters.
Side Effects:
None.
Returned Value:
A boolean: Converts any argument that is an upper-case letter to lower case, and returns #t if, and only if, the integer whose ASCII character then represents the first argument is equal to the integer whose ASCII character then represents the second argument. Otherwise, returns #f.
For Example:
(char-ci=? #\a #\A) ;; ==> #t (char-ci=? #\A #\b) ;; ==> #f (char-ci=? #\a #\B) ;; ==> #f (char-ci=? #\B #\a) ;; ==> #f (char-ci=? #\b #\A) ;; ==> #f (char-ci=? #\a #\[) ;; ==> #f (char-ci=? #\A #\[) ;; ==> #f
Type:
Procedure.
Operation:
Case-independently test the whether the integer representation of the first argument is greater than or equal to the integer representation of the second. Wraith Scheme implements case-independence by converting any argument that is an upper-case letter to lower case before proceeding with the comparison.
Arguments:
Two characters.
Side Effects:
None.
Returned Value:
A boolean: Converts any argument that is an upper-case letter to lower case, and returns #t if, and only if, the integer whose ASCII character then represents the first argument is greater than or equal to the integer whose ASCII character then represents the second argument. Otherwise, returns #f.
For Example:
(char-ci>=? #\a #\A) ;; ==> #t (char-ci>=? #\A #\b) ;; ==> #f (char-ci>=? #\a #\B) ;; ==> #f (char-ci>=? #\B #\a) ;; ==> #t (char-ci>=? #\b #\A) ;; ==> #t (char-ci>=? #\a #\[) ;; ==> #t (char-ci>=? #\A #\[) ;; ==> #t
Type:
Procedure.
Operation:
Case-independently test the whether the integer representation of the first argument is greater than the integer representation of the second. Wraith Scheme implements case-independence by converting any argument that is an upper-case letter to lower case before proceeding with the comparison.
Arguments:
Two characters.
Side Effects:
None.
Returned Value:
A boolean: Converts any argument that is an upper-case letter to lower case, and returns #t if, and only if, the integer whose ASCII character then represents the first argument is greater than the integer whose ASCII character then represents the second argument. Otherwise, returns #f.
For Example:
(char-ci>? #\a #\A) ;; ==> #f (char-ci>? #\A #\b) ;; ==> #f (char-ci>? #\a #\B) ;; ==> #f (char-ci>? #\B #\a) ;; ==> #t (char-ci>? #\b #\A) ;; ==> #t (char-ci>? #\a #\[) ;; ==> #t (char-ci>? #\A #\[) ;; ==> #t
Type:
Procedure.
Operation:
Convert a character to lower case.
Arguments:
One character.
Side Effects:
None.
Returned Value:
A character: If the argument is an upper case letter, returns it in lower case, otherwise returns it unchanged.
For Example:
(char-downcase #\A) ;; ==> #\a (char-downcase #\a) ;; ==> #\a (char-downcase #\!) ;; ==> #\!
Type:
Procedure.
Operation:
Test whether an alphabetic character is in lower case.
Arguments:
One alphabetic character.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is in lower case. Otherwise, returns #f.
For Example:
(char-lower-case? #\a) ;; ==> #t (char-lower-case? #\A) ;; ==> #f (char-lower-case? #\!) ;; ==> <error>
Type:
Procedure.
Operation:
Test whether a character is a decimal digit.
Arguments:
One character.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a decimal digit. Otherwise, returns #f.
For Example:
(char-numeric? #\3) ;; ==> #t (char-numeric? #\a) ;; ==> #f
Type:
Procedure.
Operation:
Test whether there is a character or an eof-object ready to read on a port.
Arguments:
Either none, or one port.
Side Effects:
None.
Returned Value:
A boolean: The procedure performs a test for whether or not there is a character to be read from a port. If there is an argument, it is taken to be the port to be tested. If not, the port tested is whatever is returned by the procedure "current-input-port".
Returns #t if, and only if, there is either a character to be read from the port, or the port will return an end-of-file object. Otherwise, returns #f.
Interactive ports, such as the console (keyboard) will never return an end-of-file object.
For Example:
;; From the console, at top-level: (char-ready ?) ;; ==> #t ;; The character is the "return" ;; that sent the text ;; "(char-ready?)" ;; to Wraith Scheme. (define (foo) (read-char) (char-ready?)) ;; ==> foo (foo) ;; ==> #f ;; "read-char" read past the "return". ;; Suppose "port" is an input port to a file containing ;; just the text "abc". (char-ready? port) ;; ==> #t (read-char port) ;; ==> #\a (char-ready? port) ;; ==> #t (read-char port) ;; ==> #\b (char-ready? port) ;; ==> #t (read-char port) ;; ==> #\c (char-ready? port) ;; ==> #t (read-char port) ;; ==> #<End of File> ;; How Wraith Scheme ;; displays an ;; end-of-file object. (char-ready? port) ;; ==> #t (read-char port) ;; ==> #<End of File> (char-ready? port) ;; ==> #t (read-char port) ;; ==> #<End of File> (char-ready? port) ;; ==> #t (read-char port) ;; ==> #<End of File> ;; To infinity, and beyond ...
Type:
Procedure.
Operation:
Convert a character to upper case.
Arguments:
One character.
Side Effects:
None.
Returned Value:
A character: If the argument is a lower case letter, returns it in upper case, otherwise returns it unchanged.
For Example:
(char-upcase #\A) ;; ==> #\A (char-upcase #\a) ;; ==> #\A (char-upcase #\!) ;; ==> #\!
Type:
Procedure.
Operation:
Test whether an alphabetic character is in upper case.
Arguments:
One alphabetic character.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is in upper case. Otherwise, returns #f.
For Example:
(char-upper-case? #\a) ;; ==> #f (char-upper-case? #\A) ;; ==> #t (char-upper-case? #\!) ;; ==> <error>
Type:
Procedure.
Operation:
Test whether a character is white space; that is, whether it is a space, tab, line feed, form feed, or carriage-return.
Arguments:
One character.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is white space. Otherwise, returns #t
For Example:
(char-whitespace? #\a) ;; ==> #f (char-whitespace? #\space) ;; ==> #t
Type:
Procedure.
Operation:
Test whether the integer representation of the first argument is less than or equal to the integer representation of the second.
Arguments:
Two characters.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the integer whose ASCII character represents the first argument is less than or equal to the integer whose ASCII character represents the second argument. Otherwise, returns #f.
For Example:
(char<=? #\a #\A) ;; ==> #t (char<=? #\A #\b) ;; ==> #t (char<=? #\a #\B) ;; ==> #f (char<=? #\B #\a) ;; ==> #t (char<=? #\b #\A) ;; ==> #f (char<=? #\a #\[) ;; ==> #f (char<=? #\A #\[) ;; ==> #t
Type:
Procedure.
Operation:
Test whether the integer representation of the first argument is less than the integer representation of the second.
Arguments:
Two characters.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the integer whose ASCII character represents the first argument is less than to the integer whose ASCII character represents the second argument. Otherwise, returns #f.
For Example:
(char<? #\a #\A) ;; ==> #f (char<? #\A #\b) ;; ==> #t (char<? #\a #\B) ;; ==> #f (char<? #\B #\a) ;; ==> #t (char<? #\b #\A) ;; ==> #f (char<? #\a #\[) ;; ==> #f (char<? #\A #\[) ;; ==> #t
Type:
Procedure.
Operation:
Test whether the first argument is equal to the second.
Arguments:
Two characters.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the first argument is equal to the second. Otherwise, returns #f.
For Example:
(char=? #\a #\A) ;; ==> #f (char=? #\A #\b) ;; ==> #f (char=? #\a #\B) ;; ==> #f (char=? #\B #\a) ;; ==> #f (char=? #\b #\A) ;; ==> #f (char=? #\a #\[) ;; ==> #f (char=? #\A #\[) ;; ==> #f
Type:
Procedure.
Operation:
Test whether the integer representation of the first argument is greater than or equal to the integer representation of the second.
Arguments:
Two characters.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the integer whose ASCII character represents the first argument is greater than or equal to the integer whose ASCII character represents the second argument. Otherwise, returns #f.
For Example:
(char>=? #\a #\A) ;; ==> #t (char>=? #\A #\b) ;; ==> #f (char>=? #\a #\B) ;; ==> #t (char>=? #\B #\a) ;; ==> #f (char>=? #\b #\A) ;; ==> #t (char>=? #\a #\[) ;; ==> #t (char>=? #\A #\[) ;; ==> #f
Type:
Procedure.
Operation:
Test whether the integer representation of the first argument is greater than the integer representation of the second.
Arguments:
Two characters.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the integer whose ASCII character represents the first argument is greater than the integer whose ASCII character represents the second argument. Otherwise, returns #f.
For Example:
(char>=? #\a #\A) ;; ==> #f (char>=? #\A #\b) ;; ==> #f (char>=? #\a #\B) ;; ==> #t (char>=? #\B #\a) ;; ==> #f (char>=? #\b #\A) ;; ==> #t (char>=? #\a #\[) ;; ==> #t (char>=? #\A #\[) ;; ==> #f
Type:
Procedure.
Operation:
Test whether the argument is a character.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a character. Otherwise, returns #f.
For Example:
(char? #\a) ;; ==> #t (char? #\!) ;; ==> #t (char? 42) ;; ==> #f
Type:
Procedure.
Operation:
Close an input port.
Arguments:
One input port.
Side Effects:
If the argument is an open port, closes it.
Returned Value:
#t
For Example:
;; Suppose "foo" is the path to a readable file (define foo-port (open-input-file "foo")) ;; ==> foo-port (close-input-port foo-port) ;; ==> #t
Type:
Procedure.
Operation:
Close an output port.
Arguments:
One output port.
Side Effects:
If the argument is an open port, closes it.
Returned Value:
#t
For Example:
(define foo-port (open-output-file "foo")) ;; ==> foo-port (close-output-port foo-port) ;; ==> #t
Type:
Procedure.
Operation:
Test whether the argument is a complex number.
Arguments:
One scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a complex number. Otherwise, returns #f. Informally, "complex?" returns #t for every number except nans and infs, because every such number lies somewhere in the complex plane. All of Wraith Scheme's numbers lie on the real axis, but they are nonetheless in the complex plane.
For Example:
(complex? 0) ;; ==> #t (complex? (expt 10 1000000)) ;; ==> #f ;; It's an inf. (complex? #t) ;; ==> #f
Type:
Operation:
Examines a series of given clauses, each of which must be a proper list. For each clause in turn, evaluates the car of the list: If that car is true, the evaluates all the rest of the items in the list in turn, and returns whatever the last item evaluates to. If the car is false, goes on to the next given clause. If no given clause has a car that evaluates to true, returns #t. The last of the given clauses may start with the symbol "else", which is treated as if it were #t.
Arguments:
Zero or more proper lists, the last of which may have "else" as car.
Side Effects:
None in its own right, but the evaluation of items in the clauses may cause arbitrary side effects.
Returned Value:
Arbitrary, depending on the clauses; may not return at all, depending on the clauses.
For Example:
(cond) ;; ==> #f (cond (#f 1) (#f 2) (#f 3)) ;; ==> #t (cond (#f 1) (#f 2) (#t 3)) ;; ==> 3 (cond (#f 1) (#f 2) (#t 3 4 (+ 5 6))) ;; ==> 11 (cond (#f 1) (#f 2) (else 3)) ;; ==> 3 (cond ((= (* 6 9) 42) 'peculiar) ((= (* 6 9) 54) 'mundane) ) ;; ==> mundane
Type:
Procedure.
Operation:
Allocate storage for a newly-formed pair.
Arguments:
Two Scheme objects.
Side Effects:
Allocates main memory.
Returned Value:
A pair whose car is the first argument and whose cdr is the second argument. If the first argument is an item represented by a pointer to Scheme memory, then the car of the returned pair is "eq?" to the second argument. If the second argument is an item represented by a pointer to Scheme memory, then the cdr of the returned pair is "eq?" to the second argument.
For Example:
(cons 1 2) ;; ==> (1 . 2) (cons 'a '()) ;; ==> (a) (cons 1 (list 2 3 4 5)) ;; ==> (1 2 3 4 5) (cons (list 1 2 3) (list 4 5 6)) ;; ==> ((1 2 3) 4 5 6)
Type:
Procedure.
Operation:
Mathematical cosine.
Arguments:
One number, taken to be an angle in radians.
Side Effects:
None.
Returned Value:
A number: The cosine of the argument.
For Example:
(cos 0) ;; ==> 1 (cos 1.5707963267948966) ;; ==> 6.123031769111886e-17 ;; Very nearly zero. (cos 0.7853981633974483) ;; ==> 0.7071067811865476
Type:
Procedure.
Operation:
Returns the port from which input is presently being taken.
Arguments:
None.
Side Effects:
None.
Returned Value:
A port: The port from which input is presently being taken.
For Example:
;; When input is being taken from the keyboard: (current-input-port) ;; ==> #<Console Input Port>
Type:
Procedure.
Operation:
Returns the port from to which output is presently being sent.
Arguments:
None.
Side Effects:
None.
Returned Value:
A port: The port from which input is presently being taken.
For Example:
;; When input is being sent to the display: (current-output-port) ;; ==> #<Console Output Port>
Type:
Operation:
Sets or binds an identifier to a value in the top-level environment, or, as an internal definition, in an environment associated with a procedure or special form.
Arguments:
There are three syntaxes:
First syntax: Two arguments, the first an identifier and the second any Scheme object.
Second syntax: Two or more arguments, the first a proper list of one or more identifiers, and the rest any Scheme objects.
Third syntax: Two or more arguments, the first a list of identifiers to which is appended a final identifier; that is, a list of the form (identifier1 identifier2 ... identifierN-1 . identifierN), the noteworthy feature being the dot before the final identifier, and the rest any Scheme objects.
Side Effects:
First Syntax: If the first argument has never had a value or binding in the relevant environment, gives it one. If a previous binding or value of the first argument does exist in the relevant environment, modifies it. In either case, the first argument ends up with the second argument as its value or binding, (depending on whether the second argument is of a kind that requires a binding).
In the case of internal definitions, the argument cannot have a previous binding, since the syntax restricts such definitions to the beginning of the lexical scope for the environment in question.
Second Syntax: The second syntax is shorthand, or "syntactic sugar" for binding an identifier to a lambda expression. The first element of the first argument is taken to be the identifier. The remaining elements of the first argument are taken to be the formal arguments to the lambda expression. The remaining arguments are taken to be the contents of the body of the lambda expression. Thus
(define (name var1 var2 ... varN) expression1 expression2 ... expressionN )
is equivalent to
(define name (lambda (var1 var2 ... varN) expression1 expression2 ... expressionN ) )
Third Syntax: The second syntax is shorthand, or "syntactic sugar" for binding an identifier to a lambda expression. The first element of the first argument is taken to be the identifier. The remaining elements, of the first argument, except the one after the dot, are taken to be formal arguments to the lambda expression, and the identifier after the dot has bound to it a list of any remaining actual arguments to the lambda expression when it is called. The remaining arguments to "define" are taken to be the contents of the body of the lambda expression. Thus
(define (name var1 var2 ... varN-1 . varN) expression1 expression2 ... expressionN )
is equivalent to
(define name (lambda (var1 var2 ... varN-1 . varN) expression1 expression2 ... expressionN ) )and
(define (name . var) expression1 expression2 ... expressionN )
is equivalent to
(define name (lambda var expression1 expression2 ... expressionN ) )
Returned Value:
First syntax: the first argument.
Second and third syntaxes: the first element of the first argument.
For Example:
(define a 42) ;; ==> a a ;; ==> 42 (define a 'foo) ;; ==> a a ;; ==> foo (define (hypotenuse x y) (sqrt (+ (* x x) (* y y)))) ;; ==> hypotenuse (hypotenuse 5 12) ;; ==> 13 (define (foo a) (display a)) ;; ==> foo (foo 1 2 3 4 5) ;; ==> (1 2 3 4 5)#t (define (foo b . c) (display b) (display c)) ;; ==> foo (foo 1 2 3 4 5) ;; ==> 1(2 3 4 5)#t
Type:
Operation:
Define an hygienic macro at top-level.
Arguments:
One symbol and one <transformer spec>, the latter according to the grammar of "R5" report section 4.3.2.
Side Effects:
If the first argument has never had a value or binding in the top-level environment, gives it one. If a previous binding or value of the first argument does exist in the top-level environment, modifies it. In either case, the first argument ends up with the macro transformer corresponding to the second argument, as its a binding.
Returned Value:
The first argument.
For Example:
(define-syntax when (syntax-rules () ((when test stmt) (if test stmt)) ((when test stmt ...) (if test (begin stmt ...)) ))) ;; ==> when (when #t 3) ;; ==> 3 (when #f 3) ;; ==> #f (when #t (display "foo\n") (display "bar\n") 42) ;; ==> foo bar 42
Type:
Operation:
Encapsulate a Scheme expression in such a way that it can be evaluated subsequently, by the "force" procedure, and its value then returned.
Arguments:
One Scheme object of any kind.
Side Effects:
None in its own right; side effects due to the eventual evaluation of the argument may occur, depending on the argument.
Returned Value:
A promise.
For Example:
;; Note how Wraith Scheme displays a promise: (delay (display "Carpe diem\n")) ;; ==> #<Promise> (define foo (delay (begin (display "Carpe diem\n") 123))) ;; ==> foo (force foo) ;; ==> Carpe diem ;; Side effect of evaluation. 123 ;; The returned value. (force foo) ;; ==> 123 ;; Evaluation happens only once -- ;; the returned value is saved so ;; it may be returned repeatedly. (force foo) ;; ==> 123
Type:
Procedure.
Operation:
Output an external representation of a Scheme object in a form intended easily to be read by sentient beings. Contrast with "write", whose output is intended easily to be read by computers and programmers ...
Arguments:
One or two arguments. The first may be any Scheme object. The second, if present, must be an open output port.
Side Effects:
Writes output -- if there is a second argument, to that port, otherwise, to the current output port.
Returned Value:
#t
For Example:
(display "This string\nhas three\nembedded newlines.\n") ;; ==> This string has three embedded newlines. #t (display 5/7) ;; ==> 0.7142857142857143#t (let ((my-port (open-output-file "Foo"))) (display 5/7 my-port) (close-output-port my-port)) ;; ==> #t ;; And writes to "Foo".
Type:
Operation:
Perform iteration, testing a termination condition before each iteration; optionally, create an environment, with local variables, in which the iterations are to be performed, and with means of initializing those values and bindings, and of changing them during successive iterations.
CAUTION: Wraith Scheme's implementation of "do" is abysmally slow, and uses vast amounts of memory.
Technical Note: Wraith Scheme needs "do" because the R5 standard requires it. The present release provides a version that works, but I suggest that you avoid it when you can. I may get around to writing a better implementation some day, but that is a low-priority task: I don't use "do" much myself.
Arguments:
At least two:
The first argument is a proper list, each of whose arguments is a list of two or three elements. The first is an identifier, the second an initial value or binding for the identifier, and the third, if present, an expression to be evaluated after each iteration, whose evaluation provides the value or binding for the identifier for the next iteration.
The second argument is a proper list of two or more arguments. The first is a test to be evaluated before each iteration; if it evaluates to true, no further iterations are performed, the remaining elements of the second argument are evaluated in sequence, and the "do" returns the result of the last such evaluation. If the test evaluates to false, the next iteration is performed.
The remaining arguments are evaluated in sequence during each iteration.
Side Effects:
None in its own right, but possibly many in consequence of the nature of the arguments.
Note that Wraith Scheme's present implementation of "do" is very slow and uses lots of memory.
Returned Value:
Any Scheme object, depending on the arguments; or the do may never return.
For Example:
(do ((vec (make-vector 3)) (k 0 (+ k 1))) ((= k 3) vec) (vector-set! vec k (* k k))) ;; ==> #(0 1 4)The syntax of "do" is sometimes confusing. Let me put some comments and some extra words into the previous example, to make it clearer: Think of the italicized words as comments.
(do ;; List of initialization-and-update clauses: ;; Each specifies a variable name, its initial ;; value, and any automatic update to it, that ;; takes place after each pass through the loop. ((vec (make-vector 3)) ;; No automatic change to vec. (k 0 (+ k 1))) ;; Change k to (+ k 1) after each loop. ;; Loop test and body follow ... (if (= k 3) then-return vec) ;; ((= k 3)) would stop the do but ;; return an undefined value. else (vector-set! vec k (* k k)) ;; Update variables as specified in the clauses for ;; initialization-and-update -- e.g., replace k by ;; (+ k 1) -- and then go back for another pass ;; through the loop test and body. ) ;; ==> #(0 1 4)
Type:
Procedure.
Operation:
Force two given procedures to be called when execution respectively enters and leaves the dynamic extent of another given procedure. The first argument is to be called on entry to the dynamic extent of the second, and the third on exit from the dynamic extent of the second.
Arguments:
Three procedures, each of which must accept no arguments.
Side Effects:
None in its own right, but the given procedures may have side effects of their own.
Returned Value:
Whatever the second argument returns, if it returns at all.
For Example:
(let ((path '()) (c #f)) (let ((add (lambda (s) (set! path (cons s path))))) (dynamic-wind (lambda () (add 'connect)) (lambda () (add (call-with-current-continuation (lambda (c0) (set! c c0) 'talk1)))) (lambda () (add 'disconnect))) (if (< (length path) 4) (c 'talk2) (reverse path)))) ;; ==> (connect talk1 disconnect connect talk2 disconnect)
Type:
Reserved identifier, for use in "cond", which see.
Operation:
None.
Arguments:
Does not apply.
Side Effects:
Does not apply.
Returned Value:
Does not apply.
For Example:
See "cond".
Type:
Procedure.
Operation:
Test whether the argument is an end-of-file object.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean. Returns #t if, and only if, the argument is an end-of-file object. Otherwise, returns #f.
For Example:
;; Suppose foo is an input port to a file containing ;; three characters, and that Wraith Scheme has already ;; read those characters. (eof-object? (read-char? foo)) ;; ==> #t (eof-object? 42) ;; ==> #f
Type:
Procedure.
Operation:
Test whether two Scheme objects are the same in the sense that either
(1) the objects are of the same kind, and the same region of Scheme main memory is used to store both, so that any alteration of one object necessarily alters the other (this form of identity is sometimes called "pointer equality"), or
(2) the objects are of the same kind, and each can be represented entirely within the 32-bit pointer field of a Scheme tagged pointer, and the necessary 32-bit representations are identical.
Technical Note: The behavior of "eq?" is allowed to be implementation-dependent; what Wraith Scheme does is first make sure that the objects are the same kind, and if so, return #t if, and only if, their pointer fields are identical, or if they are certain objects such as #t, #f and '(), which do not require the pointer field at all.
Arguments:
Two Scheme objects.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if the two arguments are identical in the sense described in the "Operation" section above.. Otherwise, returns #f.
For Example:
(eq? 1 1) ;; ==> #t (eq? 1 2) ;; ==> #f (eq? #\a #\a) ;; ==> #t (eq? #\a #\b) ;; ==> #f (eq? #t #t) ;; ==> #t (eq? #t #f) ;; ==> #f (define a (list 1 2)) ;; ==> a (define b (cons a '())) ;; ==> b (eq? a (car b)) ;; ==> #t (define c (list 1 2)) ;; ==> c (eq? a c) ;; ==> #f ;; Two different lists. (eq? (list 1 2) (list 1 2)) ;; ==> #f ;; Ditto.
Type:
Procedure.
Operation:
Test for equality of Scheme objects by recursively descending through pairs, lists, vectors, and strings, and applying "eqv?" to compare their contents where further recursive descent does not occur.
Arguments:
Two Scheme objects.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the arguments are equal in the sense described in the "Operation" section above. Otherwise, returns #f. May not return, if the data structures being compared are circular.
For Example:
(equal? 1 1) ;; ==> #t (equal? 1 2) ;; ==> #f (equal? #\a #\a) ;; ==> #t (equal? #\a #\b) ;; ==> #f (equal? #t #t) ;; ==> #t (equal? #t #f) ;; ==> #f (define a (list 1 2)) ;; ==> a (define b (cons a '())) ;; ==> b (equal? a (car b)) ;; ==> #t (define c (list 1 2)) (equal? a c) ;; ==> #t ;; Different lists notwithstanding. (equal? (list 1 2) (list 1 2)) ;; ==> #t ;; Ditto.
Type:
Procedure.
Operation:
Test whether two Scheme objects should "normally be regarded as the same object" (according to the R5 report). What Wraith Scheme does is return #t if the objects are "eq?", or if they are both numbers, both have the same value, and are either both exact or both inexact.
Technical Note: Much of the vagueness in the R5 definition of "eqv?" stems from the prospect that some Scheme implementations may upon occasion be able to prove that functions that do not have identical source code always return the same value when given the same arguments. Wraith Scheme makes no pretensions of ever being able to do any such thing; it returns #t from an "eqv?" test on functions only in case of pointer identity.
Arguments:
Two Scheme objects.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if the arguments are "eq?". If not, returns #t if the arguments are both numbers, and have the same numeric value, and are either both exact or both inexact. Otherwise, returns #f.
For Example:
(eqv? 1 1) ;; ==> #t (eqv? 1 2) ;; ==> #f (eqv? #\a #\a) ;; ==> #t (eqv? #\a #\b) ;; ==> #f (eqv? #t #t) ;; ==> #t (eqv? #t #f) ;; ==> #f (define a (list 1 2)) ;; ==> a (define b (cons a '())) ;; ==> b (eqv? a (car b)) ;; ==> #t (define c (list 1 2)) (eqv? a c) ;; ==> #f ;; Two different lists. (eqv? (list 1 2) (list 1 2)) ;; ==> #f ;; Ditto. (eqv? 1 #e1.0) ;; ==> #t (eqv? 1 #i1.0) ;; ==> #f
Type:
Procedure.
Operation:
Evaluate an expression in a specified environment.
Arguments:
One Scheme object, and one instance of what is returned by one of the procedures "interaction-environment", "null-environment", or "scheme-machine-environment".
Side Effects:
None in its own right, but the side effects of evaluating an expression may be substantial.
Returned Value:
The result of the evaluation.
For Example:
(eval '(+ 2 2) (interaction-environment)) ;; ==> 4 (eval '(+ 2 2) (scheme-report-environment 5)) ;; ==> 4 (eval '(+ 2 2) (null-environment 5)) ;; ==> <error> ;; "+" is not defined in the null environment. (eval '(if #t 2 3) (null-environment 5)) ;; ==> 2 (define a 42) ;; ==> a a ;; ==> 42 (let ((a 3)) a) ;; ==> 3 (let ((a 3)) (eval 'a (interaction-environment))) ;; ==> 42
Type:
Procedure.
Operation:
Test whether an integer is even.
Arguments:
One integer.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is an even number. Otherwise, returns #f.
For Example:
(even? 42) ;; ==> #t (even? 137) ;; ==> #f
Type:
Procedure.
Operation:
Determine an inexact representation of a number.
Arguments:
One number.
Side Effects:
None.
Returned Value:
An inexact number whose value is the same as the argument.
For Example:
(exact->inexact 1) ;; ==> 1. (exact->inexact #i1) ;; ==> 1.
Type:
Procedure.
Operation:
Test whether a number is exact.
Arguments:
One number.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is exact. Otherwise, returns #f.
For Example:
(exact? 1) ;; ==> #t (exact? 1.) ;; ==> #f
Type:
Procedure.
Operation:
Mathematical exponentiation.
Arguments:
One number.
Side Effects:
None.
Returned Value:
A number: Returns the base of the natural logarithms raised to the argument.
For Example:
(exp 0) ;; ==> 1 (exp 1) ;; ==> 2.7182818284590451 (exp -2.5) ;; ==> 0.0820849986238988
Type:
Procedure.
Operation:
Raise a number to a power.
Arguments:
Two numbers. Reports an error when Wraith Scheme's numeric types cannot express the result, e.g., for the square root of -1.
Side Effects:
None.
Returned Value:
The first argument raised to the second argument.
For Example:
(expt 2 3) ;; ==> 8 (expt 3 2) ;; ==> 9 (expt 2 0.5) ;; ==> 1.4142135623730951 (expt 1.4142135623730951 0.5) ;; ==> 1.189207115002721 (expt -1 0.5) ;; ==> <error>
Type:
Procedure.
Operation:
Arithmetic round down.
Arguments:
One number.
Side Effects:
None.
Returned Value:
An integer: The largest integer not larger than the argument.
For Example:
(floor -6.5) ;; ==> -7. (ceiling 4) ;; ==> 4
Type:
Procedure.
Operation:
Call a procedure many times, with different arguments, in a specified order.
Arguments:
Two or more. The first argument is the procedure to call. The rest must all be proper lists of the same length, and the number of arguments beyond the first must equal the number of arguments with which the procedure is to be called. On the first call, the arguments passed to the procedure are the first elements of each list, in the same order as the lists. On the second call, the passed arguments are the second elements of the lists, and so on.
Side Effects:
None in its own right, but the intended purpose of "for-each" is to call a procedure repeatedly, for side effects, so there will likely be side effects, depending on the arguments.
Returned Value:
#t
For Example:
(define (make-sandwich first second bread) (display first) (display " and ") (display second) (display " on ") (display bread) (newline) 'yum) ;; ==> make-sandwich (for-each make-sandwich (list "ham" "tuna" "tofu" "peanut butter") (list "cheese" "tomato" "sprouts" "asparagus") (list "rye" "whole wheat" "seven-grain" "banana bread") ) ;; ==> ham and cheese on rye tuna and tomato on whole wheat tofu and sprouts on seven-grain peanut butter and asparagus on banana bread #t
Type:
Procedure.
Operation:
Cause the evaluation of a Scheme expression previously encapsulated as a promise, for lazy evaluation, by the "delay" procedure; or if that promise has already been forced, return whatever value it returned at that time.
Arguments:
One promise.
Side Effects:
None in its own right, though the evaluation of the promise may cause side effects, depending on the nature of the promise.
Returned Value:
As promised.
For Example:
;; Note how Wraith Scheme displays a promise: (delay (display "Carpe diem\n")) ;; ==> #<Promise> (define foo (delay (begin (display "Carpe diem\n") 123))) ;; ==> foo (force foo) ;; ==> Carpe diem ;; Side effect of evaluation. 123 ;; The returned value. (force foo) ;; ==> 123 ;; Evaluation happens only once -- ;; the returned value is saved so ;; it may be returned repeatedly. (force foo) ;; ==> 123
Type:
Procedure.
Operation:
Mathematical greatest common divisor.
Arguments:
Two integers.
Side Effects:
None.
Returned Value:
An integer: Returns the greatest common divisor of the two arguments.
For Example:
(gcd 28 98) ;; ==> 14 (gcd 999999999999 209457) ;; ==> 333
Type:
Operation:
Conditional evaluation, based on a test.
Arguments:
Two or three Scheme objects.
Side Effects:
None in its own right, others depending on the arguments.
Returned Value:
Evaluates the first argument: If the result is true, evaluates the second argument and returns the result of so doing. If the first argument evaluates to false, and there is a third argument, returns the result of evaluating the third argument. If the first argument evaluates to false, and there is no third argument, returns #f.
For Example:
(if #t (+ 1 2) (+ 3 4)) ;; ==> 3 (if #f (+ 1 2) (+ 3 4)) ;; ==> 7 (if #f (+ 1 2)) ;; ==> #f
Type:
Procedure.
Operation:
Determine an exact representation of a number.
Arguments:
One number.
Side Effects:
None.
Returned Value:
An exact number whose value is the same as the argument.
For Example:
(inexact->exact 1) ;; ==> 1 (inexact->exact #i1) ;; ==> 1
Type:
Procedure.
Operation:
Test whether a number is inexact. p>
Arguments:
One number.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is inexact. Otherwise, returns #f.
For Example:
(inexact? 1) ;; ==> #f (inexact? 1.) ;; ==> #t
Type:
Procedure.
Operation:
Test whether the argument is an input port.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is an input port. Otherwise, returns #f. Note that once an input port has been closed, it is no longer a port in the sense of the R5 report, because it cannot deliver characters on demand.
For Example:
(define foo (open-input-file "This.file.must.exist")) ;; ==> foo (input-port? foo) ;; ==> #t (close-input-port foo) ;; ==> #t (input-port? foo) ;; ==> #f (input-port? 42) ;; ==> #f
Type:
Procedure.
Operation:
Determine the ASCII character represented by the argument.
Arguments:
One integer in the range [0..127]
Side Effects:
None.
Returned Value:
A character: Returns the ASCII character represented by the argument.
For Example:
(integer->char 65) ;; ==> #\A (integer->char 128) ;; ==> <error>
Type:
Procedure.
Operation:
Test whether the argument is an integer.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is an integer. Otherwise, returns #f.
For Example:
(integer? 3) ;; ==> #t (integer? 3.1) ;; ==> #f ;; Technically, an integer is a real number with no fractional ;; part. The floating-point representations used by Wraith ;; Scheme do not contain enough bits to represent the ;; fractional parts of numbers of large absolute value, hence ;; such numbers are necessarily reported as integers. Thus: (integer? (/ 1.e100 3)) ;; ==> #t ;; Note that in Wraith Scheme (/ 1.e100 3) ;; ==> 3.3333333333333332e99 ;; which is 33333333333333332 followed by lots of zeros -- ;; unarguably the external representation of an integer.
Type:
Procedure.
Operation:
Return the Scheme environment in which expressions typed in the top-level read-eval-print loop are evaluated.
Arguments:
None.
Side Effects:
None.
Returned Value:
The top-level environment of Wraith Scheme.
For Example:
(eval '(+ 2 2) (interaction-environment)) 4
Type:
Operation:
Create an unnamed procedure
Arguments:
Two or more. There are three syntaxes:
First syntax: Two or more arguments, the first a proper list of one or more identifiers, and the rest any Scheme objects.
Second syntax: Two or more arguments, the first a list of identifiers to which is appended a final identifier; that is, a list of the form (identifier1 identifier2 ... identifierN-1 . identifierN), the noteworthy feature being the dot before the final identifier, and the rest any Scheme objects.
Third syntax: Two or more arguments, the first an identifier and the rest any Scheme objects.
Side Effects:
None.
Returned Value:
A lambda expression. The arguments after the first are the body of the lambda expression. The meaning of the first argument varies:
First syntax: The first argument is a list of the formal arguments of the lambda expression.
Second syntax: All elements of the first argument before the dot are taken to be formal arguments to the lambda expression, and the identifier after the dot will have a list of any remaining actual arguments to the lambda expression bound to it when the lambda expression is called.
Third syntax: The first argument will have a list of all actual arguments to the lambda expression bound to it when the lambda expression is called.
For Example:
(define hypotenuse (lambda (x y) (sqrt (+ (* x x) (* y y))))) ;; ==> hypotenuse (hypotenuse 5 12) ;; ==> 13 (define foo (lambda a (display a))) ;; ==> foo (foo 1 2 3 4 5) ;; ==> (1 2 3 4 5)#t (define foo (lambda (b . c) (display b) (display c))) ;; ==> foo (foo 1 2 3 4 5) ;; ==> 1(2 3 4 5)#t
Type:
Procedure.
Operation:
Mathematical least common multiple.
Arguments:
Two integers.
Side Effects:
None.
Returned Value:
An integer: Returns the least common multiple of the arguments.
For Example:
(lcm 24 60) ;; ==> 120 (lcm 99 88) ;; ==> 792
Type:
Procedure.
Operation:
Find the length of a proper list.
Arguments:
One proper list.
Side Effects:
None.
Returned Value:
An integer: Returns the length of the list.
For Example:
(length (list 'a 'b 'c)) ;; ==> 3 (length '()) ;; ==> 0 (length '(1 2 . 3)) ;; ==> <error>
Type:
Operation:
Creates an environment with local variables which have initial values or bindings, and evaluates expressions therein. The local variables created may not access each other in establishing their initial values. Contrast with "let*".
Arguments:
Two or more. The first is a list of two-element sublists, the first element in each sublist being an identifier and the second, when evaluated, being the initial value or binding for that identifier. All remaining arguments are the expressions to be evaluated, in the order given, in the environment so created.
Side Effects:
Creates a local environment. Other side effects possible, depending on the arguments.
Returned Value:
Whatever results from the evaluation of the last argument.
For Example:
(define a 'aa) ;; ==> a (define b 'bb) ;; ==> b (define c 'cc) ;; ==> c (let ((a c) ;; Local a gets the top-level value of c, which is 'cc (b a) ;; Local b gets the top-level value of a, which is 'aa (c b)) ;; Local c gets the top-level value of b, which is 'bb (list a b c)) ;; ==> (cc aa bb) ;; The values local to the let.
Type:
Operation:
Creates an environment with local variables whose bindings are the transformers of hygienic macros (according to the "R5" description thereof), and evaluates expressions therein. The local variables created may not access each other in establishing their initial values. Contrast with "letrec-syntax".
Arguments:
Two or more. The first is a list of two-element sublists, the first element in each sublist being an identifier and the second a <transformer spec>, according to the grammar of "R5" report section 4.3.2. All remaining arguments are the expressions to be evaluated, in the order given, in the environment so created.
Side Effects:
Creates a local environment. Other side effects possible, depending on the arguments.
Returned Value:
Whatever results from the evaluation of the last argument.
For Example:
(let ((x 'outer)) (let-syntax ((m (syntax-rules () ((m) x)))) (test::let ((x 'inner)) (m)))) ;; ==> outer
Type:
Operation:
Creates an environment with local variables which have initial values or bindings, and evaluates expressions therein. Each local variable created may access the local variables created before it when establishing its initial value. Contrast with "let".
Arguments:
Two or more. The first is a list of two-element sublists, the first element in each sublist being an identifier and the second, when evaluated, being the initial value or binding for that identifier. All remaining arguments are the expressions to be evaluated, in the order given, in the environment so created.
Side Effects:
Creates a local environment. Other side effects possible, depending on the arguments.
Returned Value:
Whatever results from the evaluation of the last argument.
For Example:
(define a 'a) ;; ==> aa (define b 'b) ;; ==> bb (define c 'c) ;; ==> cc (let* ((a c) ;; Local a gets the top-level value of c, which is cc (b a) ;; Local b gets the local value of a, which is cc (c b)) ;; Local c gets the local value of b, which is cc (list a b c)) ;; ==> (cc cc cc) ;; The values local to the let.
Type:
Operation:
Creates an environment with local variables which have initial values or bindings, and evaluates expressions therein. Each local variable created may access all local variables created by the letrec when establishing its initial value, which typically makes the most sense when what the variables are bound functions that reference one another.. Contrast with "let" and "let*".
Wraith Scheme does NOT report an error if the local variables of a letrec are used in such a way that the initialization expressions are undefined: Wraith Scheme handles "letrec" by creating a local environment in which the local variables all have values of '() -- the R5 report merely states that such pre-initialization values are undefined. Thus the example used for let and let* gives the following result for letrec:
(define a 'aa) ;; ==> a (define b 'bb) ;; ==> b (define c 'cc) ;; ==> c (letrec ((a c) ;; Local a gets the top-level value of c, which is 'cc (b a) ;; Local b gets the top-level value of a, which is 'aa (c b)) ;; Local c gets the top-level value of b, which is 'bb (list a b c)) ;; ==> (() () ()) ;; All uninitialized.
That latter result, however, need not obtain with other Scheme implementations.
Arguments:
Two or more. The first is a list of two-element sublists, the first element in each sublist being an identifier and the second, when evaluated, being the initial value or binding for that identifier. All remaining arguments are the expressions to be evaluated, in the order given, in the environment so created.
Side Effects:
Creates a local environment. Other side effects possible, depending on the arguments.
Returned Value:
Whatever results from the evaluation of the last argument.
For Example:
(letrec ((my-even? (lambda (n) (if (zero? n) #t (my-odd? (- n 1))))) (my-odd? (lambda (n) (if (zero? n) #f (my-even? (- n 1)))))) (my-even? 42)) ;; ==> #t
Type:
Operation:
Creates an environment with local variables which have initial bindings to transformers of hygienic macros, according to the "R5" description thereof. Evaluates expressions therein. Each local variable created may access all local variables created by the letrec-syntax when establishing its initial value, which typically makes the most sense when what the variables are macros that reference one another.. Contrast with "let-syntax".
Wraith Scheme does NOT report an error if the local variables of a letrec-syntax are used in such a way that the initialization expressions are undefined: Wraith Scheme handles "letrec-syntax" by creating a local environment in which the local variables all have values of '().
Arguments:
Two or more. The first is a list of two-element sublists, the first element in each sublist being an identifier and the second a <transformer spec>, according to the grammar of "R5" report section 4.3.2. All remaining arguments are the expressions to be evaluated, in the order given, in the environment so created.
Side Effects:
Creates a local environment. Other side effects possible, depending on the arguments.
Returned Value:
Whatever results from the evaluation of the last argument.
For Example:
(letrec-syntax ((my-or (syntax-rules () ((my-or) #f) ((my-or e) e) ((my-or e1 e2 ...) (let ((temp e1)) (if temp temp (my-or e2 ...))))))) (my-or)) ;; ==> #f
Type:
Procedure.
Operation:
Make a list.
Arguments:
Zero or more Scheme objects.
Side Effects:
None.
Returned Value:
A list of the arguments, in order.
For Example:
(list) ;; ==> () (list 1 2 3) ;; ==> (1 2 3)
Type:
Procedure.
Operation:
Convert a list of characters to a string containing them in the given order.
Arguments:
Zero or more characters.
Side Effects:
None.
Returned Value:
A string whose characters are the arguments, in order.
For Example:
(list->string '()) ;; ==> "" (list->string '(#\C #\a #\t)) ;; ==> "Cat"
Type:
Procedure.
Operation:
Convert a list of Scheme objects to a vector containing them in the given order.
Arguments:
Zero or more Scheme objects.
Side Effects:
None.
Returned Value:
A vector whose elements are the arguments, in order.
For Example:
(list->vector '()) ;; ==> #() (list->vector (list 1 (list 2 3 4) (* 6 7) "Foo")) ;; ==> #(1 (2 3 4) 42 "Foo")
Type:
Procedure.
Operation:
Obtain an element of a proper list, based on its position.
Arguments:
One proper list and one non-negative integer.
Side Effects:
None.
Returned Value:
A Scheme object: Returns the (zero-based) nth element of the first argument, where n is the second argument.
For Example:
(list-ref 0 '(1 2 3)) ;; ==> 1 (list-ref 1 '(1 2 3)) ;; ==> 2 (list-ref 2 '(1 2 3)) ;; ==> 3
Type:
Procedure.
Operation:
Identify a sublist of a given list made by removing elements from the front of the given list.
Arguments:
One proper list and one non-negative integer.
Side Effects:
None.
Returned Value:
A list: Returns the list obtained from the first argument by removing its first n elements, where n is the second argument. The result shares structure with the first argument: Modifying the result, for example by set-car! or set-cdr!, will modify the first argument.
For Example:
(list-tail 0 '(1 2 3)) ;; ==> (1 2 3) (list-tail 1 '(1 2 3)) ;; ==> (2 3) (list-tail 2 '(1 2 3)) ;; ==> (3) (list-tail 3 '(1 2 3)) ;; ==> ()
Type:
Procedure.
Operation:
Test whether a Scheme object is a proper list.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a proper list. Otherwise, returns #f.
For Example:
(list '()) ;; ==> #t (list '(1 2 3 4 5) ;; ==> #f (list '(1 2 3 4 . 5) ;; ==> #f (define a (list 1)) ;; ==> a (set-cdr! a a) ;; ==> #t (list? a) ;; ==> #f ;; circular list
Type:
Procedure.
Operation:
Load a file, and process its contents as if they had been entered at the keyboard. Wraith Scheme prints the results of any such evaluation, but not the literal text of the file itself.
Arguments:
At most one: If an argument is present, it must be a string containing a Unix-style path to the file to be loaded. If no argument is present, Wraith Scheme will use the Wraith Scheme Dialog Panel to obtain such a path from the user.
Side Effects:
Depends on the arguments.
Returned Value:
#t
For Example:
(load "/Users/MyName/MyFavoriteSchemeCode.s") ;; loads file ;; ==> #t (load) ;; Wraith Scheme Dialog Panel prompts for pathname.
Type:
Procedure.
Operation:
Mathematical natural logarithm.
Arguments:
One nonnegative number.
Side Effects:
None.
Returned Value:
A number: Returns the natural logarithm of the argument.
For Example:
(log 1) ;; ==> 0 (log 2.7182818284590451) ;; ==> 1. (log (/ 2.7182818284590451)) ;; ==> -1.
Type:
Procedure.
Operation:
Create a string, and optionally fill it with a specific character.
Arguments:
One or two: The first a nonnegative integer, the second, if present, a character.
Side Effects:
None.
Returned Value:
A string: Returns a string whose length is the first argument. If the second argument is present, every character in the new string will be the same as the second argument. If there is no second argument, the string will be filled with blanks.
For Example:
(make-string 0) ;; ==> "" (make-string 3) ;; ==> " " (make-string 3 #\q) ;; ==> "qqq"
Type:
Procedure.
Operation:
Create a vector, and optionally fill it with a specific Scheme object.
Arguments:
One or two: The first a nonnegative integer, the second, if present, any Scheme object.
Side Effects:
None.
Returned Value:
A vector: Returns a vector whose length is the first argument. If the second argument is present, every character in the new vector will be the same as the second argument. If there is no second argument, the vector will be filled with the empty list.
For Example:
(make-vector 0) ;; ==> #() (make-vector 3) ;; ==> #(() () ()) (make-vector 3 (list 1 2)) ;; ==> #((1 2) (1 2) (1 2))
Type:
Procedure.
Operation:
Call a procedure many times, with different arguments, in an unspecified order, and return a list of the results.
Arguments:
Two or more. The first argument is the procedure to call. The rest must all be proper lists of the same length, and the number of arguments beyond the first must equal the number of arguments with which the procedure is to be called. There will be as many calls of the procedure as there are elements in each list. There is no guarantee that the calls will be in any specified order, but for purposes of explanation, let us number them from one to N, N being the number of elements in each list.
On call number 1, the arguments passed to the procedure are the first elements of each list, in the same order as the lists. On call number 2, the passed arguments are the second elements of the lists, and so on.
Side Effects:
None in its own right, but there may be side effects of the procedure calls, depending on the arguments.
Returned Value:
A list of results of the call, in order from 1 to N, as outlined in the "Operation" section above.
For Example:
(define (make-sandwich first second bread) (display first) (display " and ") (display second) (display " on ") (display bread) (newline) (if (equal? bread "banana bread") 'yech 'yum)) ;; ==> make-sandwich (map make-sandwich (list "ham" "tuna" "tofu" "peanut butter") (list "cheese" "tomato" "sprouts" "asparagus") (list "rye" "whole wheat" "seven-grain" "banana bread") ) ;; ==> (yum yum yum yech)
Type:
Procedure.
Operation:
Arithmetic maximum.
Arguments:
One or more numbers.
Side Effects:
None.
Returned Value:
A number: Returns the maximum of the arguments.
For Example:
(max 1) ;; ==> 1 (max -17 23 -102.5 9) ;; ==> 23
Type:
Procedure.
Operation:
Identify the first sublist of a list whose car is "equal?" to a given object.
Arguments:
Two: The first is any Scheme object, the second a proper list.
Side Effects:
None.
Returned Value:
Returns the first (longest) sublist of the second argument whose car is "equal?" to the first argument. If no such sublist exists, returns #f.
For Example:
(member 2 (list 1 2 3)) ;; ==> (2 3) (member 'b '(a b c)) ;; ==> (b c) (member (list 'a) '(b (a) c)) ;; ==> ((a) c)
Type:
Procedure.
Operation:
Identify the first sublist of a list whose car is "eq?" to a given object.
Arguments:
Two: The first is any Scheme object, the second a proper list.
Side Effects:
None.
Returned Value:
Returns the first (longest) sublist of the second argument whose car is "eq?" to the first argument. If no such sublist exists, returns #f.
For Example:
(memq 2 (list 1 2 3)) ;; ==> (2 3) (memq 'b '(a b c)) ;; ==> (b c) (memq (list 'a) '(b (a) c)) ;; ==> #f
Type:
Procedure.
Operation:
Identify the first sublist of a list whose car is "eqv?" to a given object.
Arguments:
Two: The first is any Scheme object, the second a proper list.
Side Effects:
None.
Returned Value:
Returns the first (longest) sublist of the second argument whose car is "eqv?" to the first argument. If no such sublist exists, returns #f.
For Example:
(memv 2 (list 1 2 3)) ;; ==> (2 3) (memv 'b '(a b c)) ;; ==> (b c) (memv (list 'a) '(b (a) c)) ;; ==> #f
Type:
Procedure.
Operation:
Arithmetic minimum
Arguments:
One or more numbers.
Side Effects:
None.
Returned Value:
A number: Returns the minimum of the arguments.
For Example:
(min 1) ;; ==> 1 (min -17 23 -102.5 9) ;; ==> -102.5
Type:
Procedure.
Operation:
Mathematical modulus.
Arguments:
Two integers.
Side Effects:
None. o
Returned Value:
An integer: Returns the first argument modulo the second.
For Example:
(modulo 13 4) ;; ==> 1 (modulo -13 4) ;; ==> 3 (modulo 13 -4) ;; ==> -3 (modulo -13 -4) ;; ==> -1
Type:
Procedure.
Operation:
Test whether a number is negative.
Arguments:
One number.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is negative. Otherwise, returns #f.
For Example:
(negative 0) ;; ==> #f (negative 1) ; ; ==> #f (negative -1) ;; ==> #t
Type:
Procedure.
Operation:
Write a newline character, the ASCII character whose numeric representation is 10, to a port.
Arguments:
At most one, a port.
Side Effects:
Writes a newline to the given port, if there is an argument, or to the current output port, if not.
Returned Value:
#t
For Example:
(newline) ;; ==> ;; Just wrote a newline. ;; Suppose "foo" is an output port: (newline foo) ;; ==> #t ;; Wrote a newline to foo
Type:
Procedure.
Operation:
Boolean negation.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is #f. Otherwise, returns #f.
For Example:
(not #f) ;; ==> #t (not 42) ;; ==> #f (not '()) ;; ==> #f
Type:
Procedure.
Operation:
Return a Scheme environment which is supposed to contain only the syntactic keywords of Scheme, but which in Wraith Scheme contains a few more bindings.
Arguments:
One, which must be the exact integer 5.
Side Effects:
None.
Returned Value:
The null environment of Wraith Scheme, which contains bindings for the following symbols:
=> and begin c::begin c::if c::lambda case cond define delay do else if lambda let let* letrec or quasiquote quote set! unquote unquote-splicing
The "extra" symbols are macros used in defining several of the syntactic keywords. I couldn't come up with any other reasonable place to put them.
For Example:
(eval '(if #t 2 3) (null-environment 5)) 2
Type:
Procedure.
Operation:
Test whether an object is the empty list.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is the empty list. Otherwise, returns #f.
For Example:
(null? #f) ;; ==> #f (null? 42) ;; ==> #f (null? '()) ;; ==> #t
Type:
Procedure.
Operation:
Create a string containing an external representation of a given number.
Arguments:
One or two: The first a number, the second an exact integer, either 2, 8, 10 or 16, corresponding to the radix in which the number is to be represented.
Side Effects:
None.
Returned Value:
A string: Returns a string representing the first argument in the given radix, if a second argument is present, or in radix 10 if there is no second argument. The result never contains a radix prefix. The result must be such that, informally, if you read it back in using "string->number" in the correct radix, the number you get is "eqv?" to the original argument.
For Example:
(number->string 10) ;; ==> "10" (number->string 10 2) ;; ==> "1010" (number->string 10 8) ;; ==> "12" (number->string 10 16) ;; ==> "a"
Type:
Procedure.
Operation:
Test whether a Scheme object is a number.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a number. Otherwise, returns #f. Wraith Scheme considers nans and infs not to be numbers.
For Example:
(number? 'foo) ;; ==> #f (number? 1.234) ;; ==> #t (number? 1e10000) ;; ==> #f ;; inf (number? (/ 1e10000 1e10000) ;; ==> #f ;; nan
Type:
Procedure.
Operation:
Test whether an integer is odd.
Arguments:
One integer.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is an odd number. Otherwise, returns #f.
Many people think that all numbers are odd. I do not sympathize, but perhaps that is because I am odd myself.
For Example:
(odd? 42) ;; ==> #f (odd? 137) ;; ==> #t
Type:
Procedure.
Operation:
Open a port to a file for input.
Arguments:
At most one: If present, a string containing a Unix-style path to the file to be opened. If there is no argument, Wraith Scheme will use the Wraith Scheme Dialog Panel to obtain a path from the user.
Side Effects:
Opens a port.
Returned Value:
An input port.
For Example:
(open-input-file "/Users/Me/MySourceFile.s") ;; ==> <Input Port ... > ;; The text will describe the port (open-input-file) ;; Wraith Scheme will use the Dialog Panel ;; to obtain the path to the file.
Type:
Procedure.
Operation:
Open a port to a file for output.
Arguments:
At most one: If present, a string containing a Unix-style path to the file to be opened. If there is no argument, Wraith Scheme will use the Wraith Scheme Dialog Panel to obtain a path from the user.
Side Effects:
Opens a port.
Returned Value:
An output port.
For Example:
(open-output-file "/Users/Me/MyOutputFile.text") ;; ==> <Output Port ... > ;; The text will describe the port (open-output-file) ;; Wraith Scheme will use the Dialog Panel ;; to obtain the path to the file.
Type:
Operation:
Boolean or.
Arguments:
Zero or more Scheme objects of any kind.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, at least one of the arguments is true. (Recall that the only Scheme object that is false is #f.) With no arguments, returns #f. Otherwise, returns #f
This macro operates by evaluating its arguments one at a time, from left to right. When and if any argument evaluates to true, "or" returns true immediately, without evaluating any more arguments.
For Example:
(and) ;; ==> #t (or #t) ;; ==> #t (or #f) ;; ==> #f (or #t #t) ;; ==> #t (or #f #t) ;; ==> #t (or #f #f) ;; ==> #f (define (foo) (begin (display "foo ") #f)) ;; ==> foo (define (bar) (begin (display "bar ") #t)) ;; ==> bar (or (bar) (foo)) ;; ==> bar #t ;; It didn't print "foo".
Type:
Procedure.
Operation:
Test whether the argument is an output port.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is an output port. Otherwise, returns #f. Note that once an output port has been closed, it is no longer a port in the sense of the R5 report, because it cannot accept characters on demand.
For Example:
(define foo (open-output-file "Some.output.file")) ;; ==> foo (output-port? foo) ;; ==> #t (close-output-port foo) ;; ==> #t (output-port? foo) ;; ==> #f (output-port? 42) ;; ==> #f
Type:
Procedure.
Operation:
Test whether the argument is a pair.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a pair. Otherwise, returns #f.
For Example:
(pair? '(1 . 2)) ;; ==> #t (pair? (list 1 2)) ;; ==> #t (pair? '()) ;; ==> #f (pair? 42) ;; ==> #f
Type:
Procedure.
Operation:
Obtain the next character available from an input port -- or hang waiting if none is available -- without doing anything to cause the port to advance to to the next character.
Arguments:
At most one, an input port.
Side Effects:
None.
Returned Value:
A character or an end-of file object: If there is an argument, obtain the result from that port. If there is no argument, obtain the result from the current input port. The procedure may not return immediately, if the port is to an interactive device, such as the keyboard, which has no character ready.
For Example:
;; Suppose that foo is an input port just opened to ;; a text file containing just one character, "a": (peek-char foo) ;; ==> #\a (peek-char foo) ;; ==> #\a (peek-char foo) ;; ==> #\a (peek-char foo) ;; ==> #\a (read-char foo) ;; ==> #\a (peek-char foo) ;; ==> #<End of File>
Type:
Procedure.
Operation:
Test whether the argument is a port.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a port. Otherwise, returns #f. Note that once a port has been closed, it is no longer a port as Scheme uses the term, because it can neither accept nor provide characters on demand.
For Example:
(define foo (open-output-file "Some.output.file")) ;; ==> foo (define bar (open-input-file "Some.existing.input.file")) ;; ==> bar (port? foo) ;; ==> #t (port? bar) ;; ==> #t (close-output-port foo) ;; ==> #t (close-input-port bar) ;; ==> #t (port? foo) ;; ==> #f (port? bar) ;; ==> #f (port? 42) ;; ==> #f
Type:
Procedure.
Operation:
Test whether a number is positive.
Arguments:
One number.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is positive. Otherwise, returns #f.
For Example:
(positive 0) ;; ==> #f (positive 1) ;; ==> #t (positive -1) ;; ==> #f
Type:
Procedure.
Operation:
Test whether a Scheme object is a procedure.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a procedure. Returns #f otherwise.
Macros and special forms are not procedures.
For Example:
(procedure? +) ;; ==> #t (procedure? (lambda (x) (+ x 1))) ;; ==> #t (procedure? lambda) ;; ==> #f (procedure? let) ;; ==> #f
Additional Syntax:
Backquote: `<whatever> is equivalent to (quasiquote <whatever>).
Type:
Operation:
Instantiate literal data with an option for partial evaluation using "unquote" or "unquote-splicing". Thus, (quasiquote <whatever>) evaluates to <whatever>, but if any subexpression of <whatever> begins with either "unquote" or "unquote-splicing", or with their respective syntactic equivalents, "," or ",@", then that subexpression will be evaluated according to the rules for unquote or unquote-splicing before being inserted into <whatever>.
The macros "quasiquote", "unquote" and "unquote-splicing" may be nested within <whatever>: Starting with a nesting level of zero at the the left end of <whatever>, each "quasiquote" increases the nesting level by one, and each "unquote" or "unquote-splicing" reduces it by one, and normal evaluation occurs only when the nesting level thus determined is zero.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
The argument, with no further evaluation except as directed by "unquote" or by "unquote-splicing".
For Example:
(define foo "A string named foo") ;; ==> foo (quasiquote foo) ;; ==> foo `foo ;; ==> foo (quasiquote ,foo) ;; ==> "A string named foo." `,foo ;; ==> "A string named foo." (define a 42) ;; ==> a (quasiquote (+ 2 a)) ;; ==> (+ 2 a) `(+ 2 a) ;; ==> (+ 2 a) `(+ 2 ,a) ;; ==> (+ 2 42) (define b (list 27 18 28)) ;; ==> b `(+ 2 b) ;; ==> (+ 2 b) `(+ 2 ,b) ;; ==> (+ 2 (27 18 28)) ;; Doesn't add up .... `(+ 2 ,@b) ;; ==> (+ 2 27 18 2)
Additional Syntax:
Quote: '<whatever> is equivalent to (quote <whatever>).
Type:
Operation:
Instantiate literal data; that is, (quote <whatever>) evaluates to <whatever>.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
The argument, without further evaluation.
For Example:
(quote foo) ;; ==> foo 'foo ;; ==> foo (quote (+ 2 2)) ;; ==> (+ 2 2) '(+ 2 2) ;; ==> (+ 2 2)
Type:
Procedure.
Operation:
Mathematical quotient.
Arguments:
Two integers.
Side Effects:
None.
Returned Value:
An integer: The quotient of the first number by the second.
For Example:
(quotient 13 4) ;; ==> 3 (quotient -13 4) ;; ==> -3 (quotient 13 -4) ;; ==> -3 (quotient -13 -4) ;; ==> 3
Type:
Procedure.
Operation:
Test whether the argument is a rational number.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a rational number. Otherwise, returns #f.
For Example:
(rational? #t) ;; ==> #f (rational? 1) ;; ==> #t (rational? 1.5) ;; ==> #t (rational? (sqrt 2)) ;; ==> #t ;; Note that in Wraith Scheme (sqrt 2) ;; ==> 1.4142135623730951 ;; which is 14142135623730951/10000000000000000 ;; and thus is rational.
Type:
Procedure.
Operation:
Read one Scheme object from a port. What is read must "parse"; that is, it must be a valid external representation of a Scheme object, but "read" does not evaluate it.
Arguments:
At most one: If present, an input port.
Side Effects:
None.
Returned Value:
A Scheme object: If an argument is present, returns the next Scheme object available from that port, or an end-of-file object; if not, returns the next Scheme object available at the current input port, or an end-of-file object.
For Example:
;; Suppose "foo" is a newly-opened input port to a file containing ;; the text "(+ 2 2) No more". (read foo) ;; ==> (+ 2 2) (read foo) ;; ==> No (read foo) ;; ==> more (read foo) ;; ==> <End of File>
Type:
Procedure.
Operation:
Obtain the next character available from an input port -- or hang waiting if none is available.
Arguments:
At most one, an input port.
Side Effects:
Reads from a port.
Returned Value:
A character or an end-of file object: If there is an argument, obtain the result from that port. If there is no argument, obtain the result from the current input port. The procedure may not return immediately, if the port is to an interactive device, such as the keyboard, which has no character ready.
For Example:
;; Suppose that foo is an input port just opened to ;; a text file containing the text "abc": (read-char foo) ;; ==> #\a (read-char foo) ;; ==> #\b (read-char foo) ;; ==> #\c (read-char foo) ;; ==> #<End of File> (read-char foo) ;; ==> #<End of File> (read-char foo) ;; ==> #<End of File>
Type:
Procedure.
Operation:
Test whether the argument is a real number.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a real number. Otherwise, returns #f.
For Example:
(real? #t) ;; ==> #f (real? 1) ;; ==> #t (real? 1.5) ;; ==> #t (real? (sqrt 2)) ;; ==> #t
Type:
Procedure.
Operation:
Mathematical remainder.
Arguments:
Two integers.
Side Effects:
None.
Returned Value:
An integer: The remainder of the first number when divided (in the sense of "quotient") by the second.
For Example:
(remainder 13 4) ;; ==> 1 (remainder -13 4) ;; ==> -1 (remainder 13 -4) ;; ==> 1 (remainder -13 -4) ;; ==> -1
Type:
Procedure.
Operation:
Reverse a proper list.
Arguments:
One proper list.
Side Effects:
None.
Returned Value:
A list: Returns a newly-created list whose elements are the elements of the argument in reverse order.
For Example:
(reverse '()) ;; ==> () (reverse (list 1 2 3)) ;; ==> (3 2 1)
Type:
Procedure.
Operation:
Arithmetic round to nearest integer.
Arguments:
One number.
Side Effects:
None.
Returned Value:
An integer: The closest integer to the argument, rounding to even when the argument is half way between two integers.
For Example:
(round 3.49) ;; ==> 3. (round 3.51) ;; ==> 4. (round 3.5) ;; ==> 4. (round 2.5) ;; ==> 2.
Type:
Procedure.
Operation:
Return a Scheme environment which contains the bindings in the null environment, plus all other bindings that are either required by the R5 report or are optional and are supported by Wraith Scheme.
Arguments:
One, which must be the exact integer 5.
Side Effects:
None.
Returned Value:
The Scheme-report environment of Wraith Scheme.
For Example:
(eval '(+ 2 2) (scheme-report-environment 5)) 4
Type:
Operation:
Arguments:
Two: The first, an identifier; the second, any Scheme object.
Side Effects:
Changes a pre-existing variable value or binding; informally, changes the value of a variable. The second argument becomes the value or binding of the first, in whatever environment the "set!" occurred in.
In the top-level environment, "define" may also be used to give new values or bindings to identifiers; however, in other environments, only "set!" has this capability.
Returned Value:
#t
For Example:
;; Suppose that "a" has never had a value or binding. (set! a 42) ;; ==> <error> ;; No value to change. (define a 23) ;; ==> a a ;; ==> 23 (set! a 42) ;; ==> #t a ;; ==> 42
Type:
Procedure.
Operation:
Change the car of a pair to a new value.
Arguments:
Two: The first, a pair; the second, any Scheme object, to become the new car.
Side Effects:
Changes the pair.
Returned Value:
#t
For Example:
(define a (cons 1 2)) ;; ==> a a ;; ==> (1 . 2) (set-car! a 42) ;; ==> #t a ;; ==> (42 . 2)
Type:
Procedure.
Operation:
Change the cdr of a pair to a new value.
Arguments:
Two: the first, a pair; the second, any Scheme object, to become the new cdr.
Side Effects:
Changes the pair.
Returned Value:
#t
For Example:
(define a (cons 1 2)) ;; ==> a a ;; ==> (1 . 2) (set-cdr! a 42) ;; ==> #t a ;; ==> (1 . 42)
Type:
Procedure.
Operation:
Mathematical sine.
Arguments:
One number, taken to be an angle in radians.
Side Effects:
None.
Returned Value:
The sine of the argument.
For Example:
(sin 0) ;; ==> 0 (sin 1.5707963267948966) ;; ==> 1. (sin 0.7853981633974483) ;; ==> 0.7071067811865475
Type:
Procedure.
Operation:
Mathematical square root.
Arguments:
One nonnegative number.
Side Effects:
None.
Returned Value:
The square root of the argument.
For Example:
(sqrt 0) ;; ==> 0 (sqrt 2.5) ;; ==> 1.5811388300841898 (sqrt 4) ;; ==> 2
Type:
Procedure.
Operation:
Make a list of the characters in a string.
Arguments:
One string.
Side Effects:
None.
Returned Value:
A list: Returns a list of the characters in the argument, in order.
For Example:
(string->list "Cat") ;; ==> (#\C #\a #\t)
Type:
Procedure.
Operation:
Read the contents of a string as a number in a particular radix.
Arguments:
One or two: The first, the string to be read, the second an exact integer, either 2, 8, 10 or 16, corresponding to the radix in which the number is to be represented. If there is no second argument, the radix is taken to be 10. of the
Side Effects:
None.
Returned Value:
A number: Returns a number whose external representation in the given base is the given string.
For Example:
(string->number "123") ;; ==> 123 (string->number "1001" 2) ;; ==> 9 (string->number "1001" 8) ;; ==> 513 (string->number "1001" 10) ;; ==> 1001 (string->number "1001") ;; ==> 1001 (string->number "1001" 16) ;; ==> 4097 (string->number "-#i123###.e23") ;; ==> -1.2300000000000001e28
Type:
Procedure.
Operation:
Create a Scheme identifier from the letters of the argument.
Arguments:
One string.
Side Effects:
None.
Returned Value:
A symbol: Returns a Scheme identifier whose characters are the same as those in the given string, in the same order.
For Example:
(string->symbol "Cat") ;; ==> Cat ;; Note the capitalization.
Type:
Procedure.
Operation:
Concatenate strings.
Arguments:
One or more strings.
Side Effects:
None.
Returned Value:
A string: Returns a string whose characters are the characters of the arguments, in order.
For Example:
(string-append "I " "see " "the " "cat.") ;; ==> "I see the cat."
Type:
Procedure.
Operation:
Convert two strings to lower case and test for lexicographic less than or equal to.
Lexicographic comparison compares strings character-by-character and defines their ordering based on the ASCII integers that represent the first characters at which they differ, if any. If one string ends before a difference occurs, the longer string is taken to be greater. If both strings end with no difference, the strings are taken to be equal.
Arguments:
Two strings.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the first string is lexicographically less than or equal to the second. Otherwise, returns #f.
For Example:
(string-ci<=? "aa" "aardvark") ;; ==> #t (string-ci<=? "Aa" "aardvark") ;; ==> #t (string-ci<=? "aa" "Aardvark") ;; ==> #t (string-ci<=? "aa" "pahoehoe") ;; ==> #t (string-ci<=? "pahoehoe" "aa") ;; ==> #f (string-ci<=? "aardvark" "aardvark") ;; ==> #t
Type:
Procedure.
Operation:
Convert two strings to lower case and test for lexicographic less than.
Lexicographic comparison compares strings character-by-character and defines their ordering based on the ASCII integers that represent the first characters at which they differ, if any. If one string ends before a difference occurs, the longer string is taken to be greater. If both strings end with no difference, the strings are taken to be equal.
Arguments:
Two strings.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the first string is lexicographically less than the second. Otherwise, returns #f.
For Example:
(string-ci<? "aa" "aardvark") ;; ==> #t (string-ci<? "Aa" "aardvark") ;; ==> #t (string-ci<? "aa" "Aardvark") ;; ==> #t (string-ci<? "aa" "pahoehoe") ;; ==> #t (string-ci<? "pahoehoe" "aa") ;; ==> #f (string-ci<? "aardvark" "aardvark") ;; ==> #f
Type:
Procedure.
Operation:
Convert two strings to lower case and test for lexicographic equality.
Lexicographic comparison compares strings character-by-character and defines their ordering based on the ASCII integers that represent the first characters at which they differ, if any. If one string ends before a difference occurs, the longer string is taken to be greater. If both strings end with no difference, the strings are taken to be equal.
Arguments:
Two strings.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the first string is lexicographically equality the second. Otherwise, returns #f.
For Example:
(string-ci=? "aa" "aardvark") ;; ==> #f (string-ci=? "Aa" "aardvark") ;; ==> #f (string-ci=? "aa" "Aardvark") ;; ==> #f (string-ci=? "aa" "pahoehoe") ;; ==> #f (string-ci=? "aardvark" "aardvark") ;; ==> #t (string-ci=? "aardvark" "AARDVARK") ;; ==> #t
Type:
Procedure.
Operation:
Convert two strings to lower case and test for lexicographic greater than or equal to.
Lexicographic comparison compares strings character-by-character and defines their ordering based on the ASCII integers that represent the first characters at which they differ, if any. If one string ends before a difference occurs, the longer string is taken to be greater. If both strings end with no difference, the strings are taken to be equal.
Arguments:
Two strings.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the first string is lexicographically greater than or equal to the second. Otherwise, returns #f.
For Example:
(string-ci>=? "aa" "aardvark") ;; ==> #f (string-ci>=? "Aa" "aardvark") ;; ==> #f (string-ci>=? "aa" "Aardvark") ;; ==> #f (string-ci>=? "aa" "pahoehoe") ;; ==> #f (string-ci>=? "pahoehoe" "aa") ;; ==> #t (string-ci>=? "aardvark" "aardvark") ;; ==> #t
Type:
Procedure.
Operation:
Convert two strings to lower case and test for lexicographic greater than.
Lexicographic comparison compares strings character-by-character and defines their ordering based on the ASCII integers that represent the first characters at which they differ, if any. If one string ends before a difference occurs, the longer string is taken to be greater. If both strings end with no difference, the strings are taken to be equal.
Arguments:
Two strings.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the first string is lexicographically greater than the second. Otherwise, returns #f.
For Example:
(string-ci>? "aa" "aardvark") ;; ==> #f (string-ci>? "Aa" "aardvark") ;; ==> #f (string-ci>? "aa" "Aardvark") ;; ==> #f (string-ci>? "aa" "pahoehoe") ;; ==> #f (string-ci>? "pahoehoe" "aa") ;; ==> #t (string-ci>? "aardvark" "aardvark") ;; ==> #f
Type:
Procedure.
Operation:
Copy a string.
Arguments:
One string.
Side Effects:
None.
Returned Value:
A string: Returns a newly-allocated copy of the argument.
For Example:
(string-copy "Cat") ;; ==> "Cat"
Type:
Procedure.
Operation:
Fill a string with a given character.
Arguments:
Two: The first a string, the second the character to fill with.
Side Effects:
Alters the string.
Returned Value:
#t
For Example:
(define a (make-string 2)) ;; ==> a a ;; ==> " " (string-fill! a #\x) ;; ==> #t a ;; ==> "xx"
Type:
Procedure.
Operation:
Determine the length of a string.
Arguments:
One string.
Side Effects:
None.
Returned Value:
An integer: Returns the number of characters in the argument.
For Example:
(string-length "Cat") ;; ==> 3
Type:
Procedure.
Operation:
Get a specific character from a string.
Arguments:
Two: The first a string, the second a nonnegative integer, taken as the zero-based index of the character to return.
Side Effects:
None.
Returned Value:
A character: Returns the first argument's character that was at position N from the start of the string, N being the second argument. A value of zero for N returns the first character in the string.
For Example:
(string-ref "Cat" 0) ;; ==> #\C (string-ref "Cat" 1) ;; ==> #\a (string-ref "Cat" 2) ;; ==> #\t
Type:
Procedure.
Operation:
Set one character in a string to a new value.
Arguments:
Three: The first a string, the second a nonnegative integer, taken as the zero-based index of the character to change, the third the new character.
Side Effects:
Changes the string.
Returned Value:
#t
For Example:
(define a (make-string 3)) ;; ==> a a ;; ==> " " (string-set! a 0 #\C) ;; ==> #t a ;; ==> "C " (string-set! a 1 #\a) ;; ==> #t a ;; ==> "Ca " (string-set! a 2 #\t) ;; ==> #t a ;; ==> "Cat"
Type:
Procedure.
Operation:
Test two strings for lexicographic less than or equal to.
Lexicographic comparison compares strings character-by-character and defines their ordering based on the ASCII integers that represent the first characters at which they differ, if any. If one string ends before a difference occurs, the longer string is taken to be greater. If both strings end with no difference, the strings are taken to be equal.
Arguments:
Two strings.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the first string is lexicographically less than or equal to the second. Otherwise, returns #f.
For Example:
(string<=? "aa" "aardvark") ;; ==> #t (string<=? "Aa" "aardvark") ;; ==> #t (string<=? "aa" "Aardvark") ;; ==> #f (string<=? "aa" "pahoehoe") ;; ==> #t (string<=? "aardvark" "aardvark") ;; ==> #t
Type:
Procedure.
Operation:
Test two strings for lexicographic less than.
Lexicographic comparison compares strings character-by-character and defines their ordering based on the ASCII integers that represent the first characters at which they differ, if any. If one string ends before a difference occurs, the longer string is taken to be greater. If both strings end with no difference, the strings are taken to be equal.
Arguments:
Two strings.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the first string is lexicographically less than the second. Otherwise, returns #f.
For Example:
(string<? "aa" "aardvark") ;; ==> #t (string<? "Aa" "aardvark") ;; ==> #t (string<? "aa" "Aardvark") ;; ==> #f (string<? "aa" "pahoehoe") ;; ==> #t (string<? "aardvark" "aardvark") ;; ==> #f
Type:
Procedure.
Operation:
Test two strings for lexicographic equality.
Lexicographic comparison compares strings character-by-character and defines their ordering based on the ASCII integers that represent the first characters at which they differ, if any. If one string ends before a difference occurs, the longer string is taken to be greater. If both strings end with no difference, the strings are taken to be equal.
Arguments:
Two strings.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the first string is lexicographically equality the second. Otherwise, returns #f.
For Example:
(string=? "aa" "aardvark") ;; ==> #f (string=? "Aa" "aardvark") ;; ==> #f (string=? "aa" "Aardvark") ;; ==> #f (string=? "aa" "pahoehoe") ;; ==> #f (string=? "aardvark" "aardvark") ;; ==> #t (string=? "aardvark" "AARDVARK") ;; ==> #f
Type:
Procedure.
Operation:
Test two strings for lexicographic greater than or equal to.
Lexicographic comparison compares strings character-by-character and defines their ordering based on the ASCII integers that represent the first characters at which they differ, if any. If one string ends before a difference occurs, the longer string is taken to be greater. If both strings end with no difference, the strings are taken to be equal.
Arguments:
Two strings.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the first string is lexicographically greater than or equal to the second. Otherwise, returns #f.
For Example:
(string>=? "aa" "aardvark") ;; ==> #f (string>=? "Aa" "aardvark") ;; ==> #f (string>=? "aa" "Aardvark") ;; ==> #t (string>=? "aa" "pahoehoe") ;; ==> #f (string>=? "pahoehoe" "aa") ;; ==> #t (string>=? "aardvark" "aardvark") ;; ==> #t
Type:
Procedure.
Operation:
Test two strings for lexicographic greater than.
Lexicographic comparison compares strings character-by-character and defines their ordering based on the ASCII integers that represent the first characters at which they differ, if any. If one string ends before a difference occurs, the longer string is taken to be greater. If both strings end with no difference, the strings are taken to be equal.
Arguments:
Two strings.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the first string is lexicographically greater than the second. Otherwise, returns #f.
For Example:
(string>? "aa" "aardvark") ;; ==> #f (string>? "Aa" "aardvark") ;; ==> #f (string>? "aa" "Aardvark") ;; ==> #t (string>? "aa" "pahoehoe") ;; ==> #f (string>? "pahoehoe" "aa") ;; ==> #t (string>? "aardvark" "aardvark") ;; ==> #f
Type:
Procedure.
Operation:
Test whether a Scheme object is a string.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a string. Otherwise, returns #f.
For Example:
(string? #t) ;; ==> #f (string? 'Cat) ;; ==> #f (string? "Cat") ;; ==> #t
Type:
Procedure.
Operation:
Make a copy of part of a given string.
Arguments:
Three: The first a string, the second and third integers, respectively taken to be the zero-based indexes into the given string to the position of the first character of the intended substring, and to the position just past the last character of the intended substring. If the second and third arguments are equal, the substring indicated has zero length, and contains no characters.
Side Effects:
None.
Returned Value:
A string: Returns a newly-allocated copy of the substring described in the "Arguments" section above.
For Example:
(substring "Cat" 0 0) ;; ==> "" (substring "The cat sees me." 4 7) ;; ==> "cat"
Type:
Procedure.
Operation:
Make a string containing the letters of a given symbol.
Arguments:
One symbol.
Side Effects:
None.
Returned Value:
A string: Returns a string with the same characters as the argument, in the same order.
For Example:
(symbol->string 'foo) ;; ==> "foo"
Type:
Procedure.
Operation:
Test whether a Scheme object is a symbol.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a symbol. Otherwise, returns #f.
For Example:
(symbol? #t) ;; ==> #f (symbol? "foo") ;; ==> #f (symbol? 'foo) ;; ==> #t
Type:
Operation:
Primitive for construction of hygienic macros.
Arguments:
The form of a macro call of "syntax-rules" should match the grammar for <transformer spec> given in section 4.3.2 of the "R5" report.
Side Effects:
None.
Returned Value:
A procedure, suitable for use as the transformer of an hygienic macro.
For Example:
Strictly, there are no examples: The formal definition of Scheme mentions "syntax-rules" only in the context of the syntax required for the standard implementation of hygienic macros. There is no specification of what sort of entity "syntax-rules" should be, or even of whether or not there should be a Scheme object associated with that identifier. There is also no specification of what behavior should obtain if "syntax-rules" is used in some other context, such as
(syntax-rules foo bar baz)
I mention "syntax-rules" here only because its use in the "R5" report resembles the use of a procedure or special form: You might like to know what happens if you try to use it that way. The answer is, that if the call to "syntax-rules" matches the grammar for <transformer spec> given in section 4.3.2 of the "R5" report, you will get a procedure suitable for use as the transformer of an hygienic macro. If not, you will probably get some form of error message. For example, noting that hex values may vary:
(syntax-rules foo bar baz) ;; ==> 00000003-15d458ac: Symbol -- Not a Car Problem: Implementation: Tried to take the car of a non-pair. Last lambda called (which may have returned) has never been named. Recent names of non-tail-recursive stacked lambda expressions: c::if-code c::let-code () (Resetting) Top-level loop ...
The reason for this behavior is an implementation detail of Wraith Scheme: In Wraith Scheme, "syntax-rules" itself does not do any tests to make sure that it is being called with the correct grammar. All appropriate syntax checking is done by forms "define-syntax", "let-syntax", and "letrec-syntax", which use the symbol "syntax-rules" as part of their implementation. Thus in:
(syntax-rules foo bar baz)
the macro call is obviously not a <transformer spec>, and the error message noted occurs when the macro "syntax-rules" stumbles because of that failing. On the other hand, when Wraith Scheme encounters the form:
(define-syntax foo (syntax-rules foo bar baz))
it produces a more useful error report:
(define-syntax foo (syntax-rules foo bar baz)) "syntax-rules" used as shown, but the second argument is not a transformer specification. The problems include: Problem: The second item in that argument is not a list of identifiers. (Resetting) Top-level loop ...
If you wish to experiment with "syntax-rules" all by itself, go ahead, but beware of mysterious failures and puzzling error messages when you use it in any other context than an instance of "define-syntax", "let-syntax", or "letrec-syntax".
Type:
Procedure.
Operation:
Mathematical tangent.
Arguments:
One number, taken as an angle in radians.
Side Effects:
None.
Returned Value:
The tangent of the argument.
For Example:
(tan 0) ;; ==> 0 (tan 1.5707963267948966) ;; ==> 16331778728383844 (tan 3) ;; ==> -0.1425465430742778
Type:
Procedure.
Operation:
If a transcript file is in use, stop using it and close the port to the file. If no transcript is in use, "transcript-off" does nothing.
Arguments:
None.
Side Effects:
Closes any open transcript file.
Returned Value:
#t
For Example:
(transcript-off) ;; ==> #t
Type:
Procedure.
Operation:
Open a transcript file and start using it.
Wraith Scheme allows only one transcript file to be open at a time. If a transcript file is already in use when "transcript-on" is called, Wraith Scheme will close the old transcript file before starting to use the new one.
Transcript files record everything that appeared in the Wraith Scheme Main Display Panel while the transcript file was in use, whether keyed in by the user or output by Wraith Scheme.
Arguments:
At most one: If present, a string containing a Unix-style pathname to a file to be used as a transcript file. If there is no argument, Wraith Scheme will use the Wraith Scheme Dialog Panel to obtain a pathname.
Side Effects:
Opens a new transcript file, and closes any transcript file that was already in use.
Returned Value:
#t
For Example:
(transcript-on "MyTranscript.text") ;; Opens the file ;; ==> #t (transcript-on) ;; Wraith Scheme uses the Dialog Panel ;; ==> #t
Type:
Procedure.
Operation:
Arithmetic truncation toward zero.
Arguments:
One number.
Side Effects:
None.
Returned Value:
An integer: The integer closest to the argument whose absolute value is not larger than the absolute value of the argument.
For Example:
(truncate 1) ;; ==> 1 (truncate 1.00001) ;; ==> 1. (truncate 1.9999) ;; ==> 1. (truncate 0.9999) ;; ==> 0. (truncate -1) ;; ==> -1 (truncate -1.00001) ;; ==> -1. (truncate -1.9999) ;; ==> -1. (truncate -0.9999) ;; ==> 0.
Additional Syntax:
Comma: ,<whatever> is equivalent to (unquote <whatever>).
Type:
Operation:
Reduce the level of nesting by one within a quasiquoted expression, (quasiquote <whatever>). When that level is zero, the evaluation that was inhibited by "quasiquote" resumes, and the argument of "unquote" is inserted into <whatever>.
The macros "quasiquote", "unquote" and "unquote-splicing" may be nested within <whatever>: Starting with a nesting level of zero at the the left end of <whatever>, each "quasiquote" increases the nesting level by one, and each "unquote" or "unquote-splicing" reduces it by one, and normal evaluation occurs only when the nesting level thus determined is zero.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A Scheme object: Returns the argument, either evaluated or not, according to whether the nesting level, defined in the "Operation" section above, is zero or not. In either case the returned value is spliced into the enclosing quasiquoted expression.
For Example:
(define foo "A string named foo") ;; ==> foo (quasiquote foo) ;; ==> foo `foo ;; ==> foo (quasiquote ,foo) ;; ==> "A string named foo." `,foo ;; ==> "A string named foo." (define a 42) ;; ==> a (quasiquote (+ 2 a)) ;; ==> (+ 2 a) `(+ 2 a) ;; ==> (+ 2 a) `(+ 2 ,a) ;; ==> (+ 2 42) (define b (list 27 18 28)) ;; ==> b `(+ 2 b) ;; ==> (+ 2 b) `(+ 2 ,b) ;; ==> (+ 2 (27 18 28)) ;; Doesn't add up .... `(+ 2 ,@b) ;; ==> (+ 2 27 18 2)
Additional Syntax:
Comma and at-sign: ,@<whatever> is equivalent to (unquote-spicing <whatever>).
Type:
Operation:
Reduce the level of nesting by one within a quasiquoted expression, (quasiquote <whatever>). When that level is zero, the evaluation that was inhibited by "quasiquote" resumes, and the elements of the argument of "unquote-splicing" -- which is a list -- are spliced into <whatever>.
The macros "quasiquote", "unquote" and "unquote-splicing" may be nested within <whatever>: Starting with a nesting level of zero at the the left end of <whatever>, each "quasiquote" increases the nesting level by one, and each "unquote" or "unquote-splicing" reduces it by one, and normal evaluation occurs only when the nesting level thus determined is zero.
Arguments:
One proper list.
Side Effects:
None.
Returned Value:
One or more Scheme objects: If the nesting level, defined in the "Operation" section above, is zero, returns the elements of the argument; if not, returns the argument, which in either case is spliced into the enclosing quasiquoted expression.
For Example:
(define foo "A string named foo") ;; ==> foo (quasiquote foo) ;; ==> foo `foo ;; ==> foo (quasiquote ,foo) ;; ==> "A string named foo." `,foo ;; ==> "A string named foo." (define a 42) ;; ==> a (quasiquote (+ 2 a)) ;; ==> (+ 2 a) `(+ 2 a) ;; ==> (+ 2 a) `(+ 2 ,a) ;; ==> (+ 2 42) (define b (list 27 18 28)) ;; ==> b `(+ 2 b) ;; ==> (+ 2 b) `(+ 2 ,b) ;; ==> (+ 2 (27 18 28)) ;; Doesn't add up .... `(+ 2 ,@b) ;; ==> (+ 2 27 18 2)
Type:
Procedure.
Operation:
In the abstract sense, "values" modifies the continuation (in the first sense discussed herein) when it is called, so that the continuation is set up to deliver multiple values to a Scheme procedure -- the values being those provided as arguments to "values" itself, in the order given. Such a continuation is only useful when the next thing following those values is a procedure call which can accept those values as its arguments.
In practical terms, "values" provides a mechanism for returning multiple values from a procedure. Although it is technically a procedure in its own right, it is perhaps most useful to think of it as a special syntactic form, used at the end of a procedure, to return values. In that sense, "values" is analogous to the "return" statement in the C programming language, except that C's "return" can return only one value, whereas "values" can return many.
Arguments:
One or more Scheme objects.
Side Effects:
None.
Returned Value:
A "Multiple Values Return" object, which can only be interpreted in the continuation established by "call-with-values". Other Scheme implementations likely handle the return from "values" differently.
For Example:
;; Here is a fancy way to add up the integers ;; from one through ten: This example passes ;; the list returned by "values" to "+", just ;; as if you had entered ;; ;; (+ 1 2 3 4 5 6 7 8 9 10) (call-with-values (lambda () (values 1 2 3 4 5 6 7 8 9 10)) +) ;; ==> 55 ;; We could equally well just list the numbers: (call-with-values (lambda () (values 1 2 3 4 5 6 7 8 9 10)) list) ;; ==> (1 2 3 4 5 6 7 8 9 10) ;; In the top-level loop: (values 1 2 3 4 5 6 7 8 9 10) ;; ==> #<Multiple Values Return>
Type:
Procedure.
Operation:
Test whether a Scheme object is a vector.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a vector. Otherwise, returns #f.
For Example:
(vector? #t) ;; ==> #f (vector? (make-vector 42)) ;; ==> #t (vector? '#(1 2 3)) ;; ==> #t
Type:
Procedure.
Operation:
Make a list of the elements in a vector.
Arguments:
One vector.
Side Effects:
None.
Returned Value:
A list: Returns a newly-allocated list whose elements are the elements of the argument, in the same order.
For Example:
(define a (make-vector 3)) ;; ==> a a ;; ==> #(() () ()) (define b (vector->list a)) ;; ==> b b ;; ==> (() () ()) (vector-set! a 2 4) ;; ==> #t a ;; ==> #(() () 4) b ;; ==> (() () ()) ;; b does not share memory with a. (vector->list a) ;; ==> (() () 4) ;; New copy of a.
Type:
Procedure.
Operation:
Fill every element of a vector with the same Scheme object.
Arguments:
Two: The first a vector to be filled, the second a Scheme object to fill it with.
Side Effects:
Modifies the first argument.
Returned Value:
#t
For Example:
(define cat (make-vector 3)) ;; ==> cat (vector-fill! cat 'meow) ;; ==> #t cat ;; ==> #(meow meow meow)
Type:
Procedure.
Operation:
Obtain the length of a vector.
Arguments:
One vector.
Side Effects:
None.
Returned Value:
An integer: Returns the length of the argument.
For Example:
(vector-length '#()) ;; ==> 0 (vector-length '#(meow meow meow)) ;; ==> 3
Type:
Procedure.
Operation:
Obtain a specified element of a vector.
Arguments:
Two: The first a vector, the second a non-negative integer, taken to be the zero-based index of the argument requested.
Side Effects:
None.
Returned Value:
A Scheme object: Returns the element of the first argument that is at the zero-based index which is the second argument.
For Example:
(vector-ref '#(c a t) 0) ;; ==> #\c (vector-ref '#(c a t) 1) ;; ==> #\a (vector-ref '#(c a t) 2) ;; ==> #\t
Type:
Procedure.
Operation:
Set one element of a vector to a new value.
Arguments:
Three: The first a vector, the second a nonnegative integer, taken as the zero-based index of the element to change, the third the new element.
Side Effects:
Changes the vector.
Returned Value:
#t
For Example:
(define a (make-vector 3)) ;; ==> a a ;; ==> #(() () ()) (vector-set! a 0 'c) ;; ==> #t a ;; ==> #(c () ()) (vector-set! a 1 'a) ;; ==> #t a ;; ==> #(c a ()) (vector-set! a 2 't) ;; ==> #t a ;; ==> #(c a t)
Type:
Procedure.
Operation:
Test whether a Scheme object is a vector.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a vector. Otherwise, returns #f.
For Example:
(vector? #t) ;; ==> #f (vector? (make-vector 3)) ;; ==> #t (vector? (list->vector (list 1 2 3))) ;; ==> #t
Type:
Procedure.
Operation:
Temporarily change the current input port to a port to a file, and do something while the change is in effect.
Arguments:
One or two: The last a procedure of no arguments, to be called while the changed current input port is in effect. If there are two arguments, the first is a string containing a Unix-style pathname to a file: Wraith Scheme will open an input port to this file and make that port the current input port while the procedure is run. If there is only one argument, Wraith Scheme will use the Wraith Scheme Dialog Panel to obtain a path to the file to be used.
Side Effects:
Temporarily changes the current input port, plus whatever side effects result from the call to the given procedure.
Returned Value:
#t
For Example:
;; Suppose "Foo" is a file containing the text "abc". (with-input-from-file "Foo" (lambda () (display (read-char)) (newline) (display (read-char)) (newline) (display (read-char)) (newline))) ;; ==> a b c #t
Type:
Procedure.
Operation:
Temporarily change the current output port to a port to a file, and do something while the change is in effect.
Arguments:
One or two: The last a procedure of no arguments, to be called while the changed current output port is in effect. If there are two arguments, the first is a string containing a Unix-style pathname to a file: Wraith Scheme will open an output port to this file and make that port the current output port while the procedure is run. If there is only one argument, Wraith Scheme will use the Wraith Scheme Dialog Panel to obtain a path to the file to be used.
Side Effects:
None.
Returned Value:
Temporarily changes the current output port, plus whatever side effects result from the call to the given procedure.
For Example:
(with-output-to-file "Foo" (lambda () (write-char #\a (newline) (write-char #\b (newline) (write-char #\c (newline))) ;; ==> ;; Writes the text ;; "abc" to file "Foo". #t
Type:
Procedure.
Operation:
Write a Scheme object to a port.
Arguments:
One or two: The first, a Scheme object to be written; the second, if present, a port to write to. If there is no second argument, the object will be written to the current output port.
Side Effects:
Writes something, somewhere.
Returned Value:
#t
For Example:
;; Suppose that "my-port" is an output port associated with ;; file "MyFile.s". (write (list 1 2 3) my-port) ;; Writes (1 2 3) ;; to "MyFile.s". ;; ==> #t
Type:
Procedure.
Operation:
Write a character to a port.
Arguments:
One or two: The first, a character to be written; the second, if present, a port to write to. If there is no second argument, the character will be written to the current output port.
Side Effects:
Writes a character somewhere.
Returned Value:
#t
For Example:
(with-output-to-file "Foo" (lambda () (write-char #\a) (write-char #\b) (write-char #\c))) ;; ==> ;; Writes the text ;; "abc" to file "Foo". #t
Type:
Procedure.
Operation:
Test whether a number is zero.
Arguments:
One number.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is zero; the test is done using the Scheme predicate "=". Otherwise, returns #f.
For Example:
(zero? 1) ;; ==> #f (zero 0) ;; ==> #t (zero #i0) ;; ==> #t
Type:
Procedure. (All of them.)
Operation:
These enhancements provide traditional bitwise boolean and shift operations for integers which can be stored as 32-bit fixnums; that is, integers in the range [-2147483648 .. 2147483647].
Rationale, Explanation, Excuses:
Arguments:
"e::bit-and", "e::bit-or" and "e::bit-xor": Two integers in the range that can be stored as 32-bit fixnums. "e::bit-not": One integer in the range that can be stored as 32-bit fixnums. "e::bit-shift-left", "e::bit-shift-right-arithmetic" and "e::bit-shift-right-logical": Two integers, the first in the range that can be stored as 32-bit fixnums and the second nonnegative.
Side Effects:
None.
Returned Value:
An integer stored as a 32-bit fixnum. "e::bit-and", "e::bit-or" and "e::bit-xor" return respectively the bitwise logical and, or, and xor of their arguments. "e::bit-not" returns the bitwise logical negation of its argument. The shift operators return their first argument shifted a number of bits equal to the second argument, in the direction indicated. "e::bit-shift-left" and "e::bit-shift-right-logical" pad at the shifted-in end with zeros. "e::bit-shift-right-arithmetic" pads with the most significant bit; that is, the sign bit.
For Example:
(e::bit-and #b1011 #b1101) ;; ==> 9 ;; Binary 1001 (e::bit-or #b1011 #b1101) ;; ==> 15 ;; Binary 1111 (e::bit-xor #b1011 #b1101) ;; ==> 6 ;; Binary 0110 (e::bit-not #b1011) ;; ==> -12 ;; Binary 11111111111111111111111111110100 (e::bit-shift-left #b1011 3) ;; ==> 88 ;; Binary 1011000 (e::bit-shift-right-logical -1 16) ;; ==> 32767 ;; Binary 111111111111111 (e::bit-shift-right-arithmetic -1 16) ;; ==> -1 ;; -1 shifted right and padded with 1's ;; is still -1
Type:
Procedure.
Operation:
Block read and write access to the value of a bound Wraith Scheme symbol, except via c::set-blocked-binding!, which see.
This procedure is one of four that are particularly useful in dealing with critical sections that involve Wraith Scheme objects, notably symbols. The four procedures in question are
These procedures should be used with great caution: They are individually and collectively calamitous, for several reasons.
Technical Note: The problem indicated is a deadlock due to an attempt to access a locked object.
Rationale, Explanation, Excuses:
Useful low-level primitive for parallel programming.
Arguments:
One symbol.
Side Effects:
Blocks read and write access to the value of its argument, except via c::set-blocked-binding!, which see.
Returned Value:
A list of two items. The first is the value bound to the symbol immediately after the lock was applied. (Since access to that binding is now locked, there is no other way to obtain that value.) The second is a locked object suitable both for the first argument to a call to "c::set-blocked-binding!" (to change the bound value), and for the argument to "c::release-block" (to release the lock).
For Example:
(define a 0) (define (blocked-increment-of-a) (let* ((the-block-list (e::block-symbol-binding 'a)) (the-value (car the-block-list)) (the-lock (cadr the-block-list)) ) (c::set-blocked-binding! the-lock (+ the-value 1)) (c::release-block the-lock)))
You might note in passing that the call to "e::blocked-symbol-binding" is of the form
(e::block-symbol-binding 'a) ;; With quotenot
(e::block-symbol-binding a) ;; No quote
Type:
Procedure.
Operation:
Test whether a symbol has a value or binding in any environment in the lexical scope of where "e::bound-instance?" was called.
Rationale, Explanation, Excuses:
Many Lisp systems would call this procedure "boundp" or "bound?". It can be useful when investigating Scheme memory, or when one needs to make sure that a haphazardly chosen symbol has no value or binding.
Arguments:
One symbol.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument has a value or binding in the current lexical scope. Otherwise, returns #f.
For Example:
(e::bound-instance '+) ;; ==> #t (e::bound-instance 'cons) ;; ==> #t (define a 3) ;; ==> a (e::bound-instance? 'a) ;; ==> #t (e::bound-instance 'xglerb) ;; ==> #f ;; Unless you have ;; defined xglerb.
Type:
Procedure.
Operation:
Clear the internal flag that tell Wraith Scheme to compile defines automatically.
Rationale, Explanation, Excuses:
Provides Scheme-program control of an important internal flag.
Arguments:
None.
Side Effects:
Turns off automatic compilation.
Returned Value:
#t
For Example:
(e::clear-compiler-on!) ;; ==> #t
Type:
Procedure.
Operation:
Rationale, Explanation, Excuses:
To make it difficult inadvertently to redefine fundamental Scheme procedures like "+" and "cons", I provide symbols with a "permanent" flag. When set, any attempt to change the value or binding of the given symbol causes Wraith Scheme to report an error. "e::clear-permanent!" clears this flag, so you can, for example, redefine "cons", if you really, really, want to, "e::set-permanent!" sets it, so you can't, and "e::permanent?" tests whether it is set or not.
On your head be it.
You may of course use "e::clear-permanent" and its companion, "e::set-permanent!", for new variables that you yourself create.
Arguments:
One symbol.
Side Effects:
Makes it possible to change what the value or binding of the argument.
Returned Value:
#t
For Example:
(e::clear-permanent! 'cons) ;; ==> #t ;; DANGER WILL ROBINSON
Type:
Procedure.
Operation:
Clear the internal flag that tell Wraith Scheme to display numbers with the full precision available.
Rationale, Explanation, Excuses:
Provides Scheme-program control of an important internal flag.
Arguments:
None.
Side Effects:
Causes Wraith Scheme's numeric display routines to use reduced precision.
Returned Value:
#t
For Example:
(e::clear-show-full-precision!) ;; ==> #t
Type:
Procedure.
Operation:
Test whether a port is closed.
Rationale, Explanation, Excuses:
The entities that Wraith Scheme uses for ports persist even after they have been closed; they are in fact reused. "Open" and "closed" are elements of port state. Thus it makes sense to have a procedure to test whether a port is open or closed.
Arguments:
One port -- either an input port or an output port will do.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is closed. Otherwise, returns #f.
For Example:
(define foo (open-output-file "Whatever")) ;; ==> foo (e::closed-port? foo) ;; ==> #f (close-output-port foo) ;; ==> #t (e::closed-port? foo) ;; ==> #t
Type:
Procedure.
Operation:
Return the value of the internal flag that controls whether Wraith Scheme compiles defines automatically.
Rationale, Explanation, Excuses:
Allow Scheme programs to examine important internal state of the Wraith Scheme interpreter.
Arguments:
None.
Side Effects:
None.
Returned Value:
A boolean: Returns the (boolean) flag that controls whether Wraith Scheme compiles defines automatically. That flag is true if, and only if, defines are automatically compiled.
For Example:
(e::set-compiler-on!) ;; ==> #t (e::compiler-on?) ;; ==> #t (e::clear-compiler-on!) ;; ==> #t (e::compiler-on?) ;; ==> #f
Type:
Procedure.
Operation:
Invoke the Wraith Scheme compiler on a Scheme object.
Rationale, Explanation, Excuses:
Wraith Scheme has a rather minimal compiler built in; this is how you use it. Actually, it is perhaps better used by setting the "Compile Defines" flag from the Interpreter Menu, but this procedure allows you to compile individual objects.
The compiler only compiles lambda expressions.
The top-level loop will print out #<Interpreted lambda expression> when it returns from "e::compile-form", but if you use "e::inspect" on what it returns you will see that variable references have been replaced by references to specific locations in the environment; the form is being interpreted, but much of the work in interpreting an uncompiled form -- looking up the values or bindings of symbols -- will now be side-stepped.
Arguments:
One Scheme object; preferably, a lambda expression.
Side Effects:
Compiles the lambda expression.
Returned Value:
A Scheme object.
For Example:
;; With the "Compile Defines" menu item disabled: (define (increment x) (+ x 1)) ;; ==> increment (e::inspect increment) ;; ==> ;; The hex numbers will vary 0004-1b8484cc: Lambda Pair -- Not a Car (lambda (x) (+ x 1)) Lambda's non-top-level environments are: ... -------- End of Environment List -------- #<Interpreted lambda expression> ;; Now compile it, and inspect again: (define increment (e::compile-form increment)) ;; ==> increment (e::inspect increment) ;; ==> ;; The hex numbers will vary 0004-1b8417c4: Lambda Pair -- Not a Car (lambda (x) (#<Built-in procedure "+"> #<Ref to var 0 in environment 0 down> 1)) Lambda's non-top-level environments are: ... -------- End of Environment List -------- #<Interpreted lambda expression>
Type:
Procedure.
Operation:
Cons the argument with the Wraith Scheme continuation, which will cause it to be evaluated immediately, in the environment in which "e::cons-with-continuation" was called.
Rationale, Explanation, Excuses:
This procedure is what many Lisp interpretations would call "eval". At the time I implemented it, there was much debate in the Scheme community about whether Scheme should have an "eval" procedure at all, and if it did, what that procedure should do. Much of the debate centered around the environment in which the evaluation should take place. I side-stepped the debate by (1) not calling "e::cons-with-continuation" "eval", and (2) choosing a name that made it very clear what environment was in use.
At least, it is clear if you know what a "continuation" is.
Note that
(e::cons-with-continuation <whatever>)
is not equivalent to
(eval <whatever> (interaction-environment))
In Wraith Scheme, the interaction environment is the one encountered when entering Scheme expressions into the top-level loop, but "e::cons-with-continuation" uses the environment in which it was called, which may be the local environment of a lambda expression containing that call.
Note further that because of the renaming of formal parameters of lambda expressions during macro expansion, use of "e::cons-with-continuation" within lambda expressions, with quoted arguments, may give unexpected results, such as:
(let ((x 3)) (e::cons-with-continuation 'x)) ;; ==> <error> x Problem: No lexically visible binding of this symbol.
What is happening is that in Wraith Scheme, "let" is a macro, which in this case expands using a renamed lambda variable, into something like:
((c::lambda (g23008) (e::cons-with-continuation (quote x))) 3)
(The actual name used will vary depending on how many similar substitutions Wraith Scheme has made since it was started.)
Arguments:
One Scheme object.
Side Effects:
Evaluates the argument immediately, in the environment in which "e::cons-with-continuation" is called.
Returned Value:
Any Scheme object. Strictly, e::cons-with-continuation does not return; where you would have expected a return value to appear, what appears is the result of evaluating the argument.
For Example:
(define form-to-be-evaled (list 'begin (list 'display "Hello from the continuation!") (list 'newline))) ;; ==> form-to-be-evaled form-to-be-evaled ;; ==> (begin (display "Hello from the continuation!") (newline)) (e::cons-with-continuation form-to-be-evaled) ;; ==> Hello from the continuation! #t
Type:
Procedure.
Operation:
Find the current directory; the directory from which Unix relative paths begin.
Rationale, Explanation, Excuses: Making effective use of the MacIntosh's Unix file system from Wraith Scheme requires means to set and determine the current directory.
Arguments:
None.
Side Effects:
None.
Returned Value:
A string: Returns a string containing a Unix-style path to the current directory. The returned string will end in a '/'.
For Example:
(e::current-directory) ;; ==> "/" ;; When Wraith Scheme ;; starts from the Dock.
Type:
Procedure.
Operation:
Not built in to Wraith Scheme; to be defined by the user.
Rationale, Explanation, Excuses:
Wraith Scheme has no complicated built-in debugger; proper use of the symbol "e::debug" allows loading run at run-time, or at start-Wraith-Scheme time, or whenever you like.
Fundamentally, a debugging program is no different from any other Scheme program. You should be able to install whatever debugger you like, and -- if you have the source code -- modify it to suit yourself. The catch is, that the Wraith Scheme program needs to be able to call your debugging program when an error occurs, and to do so it needs to know the program's "name". Thus I have provided a special symbol, "e::debug", which the Wraith Scheme program recognizes and uses for that purpose.
When a non-fatal error occurs, the Wraith Scheme error-handling mechanism prints out an error message, then determines whether "e::debug" has been defined. If not, error handling provides some simple trace information -- in effect using a very simple built-in debugger.
Alternatively, If "e::debug" has been defined, Wraith Scheme will call it (and it had better be a procedure accepting one argument), passing as an argument a list of all the environments within the lexical scope of the place where the error occurred, that list being sorted in order of lexical nesting, so that more closely-nested environments occur earlier in the list.
The procedure "e::debug" may do whatever its creator wishes with that information. It might well terminate with a call to "e::reset": A normal return will merely return control to the Wraith Scheme error-handling mechanism, which will then proceed with its simple, built-in trace.
Any value returned by "e::debug" will be ignored.
Arguments:
A list of all the environments in the lexical scope of the call to "e::debug".
Side Effects:
Depends on the definition of "e::debug".
Returned Value:
Undefined.
For Example:
Does not apply.
Type:
Procedure.
Operation:
Return a copy of its argument which is "equal?" to the argument, but in which copied vectors, lists and strings in corresponding positions in the structure are not "eq?".
Rationale, Explanation, Excuses:
I needed this procedure for development of Wraith Scheme, and thought it might be generally useful. The source code for "e::deep-copy" is:
(define (e::deep-copy x) (cond ((pair? x) (cons (e::deep-copy (car x)) (e::deep-copy (cdr x)))) ((vector? x) (list->vector (map e::deep-copy (vector->list x)))) ((string? x) (string-copy x)) (#t x)))
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A Scheme object of the same structure as the argument, and "equal?" to it, but containing newly-allocated structures for lists, vectors and strings, where applicable.
For Example:
(e::deep-copy (list 1 2 3)) ;; ==> (1 2 3)
Type:
Procedure.
Operation:
Automatically skips automatic compilation; even when the "Compile Defines" menu item is set, "(e::define-no-compile foo <bar>)" does not compile <bar>, and binds it to "foo". That is, it does what "(define foo <bar>)" would do if the "Compile Defines" menu item were not set.
Rationale, Explanation, Excuses:
Sometimes it is useful to compile most things but not all, or to exempt some procedures from being compiled.
Arguments:
Two: The first an identifier, the second any Scheme object.
Note that "e::define-no-compile" only accepts the simple, two-argument syntax for "define". It is an error, for example, to attempt
(e::define-no-compile (increment x) (+ x 1))
Side Effects:
Causes the second argument to become the value or binding of the first.
Returned Value:
A symbol: Returns the first argument.
For Example:
(e::define-no-compile increment (lambda (x) (+ x 1))) ;; ==> increment (e::inspect increment) ;; The hexadecimal numbers may differ 0004-1b7bb660: Lambda Pair -- Not a Car (lambda (x) (+ x 1)) ;; No variable substitution -- ;; not compiled. Lambda's non-top-level environments are: ... -------- End of Environment List -------- #<Interpreted lambda expression>
Type:
Procedure.
Operation:
Print an error message and reset to top-level loop.
Rationale, Explanation, Excuses:
Useful primitive for error-handling.
Arguments:
One string.
Side Effects:
Resets Wraith Scheme to the top-level loop.
Returned Value:
Does not return.
For Example:
(e::error "Oops!!") ;; ==> Problem: Oops!! (Resetting) Top-level loop ...
Type:
Procedure.
Operation:
Return the default output port for error messages.
Rationale, Explanation, Excuses:
Wraith Scheme generally handles the output from error messages differently from normal output. For example, even when "current-output-port" returns a port to a file, error messages are usually sent to the console (and thereby also to any transcript file that may be open). "e::error-port" returns the port to which Wraith Scheme's error messages are sent, so that you may make procedures that you create handle errors in the same way.
Arguments:
None.
Side Effects:
None.
Returned Value:
An output port: Returns the current error port, which is typically the console.
For Example:
;; You can write a procedure that displays error messages ;; at the console when normal output is being sent elsewhere. (define (my-procedure) ... (if <disaster> (begin (display "My-procedure is going down in flames!\n" (e::error-port)) (e::reset))) ... ) ;; ==> my-procedure ;; If disaster strikes the message ;; "My-procedure is going down in flames!" ;; will appear in the Wraith Scheme window, ;; even if normal output goes to a file, as in: (with-output-to-file "foo" my-procedure)
Type:
Procedure.
Operation:
Exit the Wraith Scheme program immediately, with no second chances and no confirmation dialog.
When invoked from the MomCat, this procedure also causes all other instances of Wraith Scheme that are running -- that is, all kittens -- to exit. When called from a kitten that is not the MomCat, only that kitten will exit.
Rationale, Explanation, Excuses:
It is sometimes useful to run a Scheme program autonomously -- perhaps from the Unix command line or from a script. A forced exit is useful in such circumstances.
Arguments:
None.
Side Effects:
Quits from the Wraith Scheme program. When called from the MomCat, also causes any kittens present to exit.
Returned Value:
Does not apply.
For Example:
(e::exit) ;; ==> ;; Wraith Scheme exits.
Type:
Procedure.
Operation:
Rationale, Explanation, Excuses:
A "call" or invocation of a Wraith Scheme macro involves using a procedure -- sometimes called a "transformer" -- that was created when the macro was defined, to transform the expression in which the macro call occurred, into something else. That "something else" is evaluated by Wraith Scheme, to produce the result of the macro "call".
"e::expand-macro" does all of these steps except for the last one: It produces the "something else", but does not evaluate it.
For example, in Wraith Scheme, "if" is a macro. When Wraith Scheme encounters an expression like "(if #t 1 2)", Wraith Scheme
e::expand-macro does all of that except for the last step. It returns (c::if #t 1 2) as its result. I installed this procedure primarily for debugging Wraith Scheme's low-level macro implementation.
Arguments:
Side Effects:
None in its own right, but macro expansion may have side effects that depend on the transforming procedure associated with the particular macro.
Returned Value:
A list: Returns the expansion of the macro.
For Example:
(e::expand-macro '(cond (#f 1) (#f 4) (#t 42) (else 'foo))) ;; ==> ;; Formatted for clarity: Note that the expansion of ;; the macro is not recursive -- the returned form ;; contains another instance of the "cond" macro. (c::if #f (begin 1) (cond (#f 4) (#t 42) (else (quote foo))))
Type:
Procedure.
Operation:
Recursively expand all the macros, in a Wraith Scheme expression until none remain, but do not evaluate the expanded form.
Note that this procedure modifies its argument. (Perhaps I should have named it "e::expand-macros-recursively!".) For that reason, an attempt to use "e::expand-macros-recursively" with an argument that is a quoted expression, like
(e::expand-macros-recursively '(cond (#f 1) (#f 4) (#t 42) else 'foo))
will fail, because quoted expressions are supposed to be constants, and are not supposed to be modifiable, and Wraith Scheme is pretty good about catching attempts to do so. Use e::deep-copy, as shown in the example below.
Rationale, Explanation, Excuses:
This procedure is rather an elaboration of "e::expand-macro", immediately above: Whereas "e::expand-macro" only expands the outermost macro in a Scheme expression (and only works if the car of the expression is in fact a macro), "e::expand-macros-recursively" goes through the entire expression, expanding every macro it can find, and doesn't stop until no macros remain.
Like "e::expand-macro", "e::expand-macros-recursively" does not evaluate the fully-expanded expression.
Arguments:
A Scheme expression, presumably containing macros.
Side Effects:
None in its own right, but macro expansion may have side effects that depend on the transforming procedure associated with the particular macro.
Returned Value:
Returns the given Scheme expression with all macros expanded.
For Example:
(e::expand-macros-recursively (e::deep-copy '(cond (#f 1) (#f 4) (#t 42) (else 'foo)))) ;; ==> ;; Formatted for clarity: (c::if #f 1 (c::if #f 4 (c::if #t 42 (quote foo))))
Type:
Procedure.
Operation:
Determine whether Unix-style pathname is a path to a file that can be opened for reading.
Rationale, Explanation, Excuses:
This procedure is useful for working with the Macintosh's Unix-based file system.
The name "e::file-exists?" is a little misleading: Strictly, the procedure returns a boolean indicating whether the Unix command "fopen" was able to open the indicated pathname for reading; the procedure may return #f if the file existed but had Unix permission settings inappropriate for reading by the current user of Wraith Scheme.
Arguments:
One string, presumably containing something that looks like a Unix-style pathname.
Side Effects:
None. Note in particular, that this procedure closes any file that it opens.
Returned Value:
A boolean: Returns #t if, and only if, Unix "fopen" could open the path contained within the argument for reading. Otherwise, returns #f.
For Example:
(e::file-exists? "/") ;; ==> #t (e::file-exists? "No.such.file") ;; ==> #f ;; If there is no such file.
Type:
Procedure.
Operation:
Determine whether a Scheme object is a number stored as a fixnum.
Rationale, Explanation, Excuses:
I installed this procedure to aid in debugging Wraith Scheme's functions that deal with numbers. In the present version of Wraith Scheme, the only fixnums stored are 32-bit integers.
Note that it is possible to store integers as flonums: Wraith Scheme does so frequently.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a number stored as a fixnum. Otherwise, returns #f.
For Example:
(e::fixnum? #t) ;; ==> #f (e::fixnum? 1) ;; ==> #t (e::fixnum? 1.000) ;; ==> #t (e::fixnum? 1.001) ;; ==> #f (e::fixnum? (sqrt 4) ;; ==> #f ;; But note that (integer? (sqrt 4)) ;; ==> #t (e::fixnum? 1000000000000) ;; ==> #f (integer? 1000000000000) ;; ==> #t
Type:
Procedure.
Operation:
Determine whether a Scheme object is a number stored as a flonum
Rationale, Explanation, Excuses:
I installed this procedure to aid in debugging Wraith Scheme's functions that deal with numbers. In the present version of Wraith Scheme, flonums are used to store only 32-bit and 64-bit floating-point numbers.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a number stored as a flonum. Otherwise, returns #f.
For Example:
(e::float? #t) ;; ==> #f (e::float? 1) ;; ==> #f (e::float? 1.000) ;; ==> #f (e::float? 1.001) ;; ==> #t (e::float? (sqrt 4) ;; ==> #t ;; But note that (integer? (sqrt 4)) ;; ==> #t (e::float? 1000000000000) ;; ==> #t (integer? 1000000000000) ;; ==> #t
Type:
Procedure.
Operation:
Test whether a promise has been forced.
Rationale, Explanation, Excuses:
In case the evaluation of a promise causes side effects, it may be useful to determine whether or not that evaluation has already taken place.
Recall that the result of forcing a promise the first time is cached, so that subsequent forces of the same promise cause no additional evaluation.
Arguments:
One promise.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument has been forced. Otherwise, returns #f.
For Example:
(define a (delay (+ 2 2))) ;; ==> a (e::forced? a) ;; ==> #f (force a) ;; ==> 4 (e::forced? a) ;; ==> #t
Type:
Procedure.
Operation:
Cause garbage collection.
Rationale, Explanation, Excuses:
Garbage collection happens automatically, when Wraith Scheme's current main memory is about to fill up. It may be useful to force it; for example, when about to measure code speed, or when a time-consuming interruption of a process controlled by Wraith Scheme would be unfortunate ...
Computer: Captain! CAPTAIN!! Klingons close on the port bow!
Captain James T. Schemer: Shields up! Fire photon torpedoes!
Computer: Just a few minutes while I garbage-collect. Be patient ...
Arguments:
None.
Side Effects:
None.
Returned Value:
#t
For Example:
(e::full-gc) ;; Wraith Scheme garbage collects. ;; ==> #t
Type:
Procedure.
Operation:
Generate a symbol that has no value or binding.
This operation is atomic, in the sense that even if many Wraith Scheme procedures call "e::gensym", even at the same time, every gensym'd value returned will be unique.
Rationale, Explanation, Excuses:
Gensym'd symbols are useful for various kinds of software that needs "scratch" labels for things.
The symbols created by "e::gensym" are of the general form "gNNNNN...", where the N's constitute the external representation of a positive integer greater than or equal to 23000.
I chose this form in memory of Ratfor (rational Fortran), which generated symbols of the same form.
The procedure will check each generated symbol before returning; if the symbol it generates already happens to have a value or a binding, it will choose another.
Arguments:
None.
Side Effects:
None.
Returned Value:
A symbol: Returns a symbol that had no value or binding when it was generated.
For Example:
(e::gensym) ;; ==> g23000
Type:
Procedure.
Operation:
Obtain the 32-bit tag portion of the Wraith Scheme tagged aval associated with a Wraith Scheme object.
Rationale, Explanation, Excuses:
This procedure provides a low-level view of part of the structure of Wraith Scheme objects. I implemented it to aid in debugging Wraith Scheme.
I am reluctant to document what the tag bits mean because their meaning will almost certainly change in subsequent releases. Send me EMail if you really want to know.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
An integer: Returns the tag associated with the argument.
For Example:
(e::get-tag 42) ;; ==> 57 ;; #b111001
Type:
Procedure.
Operation:
Test whether a Scheme object is an "inf" -- a special flonum value used to represent an infinity. (More commonly, used to represent the result of a calculation that has overflowed the allowed range of flonums.)
Rationale, Explanation, Excuses:
Wraith Scheme uses IEEE floating-point numbers, which have infs and nans, so it is useful to be able to test for their presence.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is an inf (of any sign). Otherwise, returns #f
For Example:
(e::inf? #t) ;; ==> #f (e::inf? 3) ;; ==> #f (e::inf? 1.e10000) ;; ==> #t
Type:
Procedure.
Operation:
Report a useful selection of information about the low-level structure of a Wraith Scheme object.
Rationale, Explanation, Excuses:
I installed this procedure primarily for debugging Wraith Scheme. It is also useful for satisfying one's curiosity about what Wraith Scheme is doing.
"e::inspect" returns its argument. Thus you may wrap "(e::inspect ...)" around basically any Scheme object, anywhere, to print out useful information, without interrupting the flow of calculation at the point where the object is used.
The first line of output from "e::inspect" is generally the numeric values of the Wraith Scheme tagged aval that represents it, with the 32-bit tag separated from the 32-bit value by a dash. The numbers will be printed in hexadecimal, and will be followed by information about the cdr-coding (if any) of the object.
"e::inspect" is capable of printing lots of output, such as the entire source code or compiled code of a lambda expression or macro. The volume of printout is thus affected by the settings of the print-length and print-depth variables for lists and for vectors. Set these quantities to large numbers if you want to see all of the output from "e::inspect".
Arguments:
Any Scheme object.
Side Effects:
None.
Returned Value:
Any Scheme object: "e::inspect" returns its argument.
For Example:
;; Hexadecimal output will vary ... (e::inspect 42) ;; ==> 0039-0000002a: Exact Short Fixnum -- Not a Car 42 (e::inspect define) ;; ==> (e::inspect define) 000a-1b7bfe34: Macro -- Not a Car (lambda (form) (c::if (list? form) ;; ... lots more output. #<Macro>
Type:
Procedure.
Operation:
Provide a lengthy human-readable description of the contents of a Wraith Scheme world file.
Rationale, Explanation, Excuses:
I implemented this procedure for debugging Wraith Scheme's mechanisms for loading and storing worlds.
WARNING: Wraith Scheme does a poor job of identifying world files. Using "e::inspect-world" with a file that is not actually a Wraith Scheme world file may cause Wraith Scheme to crash.
Caution: A very large world file may cause this procedure to produce more than a hundred million lines of output -- or at least to try to do so -- and there is no way to preselect just part of it: When I use "e::inspect-world" for debugging, I use small world files.
Arguments:
At most one: If there is an argument, it should be a string containing a Unix-style path to a Wraith Scheme world file; if there is no argument, Wraith Scheme will use the Dialog Panel to obtain a path.
Side Effects:
None.
Returned Value:
#t
For Example:
(e::inspect-world "<the default Wraith Scheme world>") ;; ==> ;; Lots of output ;; If you would like to see what a world file dump ;; looks like, use the Wraith Scheme Instrument Panel ;; to obtain the path to the standard Wraith Scheme world ;; -- the default one that gets loaded when Wraith Scheme ;; is launched, and try "e::inspect-world" with that one. (e::inspect-world) ;; Wraith Scheme uses Dialog Panel ;; to obtain a path to the file ;; to be inspected. ;; ==> #t
Type:
Procedure.
Operation:
Return the kitten number of the Wraith Scheme process where called.
Rationale, Explanation, Excuses:
Provides elementary information about parallel instances of Wraith Scheme.
Arguments:
None.
Side Effects:
None.
Returned Value:
An integer: The kitten number of the process in which the procedure was called.
For Example:
(e::kitten-number) ;; ==> 0 ;; In MomCat (e::kitten-number) ;; ==> 7 ;; In kitten 7
Type:
Procedures.
Operation:
Get and set internal variables used to control printing of large data structures.
Rationale, Explanation, Excuses:
Printing a circularly-linked data structure is a task that does not end. To help avoid such conditions, Wraith Scheme uses four internal variables to control how many elements of lists and vectors are printed, and to control how deep nested lists and vectors are printed.
The variables are not accessible by name; procedures are used to set and obtain their values, but for purposes of discussion, let us imagine that they are called:
list-print-depth list-print-length vector-print-depth vector-print-length
Current values of all these variables are displayed in the Wraith Scheme Instrument Panel.
When a list is longer than the value of "list-print-length", the print routines use an ellipsis to indicate the "extra" elements. Thus if "list-print-length" is 6, a list might print as:
(foo bar baz frob quux mumble ...)
and similarly for vectors.
When lists are nested more deeply than the value of "list-print-depth", the print routines use an ellipsis to indicate the "extra" elements. Thus if "list-print-depth" is 6, a deeply-nested list might print as:
(((((((...)))))))
Two caveats apply to the use of these internal variables:
Arguments:
The "set" procedures: An integer no less than three.
The other procedures: None.
Side Effects:
None.
Returned Value:
The "set" procedures: #t.
The other procedures: An integer: Return the present value of the indicated special variable.
For Example:
(e::list-print-length) ;; ==> 20 ;; The default. (list 1 2 3 4) ;; ==> (1 2 3 4) (e::set-list-print-length! 3) ;; ==> #t (list 1 2 3 4) ;; ==> (1 2 3 ...)
Type:
Procedure.
Operation:
Load a Wraith Scheme world file.
Only the MomCat may perform this procedure; calling this procedure in any other Wraith Scheme process will cause an error.
Rationale, Explanation, Excuses:
A world file is a machine-readable image of the entire content of Wraith Scheme main memory. Storing one saves the what you were working on in Wraith Scheme so that you may resume work in another session. Loading one restores that saved work.
Arguments:
At most one: If there is an argument, it should be a string containing a Unix-style path to a Wraith Scheme world file; if there is no argument, Wraith Scheme will use the Dialog Panel to obtain a path.
Side Effects:
Overwrites all of Wraith Scheme's main memory.
Returned Value:
Does not apply; after a world load, Wraith Scheme will reset to the top-level loop.
For Example:
(e::load-world! "MyFavoriteWorld") ;; ==> ;; Load world and reset. (e::load-world) ;; Wraith Scheme uses Dialog Panel ;; to obtain a path to the file ;; to be used. ;; ==> #t
Type:
Procedure.
Operation:
Test whether a Scheme object is a "logic constant" -- one of "#u" and "#s".
Rationale, Explanation, Excuses:
This procedure is for logic programming along the lines described in Daniel P. Friedman, William E. Byrd and Oleg Kiselyov, The Reasoned Schemer, MIT Press, 2005. Wraith Scheme provides the logic constants #u and #s.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is either #u or #s. Otherwise, returns #f.
For Example:
(e::logic-constant? #t) ;; ==> #f (e::logic-constant? #u) ;; ==> #t (e::logic-constant? #s) ;; ==> #t
Type:
Procedure.
Operation:
Test whether a Scheme object is a long float; that is, whether it is stored as a 64-bit flonum.
Rationale, Explanation, Excuses:
I installed this procedure to aid in debugging Wraith Scheme's functions that deal with numbers. In the present version of Wraith Scheme, long floats are numbers stored as 64-bit flonums.
Arguments:
One Scheme object
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is stored as a 64-bit flonum. Otherwise, returns #f.
For Example:
(e::long-float? #t) ;; ==> #f (e::long-float? 1) ;; ==> #f (e::long-float? 1.1q0) ;; ==> #f (e::long-float? 1.1e0) ;; ==> #t
Type:
Operation:
Create a Wraith Scheme low-level macro, and make it be the value of a symbol.
Rationale, Explanation, Excuses:
The macros referred to are Wraith Scheme's low-level internal implementation, not the hygienic macros defined in the R5 report.
A "call" or invocation of a Wraith Scheme macro involves using a procedure that was created when the macro was defined, to transform the expression in which the macro call occurred, into something else. That "something else" is evaluated by Wraith Scheme, to produce the result of the macro "call".
"e::macro" creates the procedure in question, makes it part of a Wraith Scheme low-level macro object, and binds that object to a symbol -- the symbol being what we might informally call the macro's "name".
The Wraith Scheme code for a macro "call" is similar to the code for a procedure call: It is a list whose first item evaluates to the macro in question. When Wraith Scheme encounters such an expression, it passes the entire list as an argument to the lambda expression associated with that macro, then further evaluates whatever the lambda expression returns.
The most conventional use of macros is to perform some syntactic transformation on the list which constitutes the macro call, but other uses are certainly possible.
Arguments:
Two: The first, a symbol, and the second, a lambda expression of one argument, which will be passed the entire expression that constitutes a macro "call", when the macro in question is called.
Side Effects:
None.
Returned Value:
A symbol: Returns the first argument.
For Example:
;; Suppose you are tired of writing "set!" and would ;; rather write things like "(assign 3 to foo)". ;; Define this macro: (e::macro assign ;; The macro "name". (lambda (form) ;; form is, e.g., "(assign 3 to foo)" ;; We build up the returned value from ;; a quasiquoted "set!" ... `(set! ,(cadddr form) ;; The cadddr is, e.g., "foo". ,(cadr form)))) ;; The cadr is, e.g., "3". ;; ==> assign ;; Let's expand a call and see if it works: (e::expand-macro '(assign 3 to foo)) ;; ==> (set! foo 3) ;; Looks promising, let's try it. The ;; "set!" won't work unless "foo" is already ;; defined, so ... (define foo 0) ;; ==> foo foo ;; ==> 0 (assign 3 to foo) ;; ==> #t foo ;; ==> 3 ;; Yippee!!
Type:
Operation:
Create a Wraith Scheme low-level macro, but do not bind it to a symbol.
Rationale, Explanation, Excuses:
The macros referred to are Wraith Scheme's low-level internal implementation, not the macros defined in the R5 report.
A "call" or invocation of a Wraith Scheme macro involves using a procedure that was created when the macro was defined, to transform the expression in which the macro call occurred, into something else. That "something else" is evaluated by Wraith Scheme, to produce the result of the macro "call".
"e::macro-body" creates the procedure in question and makes it part of a Wraith Scheme low-level macro object, but does not bind that object to a symbol -- less formally, the object is not given a "name".
The Wraith Scheme code for a macro "call" is similar to the code for a procedure call: It is a list whose first item evaluates to the macro in question. When Wraith Scheme encounters such an expression, it passes the entire list as an argument to the lambda expression associated with that macro, then further evaluates whatever the lambda expression returns.
The most conventional use of macros is to perform some syntactic transformation on the list which constitutes the macro call, but other uses are certainly possible.
Arguments:
One lambda expression of one argument, which will be passed the entire expression that constitutes a macro "call", when the macro in question is called.
Side Effects:
None.
Returned Value:
A macro.
For Example:
;; Suppose you are tired of writing "set!" and would ;; rather write things like "(assign 3 to foo)". ;; Define this macro: (define assign ;; The macro "name". (e::macro-body (lambda (form) ;; form is, e.g., "(assign 3 to foo)" ;; We build up the returned value from ;; a quasiquoted "set!" ... `(set! ,(cadddr form) ;; The cadddr is, e.g., "foo". ,(cadr form))))) ;; The cadr is, e.g., "3". ;; ==> assign ;; Let's expand a call and see if it works: (e::expand-macro '(assign 3 to foo)) ;; ==> (set! foo 3) ;; Looks promising, let's try it. The ;; "set!" won't work unless "foo" is already ;; defined, so ... (define foo 0) ;; ==> foo foo ;; ==> 0 (assign 3 to foo) ;; ==> #t foo ;; ==> 3 ;; Yippee!!
Type:
Procedure.
Operation:
Test whether a Scheme object is a Wraith Scheme low-level macro.
Rationale, Explanation, Excuses:
The macros referred to are Wraith Scheme's low-level implementation, not the kind defined in the R5 report.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a Wraith Scheme low-level macro. Otherwise, returns #f.
For Example:
(e::macro? define) ;; ==> #t (e::macro? cons) ;; ==> #f
Type:
Procedure.
Operation:
Returns whether or not the Wraith Scheme process in which it was called is the MomCat.
Rationale, Explanation, Excuses:
Provides elementary information about parallel instances of Wraith Scheme.
Arguments:
None.
Side Effects:
None.
Returned Value:
A boolean. Returns #t if, and only if, called in the MomCat. Otherwise, returns #f
For Example:
(e::momcat?) ;; ==> #t ;; In MomCat (e::momcat?) ;; ==> #f ;; In kittens 1 through 7
Type:
Procedure.
Operation:
Construct a Wraith Scheme string containing a number formatted with two digits to the right of the decimal point.
Rationale, Explanation, Excuses:
Standard R5 Scheme procedures offer little immediate capability for formatting numbers in many ways.
Arguments:
One number:
Side Effects:
None.
Returned Value:
A string: Returns the first argument formatted with two digits to the right of the decimal point.
For Example:
(e::money->string 29.95) ;; ==> "29.95"
Type:
Procedure.
Operation:
Test whether a Scheme object is a "multiple-values return" -- a special type of Scheme object used by Wraith Scheme as an intermediary between "values" and "call-with-values".
Rationale, Explanation, Excuses:
"Multiple-values returns" are a class of object peculiar to Wraith Scheme, whose existence and use is a low-level implementation detail that might become visible to users, and that might be of interest to some. This predicate provides a way to distinguish these objects.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a multiple-values return. Otherwise, returns #f
For Example:
(e::multiple-values? (values 1 2 3)) ;; ==> #t (e::multiple-values? #t) ;; ==> #f (e::multiple-values? 42) ;; ==> #f
Type:
Procedure.
Operation:
Test whether a Scheme object is a "nan" -- a special flonum value used to represent the result of a mathematical calculation that could not produce a numerical result.
Rationale, Explanation, Excuses:
Wraith Scheme uses IEEE floating-point numbers, which have infs and nans, so it is useful to be able to test for their presence.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a nan. Otherwise, returns #f
For Example:
(e::nan? #t) ;; ==> #f (e::nan? 3) ;; ==> #f (e::nan? ((- 1.e10000 1.e10000)) ;; ==> #t ;; Two infs.
Type:
Procedure.
Operation:
Test whether the amount of Wraith Scheme main memory in use equals or exceeds ninety percent of the amount available.
Rationale, Explanation, Excuses:
It may occasionally be useful to know when Wraith Scheme is about to garbage-collect. A user could easily write this procedure, but it is faster as a built-in.
Arguments:
None.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the amount of Wraith Scheme main memory in use equals or exceeds ninety percent of the amount available. Otherwise, returns #f
For Example:
(e::ninety-percent-used?) ;; ==> #f
Type:
Procedure.
Operation:
Test whether a Scheme object is different from the empty list.
Rationale, Explanation, Excuses:
This operation is marginally faster than the composition of "not" and "null?", and allowed rapid modification of code when I converted my Scheme system from one that used the empty list to represent falsehood to one that didn't.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is not the empty list. Otherwise, returns #f.
For Example:
(e::not-null? #t) ;; ==> #t (e::not-null? #f) ;; ==> #t (e::not-null? '()) ;; ==> #f
Type:
Procedure.
Operation:
Return the number of kittens running in parallel that were present when the current group of parallel Wraith Scheme processes was started. That is, this number does not change if a kitten exits for some reason, or if you cause it to exit -- for example, by means of the "Quit" command.
The MomCat is not included in this count.
Rationale, Explanation, Excuses:
Provides elementary information about parallel instances of Wraith Scheme.
Arguments:
None.
Side Effects:
None.
Returned Value:
For Example:
(e::number-of-kittens) ;; ==> 0 ;; If just the MomCat. (e::number-of-kittens) ;; ==> 7 ;; With the MomCat and 7 kittens.
Type:
Procedure.
Operation:
Construct a Wraith Scheme string containing a number formatted with a given number of digits to the right of the decimal point.
Rationale, Explanation, Excuses:
Standard R5 Scheme procedures offer little immediate capability for formatting numbers in many ways.
Arguments:
Two numbers. The first is the number to be formatted; the second is the number of digits to appear to the right of the decimal point. The second argument must be in the range [0..10].
Side Effects:
None.
Returned Value:
A string: Returns the first argument formatted with n digits to the right of the decimal point, where n is the second argument. The value of n must be in the range [0 .. 10].
For Example:
(e::number->string-with-n-decimals 1/3 3) ;; ==> "0.333" (e::number->string-with-n-decimals (- (/ 1000 3)) 6) ;; ==> "333.333333"
Type:
Procedure.
Operation:
A version of call-with-current-continuation that does not support dynamic-wind.
Rationale, Explanation, Excuses:
Wraith Scheme implements dynamic-wind generally along the lines of the implementation demonstrated by Jonathan Rees (1992) in "The Scheme of Things: The June Meeting", published in Lisp Pointers V(4), October-December 1992. That implementation involves modifying call-with-current-continuation. The unmodified version is "e::original-cwcc".
Arguments:
One argument, which must be a procedure that itself takes one argument.
Side Effects:
Saves the current state of Scheme in such a way that it can subsequently be restored at will. See call-with-current-continuation for details.
Returned Value:
See call-with-current-continuation for details.
For Example:
Type:
Procedure.
Operation:
Test whether the value or binding of a variable is "permanent", in the sense that an attempt to change it with, for example, "set!", is an error.
Rationale, Explanation, Excuses:
To make it difficult inadvertently to redefine fundamental Scheme procedures like "+" and "cons", I provide symbols with a "permanent" flag. When set, any attempt to change the value or binding of the given symbol causes Wraith Scheme to report an error. "e::clear-permanent!" clears this flag, so you can, for example, redefine "cons", if you really, really, want to, "e::set-permanent!" sets it, so you can't, and "e::permanent?" tests whether it is set or not.
Arguments:
One symbol.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the given symbol has a value or binding that is permanent, in the sense described above. Otherwise, returns #f.
For Example:
(e::clear-permanent! 'cons) ;; ==> #t (e::permanent? 'cons) ;; ==> #f (e::set-permanent! 'cons) ;; ==> #t (e::permanent? 'cons) ;; ==> #t
Type:
Procedure.
Operation:
Return the Unix process identification number of the process in which the procedure was called.
Note that the procedure e::show-kittens provides (among other things) the process ids of all members of a group of cooperating Wraith Scheme processes.
Rationale, Explanation, Excuses:
Unix process identification numbers are valuable for examining and controlling Wraith Scheme processes from the Unix command line -- perhaps from the Macintosh "Terminal" application. For example, they might be useful in interpreting output from the Unix "ps" program, or as arguments to the Unix "kill" program.
Arguments:
None.
Side Effects:
None.
Returned Value:
An integer: The Unix process identification number of the Wraith Scheme process in which the procedure was called.
For Example:
;; Process ids are nonnegative integers of up to five digits. (e::process-id) ;; ==> 22316 ;; e.g.,
Type:
Procedure.
Operation:
Find the Wraith Scheme application's directory; that is, the directory of "Wraith Scheme.app".
Rationale, Explanation, Excuses:
Users often organize directories so that files related to a program are in directories only a short pathname from the program itself. Thus a simple means to find the program's directory seems useful.
Arguments:
None.
Side Effects:
None.
Returned Value:
A string: Returns a string containing the absolute Unix path to the directory containing "Wraith Scheme.app". The returned string will end in a '/'.
For Example:
;; Perhaps (e::program-directory) ;; ==> "/Users/JayFreeman/Scheme"
Type:
Procedure.
Operation:
Test whether a Scheme object is a promise.
Rationale, Explanation, Excuses:
In Wraith Scheme, promises are a distinct type; it seemed useful to have a simple way to test for them.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is a promise. Otherwise, returns #f.
For Example:
(e::promise? '()) ;; ==> #f (define a (delay (+ 2 2))) ;; ==> a (e::promise? a) ;; ==> #t (force a) ;; ==> 4 (e::promise? a) ;; ==> #t
Type:
Procedure.
Operation:
Return a random number generated by the Unix "random" procedure.
Rationale, Explanation, Excuses:
Unix provides the high-quality random-number generator "random", and the procedure "srandom" to seed it. Wraith Scheme provides a simple interface to these procedures.
Wraith Scheme seeds the Unix "random" mechanism with the Unix time every time Wraith Scheme is launched. If you wish to make "e::random" generate the same series of numbers on several separate occasions -- for example, for debugging a calculation that uses "e::random" -- you will have to seed the random number generator with the same seed before each occasion. Use "e::srandom" to do so.
Arguments:
None.
Side Effects:
None.
Returned Value:
An integer. Returns the result of a call to Unix "random()".
For Example:
(e::random) ;; ==> 2110915871 ;; Or whatever ...
Type:
Procedure.
Operation:
Abandon processing and restart the top-level loop.
Rationale, Explanation, Excuses:
Being able to unpaint yourself from a corner is a useful control feature.
Arguments:
None.
Side Effects:
None.
Returned Value:
Does not apply; "e::reset" never returns.
For Example:
(e::reset) ;; ==> ;; Wraith Scheme resets.
Type:
Procedure.
Operation:
Find the number of bytes free in Wraith Scheme main memory.
Rationale, Explanation, Excuses:
Simple storage-instrumentation procedure: Just returns a number. Contrast with "e::show-room", which prints out text describing memory use.
Arguments:
None.
Side Effects:
None.
Returned Value:
An integer: Returns the number of bytes free in Wraith Scheme main memory.
For Example:
(e::room) ;; ==> 104716012 ;; e.g.
Type:
Procedure.
Operation:
Save the content of Wraith Scheme main memory to a Wraith Scheme world file.
Only the MomCat may perform this procedure; calling this procedure in any other Wraith Scheme process will cause an error.
Rationale, Explanation, Excuses:
A world file is a machine-readable image of the entire content of Wraith Scheme main memory. Storing one saves the what you were working on in Wraith Scheme so that you may resume work in another session. Loading one restores that saved work.
Arguments:
At most one: If there is an argument, it should be a string containing a Unix-style path to the file to be used for saving the world. if there is no argument, Wraith Scheme will use the Dialog Panel to obtain a path.
Side Effects:
None.
Returned Value:
#t
For Example:
(e::save-world "MyBackup.world") ;; Saves world ;; ==> #t (e::save-world) ;; Wraith Scheme uses Dialog Panel ;; to obtain a path to the file ;; to be used. ;; ==> #t
Type:
Procedure.
Operation:
Set the internal flag that tell Wraith Scheme to compile defines automatically.
Rationale, Explanation, Excuses:
Provides Scheme-program control of an important internal flag.
Arguments:
None.
Side Effects:
Turns on automatic compilation.
Returned Value:
#t
For Example:
(e::set-compiler-on!) ;; ==> #t
Type:
Procedure.
Operation:
Set the directory from which Unix relative paths are referenced.
Rationale, Explanation, Excuses:
Making effective use of the Macintosh's Unix file system from Wraith Scheme requires means to set and determine the current directory.
Arguments:
One string, containing a Unix-style path to a directory. If the string does not end in a '/', this procedure will append one.
Side Effects:
Sets the current directory
Returned Value:
#t
For Example:
(e::set-current-directory! "/Applications") ;; ==> ;; Wraith Scheme sets current directory #t
Type:
Procedure.
Operation:
Change the input default port, which Wraith Scheme reconnects to every time it resets to the top-level loop.
Rationale, Explanation, Excuses:
I installed this procedure as a development aid for testing error messages: By default, Wraith Scheme expects input from the keyboard, and sets the current input port to the keyboard on startup, and every time there is a reset to the top-level loop, without regard to whether that reset was deliberately caused by the user or whether it was in consequence of an error.
There are plenty of standard Scheme procedures to change the default input port while error-free code is running; however, resetting to the top-level loop always restores things so that input comes from the keyboard, or at least, that is what it would do if it weren't for "e::set-input-port!". This procedure changes the default value, to which Wraith Scheme resets the current input port, to a port obtained by opening a file. If you like, it makes Wraith Scheme think that the keyboard is in a file somewhere.
That allows me to test Wraith Scheme's error messages by taking input from a file. I fill the file with Scheme expressions that will cause an error and use "e::set-input-port!" to make the default input come from that file. I log the error messages on a transcript file. Wraith Scheme encounters the first erroneous expression -- from the file -- prints an error message, resets to the top-level loop, then takes the next erroneous expression from the file. All I have to do is check the transcript file to make sure the error messages were all proper and sensible.
Arguments:
At most one: If present, a string containing a Unix-style path to the file from which to take input. If there is no argument, Wraith Scheme will use the Wraith Scheme Dialog Panel to obtain a path.
Side Effects:
Changes the default source of input to Wraith Scheme.
Returned Value:
#t.
For Example:
(e::set-input-port! "MyErrorTests") ;; ==> #t ;; And default input from the file.
Type:
Procedure.
Operation:
Set the "permanent" flag associated with a symbol.
Rationale, Explanation, Excuses:
To make it difficult inadvertently to redefine fundamental Scheme procedures like "+" and "cons", I provide symbols with a "permanent" flag. When set, any attempt to change the value or binding of the given symbol causes Wraith Scheme to report an error. "e::clear-permanent!" clears this flag, so you can, for example, redefine "cons", if you really, really, want to, and "e::set-permanent!" sets it, so you can't, and "e::permanent?" tests whether it is set or not.
You may of course use these procedures for new symbols that you yourself create.
Arguments:
One symbol.
Side Effects:
Makes it an error to change the value or binding of the argument.
Returned Value:
#t
For Example:
(e::clear-permanent! 'cons) ;; ==> #t ;; DANGER WILL ROBINSON (e::set-permanent! 'cons) ;; ==> #t ;; That was close ...
Type:
Procedure.
Operation:
Set the internal flag that tell Wraith Scheme to display numbers with the full precision available.
Rationale, Explanation, Excuses:
Provides Scheme-program control of an important internal flag.
Arguments:
None.
Side Effects:
Causes Wraith Scheme's numeric display routines to use full precision.
Returned Value:
#t
For Example:
(e::set-show-full-precision!) ;; ==> #t
Type:
Procedure.
Operation:
Change the 32-bit tag portion of the Wraith Scheme tagged aval associated with a Wraith Scheme object.
Rationale, Explanation, Excuses:
This procedure provides detailed and destructive low-level control of part of the structure of Wraith Scheme objects. I implemented it to aid in debugging Wraith Scheme.
ALMOST ANY USE OF THIS PROCEDURE WILL CAUSE WRAITH SCHEME TO CRASH!!
Proper operation of Wraith Scheme depends on tags accurately characterizing the structure of the objects with which they are associated. On the basis of an incorrect tag, Wraith Scheme might decide to dereference something that would have been a valid pointer if the tag had been correct, but actually isn't. Other forms of disaster are also possible.
I am reluctant to document what the tag bits mean because their meaning will almost certainly change in subsequent releases. Send me EMail if you really want to know.
Arguments:
Two: The first, any Scheme object; the second, an integer, taken to be the new tag value for the first argument.
Side Effects:
Alters the low-level structure of the argument, likely disastrously.
Returned Value:
#t
For Example:
;; As I write these words, the tag for a 32-bit ;; fixnum is 57. Let's see what happens if we ;; set the tag for a character to that value. (e::get-tag #\a) ;; ==> 35 (e::set-tag #\a 57) ;; ==> 97 ;; Which is the integer ;; for ASCII 'a'.
Type:
Procedure.
Operation:
Test whether a Scheme object is a short float; that is, whether it is stored as a 32-bit flonum.
Rationale, Explanation, Excuses:
I installed this procedure to aid in debugging Wraith Scheme's functions that deal with numbers. In the present version of Wraith Scheme, long floats are numbers stored as 32-bit flonums.
Arguments:
One Scheme object.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the argument is stored as a 32-bit flonum. Otherwise, returns #f.
For Example:
(e::short-float? #t) ;; ==> #f (e::short-float? 1) ;; ==> #f (e::short-float? 1.1q0) ;; ==> #t (e::short-float? 1.1e0) ;; ==> #f
Type:
Procedure.
Operation:
Print human-readable information about all the environments lexically visible from the point where "e::show-dynamic-environment-list" was called, but only for environments which were created by the execution of a lambda expression or by some other Scheme form that creates an environment. That is, this procedure tells nothing about the interaction environment, the Scheme-report environment, or the null environment.
Rationale, Explanation, Excuses:
The fundamental construct in a Wraith Scheme environment is a pair whose car is a value or binding -- any Scheme object -- and whose cdr is the symbol which has teat value or binding. The top-level environment is hashed: It is a vector, each of whose elements is a list of value/symbol pairs. All other environments are lists of value/symbol pairs.
At any given point in the execution of Wraith Scheme code, there exists an implicit list of all the environments that are lexically visible from that point, sorted so that those lexically closer to the code executing are nearer the car of the list.
This procedure shows human-readable information about all the environments on that list that are created dynamically, by procedures that are running. It omits the environments that are visible from the top-level loop. These latter environments are large: Printing them out would take many lines and much time. With "e::show-dynamic-environment-list", you don't need to look at printout of the top-level environment if you don't need it.
Arguments:
None.
Side Effects:
None.
Returned Value:
#t
For Example:
(let ((x 3)) (let ((y 5)) ((lambda (z) (e::show-dynamic-environment-list)) 42))) ;; ==> -------- Environment 0 of Environment List -------- z <- 42 -------- Environment 1 of Environment List -------- y <- 5 -------- Environment 2 of Environment List -------- x <- 3 -------- Environment 3 of Environment List -------- ... -------- End of Environment List -------- #t
Type:
Procedure.
Operation:
Print human-readable information about the nearest environment lexically visible from the point where "e::show-environment" was called.
Rationale, Explanation, Excuses:
The fundamental construct in a Wraith Scheme environment is a pair whose car is a value -- any Scheme object -- and whose cdr is the symbol to which that value is bound. The top-level environment is hashed: It is a vector, each of whose elements is a list of value/symbol pairs. All other environments are lists of value/symbol pairs.
At any given point in the execution of Wraith Scheme code, there exists an implicit list of all the environments that are lexically visible from that point, sorted so that those lexically closer to the code executing are nearer the car of the list.
This procedure shows human-readable information about only one environment on that list -- the one lexically nearest to the point at which "e::show-environment" was called.
Arguments:
None.
Side Effects:
None.
Returned Value:
#t
For Example:
(let ((x 42)) (e::show-environment)) ;; ==> Current environment -- first of 2: x <- 42 #t
Type:
Procedure.
Operation:
Print human-readable information about all environments lexically visible from the point where "e::show-environment-list" was called.
Rationale, Explanation, Excuses:
The fundamental construct in a Wraith Scheme environment is a pair whose car is a value or binding -- any Scheme object -- and whose cdr is the symbol which has teat value or binding. The top-level environment is hashed: It is a vector, each of whose elements is a list of value/symbol pairs. All other environments are lists of value/symbol pairs.
At any given point in the execution of Wraith Scheme code, there exists an implicit list of all the environments that are lexically visible from that point, sorted so that those lexically closer to the code executing are nearer the car of the list.
This procedure shows human-readable information about every environment on that list.
Arguments:
None.
Side Effects:
None.
Returned Value:
#t
For Example:
;; In my Wraith Scheme environment, at present ... (let ((x 42)) (e::show-environment-list)) ;; ==> -------- Environment 0 of Environment List -------- x <- 42 -------- Environment 1 of Environment List -------- cdddr <- #<Built-in procedure "cdddr"> string-ref <- #<Built-in procedure "string-ref"> e::error <- #<Interpreted lambda expression> ;; ... and lots more text.
Type:
Procedure.
Operation:
Return the value of the internal flag that controls whether Wraith Scheme displays numbers with the full precision available.
Rationale, Explanation, Excuses:
Allows Scheme programs to examine important internal state of the Wraith Scheme interpreter.
Arguments:
None.
Side Effects:
None.
Returned Value:
A boolean: Returns the (boolean) flag that controls whether Wraith Scheme displays numbers with the full precision available. This flag is true if, and only if, numbers are displayed with the full precision available.
For Example:
(e::set-show-full-precision!) ;; ==> #t (e::show-full-precision?) ;; ==> #t 1/3 ;; ==> 0.33333333333333331 (e::clear-show-full-precision!) ;; ==> #t (e::show-full-precision?) ;; ==> #f 1/3 ;; ==> 0.3333333
Type:
Procedure.
Operation:
Show information about the Wraith Scheme processes running, in human-readable form. Some of this information will be useful only for development and maintenance of Wraith Scheme itself, and since I expect to change that information regularly based on my own needs, I shall not document it all here. Notwithstanding:
The entry under "On" represents Wraith Scheme's present opinion as to whether the process shown is running. It is a boolean flag (zero for FALSE, anything else for TRUE) in shared memory, set when the process is created and cleared if the process shuts down in an orderly manner. Unfortunately, not all shutdowns are orderly, and it is possible for a process to be running but unresponsive, so take this entry with a grain of salt.
The process id numbers of the MomCat and the kittens are their Unix process identification numbers. They might be useful, for example, in examining the output of the Unix "ps" command, or as arguments to the Unix "kill" command.
Note that the procedure e::process-id returns the process id of the Wraith Scheme process in which it was called.
Rationale, Explanation, Excuses:
Provides elementary information about parallel instances of Wraith Scheme.
Arguments:
None.
Side Effects:
None.
Returned Value:
#t
For Example:
(e::show-kittens) ;; ==> ;; With four kittens running, but not busy, might print: Who On ObList GC Message Message Block Process In Reg Lock From From Reason ID Mom Kitten Number Mom: 1 0 0 1 0 0 0 22316 Kit 1: 1 0 0 1 0 0 0 22318 Kit 2: 1 0 0 1 0 0 0 22320 Kit 3: 1 0 0 1 0 0 0 22322 Kit 4: 1 0 0 1 0 0 0 22324 ;; Note that the specific process id numbers will vary.
Type:
Procedure.
Operation:
Show a low-level description of every locked object in Scheme main memory, and of the state of locking of bins of the hash tables used to control access to Wraith Scheme's oblist and top-level environment.
Rationale, Explanation, Excuses:
For use in debugging.
Arguments:
None.
Side Effects:
None.
Returned Value:
#t
For Example:
(e::show-locks) ;; ==> ;; e.g., *** Memory space descriptor at 153cc000, 364624 of 11534336 (hex b00000) bytes used. space --> 153cc018, free -> 15e72fc8, lowFree -> 153cc018, end -> 15ecc018, inUse -> 1 15e92868 : 13012041-15e83248: String -- Cdr Next 15ec2630 : 13002041-15e80674: String -- Cdr Next No ObList hash bins locked. No TLE hash bins locked. #t
Type:
Procedure.
Operation:
Provide a lengthy printout describing that part of Wraith Scheme main memory that is presently in use.
Rationale, Explanation, Excuses:
For use in debugging.
Caution: Wraith Scheme main memory can be as large as one Gigabyte. If so, and if you call "e::show-room" at a time when a large part of that memory is in use, the procedure will produce more than a hundred million lines of output -- or at least to try to do so -- and there is no way to preselect just part of it.
Arguments:
None.
Side Effects:
None.
Returned Value:
#t
For Example:
(e::show-memory) ;; ==> ;; Lots of output.
Type:
Procedure.
Operation:
Describe current Wraith Scheme main memory use in human-readable form.
Rationale, Explanation, Excuses:
Simple storage-instrumentation procedure: Contrast with "e::room", which just returns the number of bytes available.
Arguments:
None.
Side Effects:
None.
Returned Value:
#t
For Example:
(e::show-room) ;; ==> 104715868 bytes free out of 104857600 (141732 used) #t
Type:
Procedure.
Operation:
Seed the Unix random number generator, "random", by calling "srandom".
Rationale, Explanation, Excuses:
Unix provides the high-quality random-number generator "random", and the procedure "srandom" to seed it. Wraith Scheme provides a simple interface to these procedures.
Wraith Scheme seeds the Unix "random" mechanism with the Unix time every time Wraith Scheme is launched. If you wish to make "e::random" generate the same series of numbers on several separate occasions -- for example, for debugging a calculation that uses "e::random" -- you will have to seed the random number generator with the same seed before each occasion. Use "e::srandom" to do so.
Arguments:
One integer, taken as an argument to be passed to Unix "srandom".
Side Effects:
Seeds the Unix "random" random-number generator.
Returned Value:
#t
For Example:
(e::srandom 42) ;; ==> #t
Type:
Procedure.
Operation:
Determine the number of items on Wraith Scheme's run-time stack.
Rationale, Explanation, Excuses:
The Scheme engine that underlies Wraith Scheme has a run-time stack, much like the run-time stack used by more conventional programming languages, such as BCPL and PL/M -- er, make that C and Java.
(Wraith Scheme's Scheme engine is not running directly on the hardware: What actually executes is a C program, with its own run-time stack, which runs the Scheme engine and manipulates the Scheme engine's run-time stack -- which is different from the run-time stack of the C code -- as an emulated program on an emulated Scheme processor that I designed as I wrote Pixie Scheme, Wraith Scheme's predecessor. Got all that?)
(Just think of Wraith Scheme as being powered by the Little Scheme Engine That Cdr, er, Could.)
That stack is not infinitely deep; it has a size in bytes equal to approximately one-tenth the size of either of Wraith Scheme's main memories. To show how deep it is -- how many Wraith Scheme tagged avals have been pushed onto it -- use "e::stack-depth".
Arguments:
None.
Side Effects:
None.
Returned Value:
An integer: Returns the number of items pushed onto the run-time stack of Wraith Scheme's Scheme engine.
For Example:
;; From the top-level loop: (e::stack-depth) ;; ==> 5
Type:
Procedure.
Operation:
Return what the home directory was when Wraith Scheme was launched.
Rationale, Explanation, Excuses:
Use this procedure when you or your Scheme program gets lost in a maze of twisty little inodes, all alike.
Arguments:
None.
Side Effects:
None.
Returned Value:
A string: Returns a string containing the absolute Unix path to the home directory as it was when Wraith Scheme was launched. The returned string will end in a '/'.
For Example:
;; When Wraith Scheme is launched from the dock: (e::startup-directory) ;; ==> "/"
Type:
Procedure.
Operation:
Find the size of each of Wraith Scheme's main memories.
Rationale, Explanation, Excuses:
"e::store-size" is a basic memory-inspection function. Do not confuse it with "e::room": The former shows how many bytes each main memory has. The latter shows how many bytes of main memory are actually in use.
Arguments:
None.
Side Effects:
None.
Returned Value:
An integer: Returns the size, in bytes, of each of Wraith Scheme's main memories.
For Example:
(e::store-size) ;; ==> 104857600 ;; E.g.
Type:
Procedure.
Operation:
Search through the body of a compiled procedure for symbols that have been made permanent since it was compiled, and substitute the values of those symbols in the procedure.
Rationale, Explanation, Excuses:
Correct use of this procedure allows the compiler to make compiled code run faster.
Arguments:
One compiled procedure.
Side Effects:
Modifies the body of the argument.
Returned Value:
A compiled procedure: Returns the argument, appropriately modified.
For Example:
(define (foo x) (+ x my-global)) ;; ==> foo (define my-global 42) ;; ==> my-global (e::set-permanent! 'my-global) ;; ==> #t (e::inspect foo) ;; ==> ... (lambda (x) (#<Built-in procedure "+"> my-global #<Ref to var 0 in environment 0 down>)) ... (e::substitute-new-permanent-symbols foo) ;; ==> ... (e::inspect foo) ... (lambda (x) (#<Built-in procedure "+"> 42 #<Ref to var 0 in environment 0 down>)) ...
Type:
Procedure.
Operation:
Pass a string to the Unix "system" function.
Rationale, Explanation, Excuses:
The Unix "system" function makes it possible for any Unix program to run any other Unix program, just as if it had been typed into a Unix shell as a command line. Wraith Scheme's "e::system" procedure provides an easy interface to this capability from within Scheme. Give your command string to "e::system" and it will pass it through to the Unix "system" function, unchanged.
One problem with "e::system" is figuring out what happened: Unix commands generally print output to a console somewhere, and when the Unix "system" command is used from within a stand-alone application like Wraith Scheme, there is no obvious console handy ...
One way to get output from "e::system" into Wraith Scheme is to write it to a scratch file. That is, make all your Unix commands redirect their output to a file, in this manner:
(e::system "SomeCommand -flags args >& Scratch.text")
Then you can have Wraith Scheme use "read" or "read-char" to get hold of the contents of the file you have written.
On the other hand, if you don't need to make the output of "e::system" available to Wraith Scheme, you can always
You should always remember that "e::system" makes the full power of Apple's Unix operating system available to Wraith Scheme programs. Unix is powerful, and with great power goes the ability to make great mistakes. Abuse of "e::system" can mess up Wraith Scheme, your file system, your Internet connection, and possibly anything anywhere on the Internet. The "e::system" procedure is thereby properly considered dangerous. You have been warned. Don't say I didn't tell you.
Have fun.
Arguments:
One: A string, typically containing something intended to be a Unix command.
Side Effects:
Almost certainly.
Returned Value:
An integer. Returns whatever the encapsulated Unix "system" function returns.
For Example:
(e::system "cal") ;; ==> 0 ;; And go look in ;; the console log.
Type:
Procedure.
Operation:
Get the Unix time.
Rationale, Explanation, Excuses:
The Unix time is the number of seconds that have elapsed since 0 hours, 0 minutes, 0 seconds, January 1, 1970, in Coordinated Universal Time, without including leap seconds, at least insofar as you have remembered to set your system clock.
Arguments:
None.
Side Effects:
None.
Returned Value:
An integer: Returns the Unix time.
For Example:
(e::time) ;; ==> 1171525209 ;; Once upon a time.
Type:
Procedure.
Operation:
Each kitten, including the MomCat, has an input queue of expressions to be evaluated (in first-in, first-out order) by its top-level loop. This adds items to the input queue of the kitten whose kitten number is its first argument.
Items in a kitten's input queue have priority over expressions typed in at the keyboard. As long as there is anything in the queue, the kitten will deal with it first, before looking to see whether the user has typed anything. (Note, however, that the kitten will not evaluate any new items from either the input queue or the keyboard until it has finished evaluating any previous item it may have encountered.)
Resetting a kitten clears its input queue, whether the reset is performed explicitly by the user or whether it occurs as the result of an error.
Rationale, Explanation, Excuses:
This procedure provides the basic mechanism whereby one kitten may get another to do something.
Arguments:
Two: The first, an integer no less than zero and no greater than the number of kittens last launched in parallel; the second, any Scheme object.
Side Effects:
Adds an item to the input queue of the indicated kitten. The eventual evaluation of that item may have side effects of its own.
Returned Value:
#t
For Example:
;; In kitten 1. (e::tell-kitten 3 '(+ 2 2)) ;; The expression '(+ 2 2) is evaluated, yielding (+ 2 2), ;; and this value is placed in the input queue for kitten 3. ;; Kitten 3 eventually evaluates (+ 2 2), and thereupon ;; prints the result -- 4 -- in its Wraith Scheme window. (e::tell-kitten 3 (+ 2 2)) ;; Note -- no quotation mark. ;; The expression (+ 2 2) is evaluated, yielding 4 ;; and this value is placed in the input queue for kitten 3. ;; Kitten 3 eventually evaluates 4, and thereupon ;; prints the result -- 4 -- in its Wraith Scheme window. ;; Note that in the first example, kitten 3 performs the ;; addition, whereas in the second example, it does not.A discussion of error-handling may also be useful: If Wraith Scheme is launched with N kittens, then this procedure will report an error if its first argument is less than zero or greater than N. If for some reason one of those kittens should quit or exit, then, depending on what caused the exit, this procedure may not be able to detect that the kitten is no longer active. If it cannot do so, it will have no basis to report an error if that kitten's number is subsequently used as the procedure's first argument: It will put the second argument into the appropriate input queue, which will still exist in Wraith Scheme memory, even though the kitten that was handing items in that input queue has itself exited.
Type:
List of pointers to Scheme machine primitive functions.
Operation:
When this list is pushed into the continuation, a top-level loop runs.
Rationale, Explanation, Excuses:
This list of pointers to Scheme machine primitive functions constitutes the never-ending read-eval-print loop that is the "top loop" of Wraith Scheme. When this list is pushed into the continuation, a top-level loop runs, and when that push is done when Wraith Scheme either starts or resets, it is the top-level loop that is running.
How can a finite list of functions run forever? Well, the last function in the list pushes the entire list into the continuation.
Arguments:
Does not apply.
Side Effects:
Does not apply.
Returned Value:
Does not apply.
For Example:
;; Here we are in the top-level loop. ;; Let's see how deep the run-time stack is. (e::stack-depth) ;; ==> 5 ;; Now, let's try that business about ;; consing with the continuation ... (e::cons-with-continuation e::top-loop-code) ;; Nothing happened! Or so it seems ... (+ 2 2) ;; ==> 4 (display "Hello, world\n") ;; ==> Hello, world #t ;; We are running a top-level loop. ;; We can enter Scheme commands ;; as long as we like. But it's ;; not *the* top-level loop. Look: (e::stack-depth) ;; ==> 29 ;; The top-level loop we have created ;; is running as an infinite loop ;; Within the "real" top-level loop, ;; which is lurking on the stack, ;; set to resume on a moment's notice. ;; We can get back to the first one ;; either by making an error or by (e::reset) ;; ==> Top-level loop ... ;; Do we believe it? (e::stack-depth) ;; ==> 5 ;; Might be so ...
Type:
Procedure.
Operation:
Invoke the Unix "usleep" function on the thread of the Wraith Scheme application that is running the Wraith Scheme engine.
Rationale, Explanation, Excuses:
This procedure provides a convenient way for Wraith Scheme to stop execution for a while without wasting system resources in an idle loop.
The argument to "e::usleep" is the intended sleep time in microseconds, but the time wasted in setting up the call to Unix "usleep" and in recovering after waking up means that naps much shorter than 0.01 second are hard to achieve reliably.
Wraith Scheme will do no processing while asleep. The "Reset to Top-Level Loop" command will not work. (Actually, it will work eventually, but not till Wraith Scheme wakes up.) "Quit", and several of the commands that affect the appearance of the Wraith Scheme window, will work.
Arguments:
One integer, taken as the number of microseconds to sleep.
Side Effects:
None.
Returned Value:
#t
For Example:
(e::usleep 1000000) ;; Nothing happens ;; for about a second ... ;; ==> #t
Type:
Procedure.
Operation:
Return a string telling when the current version of Wraith Scheme was built.
Rationale, Explanation, Excuses:
Useful for version identification. This string is printed as part of the "banner" when Wraith Scheme starts.
Arguments:
None.
Side Effects:
None.
Returned Value:
#t
For Example:
(e::version) ;; ==> "Wraith Scheme Feb 14 2007 14:54:20"
Type:
Procedure.
Operation:
Write out the contents of the continuation.
Rationale, Explanation, Excuses:
I installed this procedure as a debugging aid. It writes out (in the sense of the Scheme procedure, "write") the current continuation.
There usually isn't much in the continuation.
Arguments:
None.
Side Effects:
None.
Returned Value:
#t
For Example:
;; In the top-level loop, the ;; continuation will be empty. (e::write-continuation) ;; ==> ()#t
Type:
Procedure.
Operation:
Write out the contents of the Wraith Scheme run-time stack.
Rationale, Explanation, Excuses:
I installed this procedure as a debugging aid. It writes out (in the sense of the Scheme procedure, "write") the current Wraith Scheme run-time stack.
The stack usually contains pointers to some rather large objects, such as the full environment list, so "e::write-stack" will usually produce lots of output.
Arguments:
None.
Side Effects:
None.
Returned Value:
#t
For Example:
(e::write-stack) ;; ==> ;; Lots of output.
Type:
Procedure.
Operation:
Establish a lock on its argument, such that any Wraith Scheme procedure except c::release-block, that attempts to return or modify that argument, will loop without doing so until the lock has been released (by c::release-block).
This procedure is one of four that are particularly useful in dealing with critical sections that involve Wraith Scheme objects, notably symbols. The four procedures in question are
These procedures should be used with great caution: They are individually and collectively calamitous, for several reasons.
Technical Note: The problem indicated is a deadlock due to an attempt to access a locked object.
Rationale, Explanation, Excuses:
Fundamental low-level primitive for parallel programming.
Arguments:
One Wraith Scheme object which is stored in Wraith Scheme main memory. (The procedure will report an error if called with an inappropriate argument.)
Side Effects:
Locks its argument in such a way that any Wraith Scheme procedure except c::release-block, that attempts to return or modify that argument, will loop without doing so until the lock has been released (by c::release-block).
Returned Value:
The argument, as locked.
Failure to call c::release-block with the returned value will leave the original argument to "c::block" locked, and any subsequent attempt to use or modify that argument will cause a deadlock.
For Example:
(c::block 'foo) ;; ==> Something you should not try to print.
For a more realistic example, suppose you had some data that in principle might be modified by any of several different Wraith Scheme processes, and the nature of the data and modification was such that two Wraith Scheme processes could get in each other's way if they tried to modify the data at the same time. Thus the data might be a global counter, whose value was supposed to be incremented by various processes at various times, and it might be important that the total number of increments be recorded accurately.
Here is a way to do that using "c::block" and "c::release-block". First, make a list whose car is the actual counter -- initialized to zero -- and whose cadr is arbitrary: That is, the list must *have* a cadr -- we couldn't just initialize it to (list 0) -- but we don't care what value its cadr is.
(define the-counter-wrapper (list 0 42))
Now write an increment function that locks the cadr of our list -- note that we neither know nor care what the value of the cadr is, all we care is that it gets locked -- then modifies the car of the list and finally releases the lock.
(define increment-the-counter () (let* ((the-block (c::block (cadr the-counter-wrapper))) (the-current-value (car the-counter-wrapper)) ) (set-car! the-counter-wrapper (+ the-current-value 1)) (c::release-block the-block)))
There is an implicit assumption here, that all the Wraith Scheme processes are cooperating. That is presumably the case, because they are all doing what you, the user, told them to do, and you will presumably respect the convention of paying attention to the block. Yet there is nothing to prevent you from evaluating
(set-car! the-counter-wrapper (+ (car the-counter-wrapper) 1))
any time you wish: Wraith Scheme does not try to keep you from shooting yourself in the foot, it only provides tools with which you may endeavor to protect yourself, if you should choose to do so.
Type:
Procedure.
Operation:
Test whether the "Compile Defines" menu item is set.
Rationale, Explanation, Excuses:
Provided on the general principle that it is desirable to make internal program state available at the Scheme-language level.
Arguments:
None.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the "Compile Defines" menu item is set; that is, if Wraith Scheme is automatically compiling definitions. Otherwise, returns #f.
For Example:
;; With the "Compile Defines" menu item set: (c::compiling?) ;; ==> #t
Type:
Procedure.
Operation:
Like "define" with only the simple, two-argument syntax, and no automatic compilation.
Rationale, Explanation, Excuses:
The real "define" is a macro; "c::define" is one of the primitives from which it is built.
Wraith Scheme reports an error when "c::define" is used to attempt to redefine a "permanent" symbol.
Arguments:
Two: The first a symbol, the second any Scheme object.
Side Effects:
Causes the second argument to become the value or binding of the first, overwriting any previous value or binding.
Returned Value:
A symbol: Returns the first argument.
For Example:
(c::define a 42) ;; ==> a a ;; ==> 42
Type:
Procedure.
Operation:
Disables output from Wraith Scheme to the Wraith Scheme window, except for echoing of text entered into the Wraith Scheme Input Panel. Also see c::enable-window-output and c::window-output-enabled?.
Rationale, Explanation, Excuses:
Window output is slow.
Arguments:
None.
Side Effects:
Disables window output.
Returned Value:
#t
For Example:
(c::disable-window-output) ;; ==> #t, and window output is disabled.
Type:
Procedure.
Operation:
Test the Wraith Scheme mechanism for reporting fatal errors by crashing Wraith Scheme.
Rationale, Explanation, Excuses:
For further development of Wraith Scheme, I needed an easy mechanism to verify that the Wraith Scheme mechanism for reporting fatal errors was working correctly.
Arguments:
None.
Side Effects:
WRAITH SCHEME CRASHES.
Returned Value:
Does not apply.
For Example:
(c::down-in-flames!!!) ;; ==> <Wraith Scheme crashes> ;; Wasn't that fun?
Type:
Procedure.
Operation:
Enables output from Wraith Scheme to the Wraith Scheme window. Also see c::disable-window-output and c::window-output-enabled?.
Rationale, Explanation, Excuses:
Window output is slow.
Arguments:
None.
Side Effects:
Enables window output.
Returned Value:
#t
For Example:
(c::enable-window-output) ;; ==> #t, and window output is enabled.
Type:
Procedure.
Operation:
Get the entire current environment.
Rationale, Explanation, Excuses:
Provided for development and testing, described herein on the general principle that it is desirable to make internal program state available at the Scheme-language level.
The fundamental logical construct in a Wraith Scheme environment is a pair whose car is a value or a binding -- any Scheme object -- and whose cdr is a variable which has that value or binding. The top-level environment is hashed: It is a vector, each of whose elements is a list of value/symbol pairs. All other environments are lists of value/symbol pairs.
Arguments:
None.
Side Effects:
None.
Returned Value:
A list: Returns a list of all the environments visible from the lexical scope in which "c::environment" was called, that list being sorted in order of lexical nesting, so that more closely-nested environments occur earlier in the list.
For Example:
;; Called at top level: (c::environment) ;; ==> ;; Lots of printout. The ;; top-level environment is ;; large. (let ((x 3)) (c::environment)) ;; ==> (((3 . x)) ;; followed by the large printout for the ;; top-level environment. ;; As I write these words, the full result of (let ((x 3)) (c::environment)) ;; starts out this way (with reformatting to fit ;; here neatly): (((3 . x)) #(() ((#<Built-in procedure "cdddr"> . cdddr) (#<Built-in procedure "string-ref"> . string-ref)) () ((#<Interpreted lambda expression> . e::error)) ...
Type:
Procedure.
Operation:
Return the hash value of the string, as used by Wraith Scheme in deciding to which hash bucket of the top-level environment a symbol identified by the string should belong.
Rationale, Explanation, Excuses:
Provided on the general principle that it is desirable to make internal program mechanisms available at the Scheme-language level.
The hash algorithm presently used returns an integer in the range [0 .. 4095]. That range may change in the future.
Arguments:
One string.
Side Effects:
None.
Returned Value:
An integer: Returns the hash value of the string, as obtained by the algorithm described above.
For Example:
(c::hash-string "abcd") ;; ==> 138
Type:
Procedure.
Operation:
Returns the content of the input queue of the kitten given, as a list.
Rationale, Explanation, Excuses:
Provided mostly for testing the input queue implementation.
Arguments:
An integer: The argument must be no less than zero and no greater than the number of kittens last launched in parallel.
Side Effects:
None.
Returned Value:
A boolean:
For Example:
(c::kitten-input-queue 1) ;; ==> ()
Type:
Procedure.
Operation:
Returns a boolean telling whether the input queue for the given kitten is empty.
Rationale, Explanation, Excuses:
Provided mostly for testing the input queue implementation.
Arguments:
An integer: The argument must be no less than zero and no greater than the number of kittens last launched in parallel.
Side Effects:
None.
Returned Value:
A boolean: Returns #t if, and only if, the input queue for the given kitten is empty. Otherwise, returns #f.
For Example:
(c::kitten-queue-empty? 1) ;; ==> #t
Type:
Procedure.
Operation:
Empties the input queue of the kitten indicated.
Rationale, Explanation, Excuses:
Provided mostly for testing the input queue implementation.
Arguments:
An integer: The argument must be no less than zero and no greater than the number of kittens last launched in parallel.
Side Effects:
Empties the input queue of the kitten indicated.
Returned Value:
#t
For Example:
(c::kitten-purge-queue 1) ;; ==> #t
Type:
Procedure.
Operation:
Resets the kitten indicated.
Rationale, Explanation, Excuses:
Provided for process control and error recovery.
Arguments:
An integer: The argument must be no less than zero and no greater than the number of kittens last launched in parallel.
Side Effects:
Resets the kitten indicated.
Returned Value:
#t
For Example:
(c::kitten-reset 3) ;; ==> #t, and resets kitten 3.
Type:
Procedure.
Operation:
Provide a way to debug circumstances in which a kitten is trying to lock access to a Wraith Scheme object that is already locked, and has remained locked for a worrisome amount of time. The "worrisome amount of time" is guaranteed to be at least 0.03 seconds, but may be longer, depending on the speed of your Macintosh and on what else -- other than Wraith Scheme -- it is doing.
This procedure does not apply to locks of bins of the hash tables used to control access to Wraith Scheme's oblist and top-level environment.
If the kitten whose kitten number is passed to the procedure has been trying to obtain access to a locked object for more than the "worrisome amount of time" just described, this procedure will cause it to give up trying, print out some information about what it was attempting to lock, and reset to top-level.
This procedure may be applied to any kitten and called from any kitten.
This procedure is dangerous, because release of deadlocks may cause Wraith Scheme to crash or hang.
Rationale, Explanation, Excuses:
For use in debugging.
Arguments:
An integer: The kitten number of the kitten on on which deadlocks are to be allowed to time out.
Side Effects:
Quite possibly, Wraith Scheme will crash. With luck, Wraith Scheme will end up in a state in which you can investigate what was causing any mysterious possible deadlocks that may have been giving you cause for concern.
Returned Value:
#t
For Example:
(c::let-deadlock-time-out 0) ;; ==> #t ;; And kitten 0 may print some information about ;; any deadlock it may have been dealing with, and ;; then reset. Here is a sample of this output: Atomic test-and-set timed out at memory address 0x15e70f04: 13002079-00000004. Called by kitten 0, location 2, blocked by kitten 0, location 19. (values may have changed between timeout and report) (4 5) Problem: Failed to lock in "car". (Resetting) Top-level loop ...
Type:
Procedure.
Operation:
Construct a Wraith Scheme string containing a number formatted using a C (or C++) format string.
Rationale, Explanation, Excuses:
Standard R5 Scheme procedures offer little immediate capability for formatting numbers in many ways.
Arguments:
Two: The first a number, the second a string.
Side Effects:
None, but ...
WARNING!! "c::number->string-with-c-format" does no checking whatsoever of whether its "string" argument is appropriate for use as a C++ "format" string. Thus there is a noteworthy probability that ill-considered use of this procedure may cause Wraith Scheme to crash. This procedure is perhaps best used as a primitive for procedures which are themselves well tested and debugged.
Returned Value:
A string: Returns a string containing the formatted number. The number is first formatted as
snprintf( scratch, 256, <your number coerced to double>, <your format string>)
Then the scratch buffer is used to construct a newly-allocated Wraith Scheme string, so there is no need to copy anything to use the new string, and no concern about overwriting it.
For Example:
(c::number->string-with-c-format 1 "%.3f") ;; ==> "1.000" (c::number->string-with-c-format 29.95 "For the low, low price of only $%.2f!!") ;; ==> "For the low, low price of only $29.95!!"
Type:
Procedure.
Operation:
Release any lock on its argument. (The procedure does not test to see whether its argument was originally locked.) See c::block and e::block-symbol-binding.
This procedure is one of four that are particularly useful in dealing with critical sections that involve Wraith Scheme objects, notably symbols. The four procedures in question are
These procedures should be used with great caution: They are individually and collectively calamitous, for several reasons.
Technical Note: The problem indicated is a deadlock due to an attempt to access a locked object.
Rationale, Explanation, Excuses:
Fundamental low-level primitive for parallel programming.
Arguments:
One Wraith Scheme object which is stored in Wraith Scheme main memory, and which is presumably locked to begin with. This procedure does not type-check its argument.
Side Effects:
Releases any lock in effect on its argument.
Returned Value:
#t
For Example:
(c::release-block 3) ;; ==> (Wraith Scheme crashes)
For a more realistic example, suppose you had some data that in principle might be modified by any of several different Wraith Scheme processes, and the nature of the data and modification was such that two Wraith Scheme processes could get in each other's way if they tried to modify the data at the same time. Thus the data might be a global counter, whose value was supposed to be incremented by various processes at various times, and it might be important that the total number of increments be recorded accurately.
Here is a way to do that using "c::block" and "c::release-block". First, make a list whose car is the actual counter -- initialized to zero -- and whose cadr is arbitrary: That is, the list must *have* a cadr -- we couldn't just initialize it to (list 0) -- but we don't care what value its cadr is.
(define the-counter-wrapper (list 0 42))
Now write an increment function that locks the cadr of our list -- note that we neither know nor care what the value of the cadr is, all we care is that it gets locked -- then modifies the car of the list and finally releases the lock.
(define increment-the-counter () (let* ((the-block (c::block (cadr the-counter-wrapper))) (the-current-value (car the-counter-wrapper)) ) (set-car! the-counter-wrapper (+ the-current-value 1)) (c::release-block the-block)))
There is an implicit assumption here, that all the Wraith Scheme processes are cooperating. That is presumably the case, because they are all doing what you, the user, told them to do, and you will presumably respect the convention of paying attention to the block. Yet there is nothing to prevent you from evaluating
(set-car! the-counter-wrapper (+ (car the-counter-wrapper) 1))
any time you wish: Wraith Scheme does not try to keep you from shooting yourself in the foot, it only provides tools with which you may endeavor to protect yourself, if you should choose to do so.
Type:
Procedure.
Operation:
Show a low-level description of every locked object in Scheme main memory, and of the state of locking of bins of the hash tables used to control access to Wraith Scheme's oblist and top-level environment, and then release every lock found.
Rationale, Explanation, Excuses:
For use in debugging.
Arguments:
None.
Side Effects:
Quite possibly, Wraith Scheme will crash. With luck, Wraith Scheme will end up in a state in which you can investigate what was causing any mysterious locks that may have been giving you cause for concern.
Returned Value:
#t
For Example:
(c::release-locks) ;; ==> ;; e.g., *** Memory space descriptor at 153cc000, 364760 of 11534336 (hex b00000) bytes used. space --> 153cc018, free -> 15e72f40, lowFree -> 153cc018, end -> 15ecc018, inUse -> 1 15e92868 : 13012041-15e83248: String -- Cdr Next 15ec2630 : 13002041-15e80674: String -- Cdr Next No ObList hash bins locked. No TLE hash bins locked. Releasing locks ... 15e92868 : 13012041-15e83248: String -- Cdr Next ... was locked, unlocks to: 15e92868 : 00002001-15e83248: String -- Cdr Next 15ec2630 : 13002041-15e80674: String -- Cdr Next ... was locked, unlocks to: 15ec2630 : 00002001-15e80674: String -- Cdr Next No ObList hash bins locked. No TLE hash bins locked. #t
Type:
Procedure.
Operation:
Change the value of a symbol that has been previously subject to the procedure e::block-symbol-binding (which see). The procedure "c::set-blocked-binding!" should not be used for any other purpose.
This procedure is one of four that are particularly useful in dealing with critical sections that involve Wraith Scheme objects, notably symbols. The four procedures in question are
These procedures should be used with great caution: They are individually and collectively calamitous, for several reasons.
Technical Note: The problem indicated is a deadlock due to an attempt to access a locked object.
Rationale, Explanation, Excuses:
Useful low-level primitive for parallel programming.
Arguments:
Two arguments. The first must be a lock received from e::block-symbol-binding (which see). The second may be any Scheme object. This procedure does not type-check either of its arguments.
Side Effects:
Change the value of the variable whose blocked variable-binding is the first argument, to the second argument.
Returned Value:
#t
For Example:
(define a 0) (define (blocked-increment-of-a) (let* ((the-block-list (e::block-symbol-binding 'a)) (the-value (car the-block-list)) (the-lock (cadr the-block-list)) ) (c::set-blocked-binding! the-lock (+ the-value 1)) (c::release-block the-lock)))
Type:
Procedure.
Operation:
Find the value or binding of a symbol, if there is one.
Rationale, Explanation, Excuses:
This procedure was useful for the compiler; it is in essence a mini "eval" that works only for symbols. It obtains the value or binding of the symbol in the lexical scope where "c::symeval" was called.
Arguments:
One symbol.
Side Effects:
None.
Returned Value:
Any Scheme object: Returns the value or binding or the argument in the current lexical scope. Reports an error if the argument has no value or binding in the current lexical scope.
For Example:
(c::symeval 'cons) ;; ==> #<Built-in procedure "cons"> (c::symeval 'not-bound) ;; ==> ;; error message: not-bound Problem: No lexically visible binding of this symbol. (Resetting) Top-level loop ... (define not-bound 42) ;; ==> not-bound (c::symeval 'not-bound) ;; ==> 42
Type:
Procedure.
Operation:
Check whether window output is enabled or not. Also see c::disable-window-output, and c::enable-window-output.
Rationale, Explanation, Excuses:
Window output is slow.
Arguments:
None.
Side Effects:
None
Returned Value:
A boolean: Returns #t if, and only if, window output is enabled. Otherwise, returns #f.
For Example:
(c::window-output-enabled?) ;; ==> #t or #f, depending on whether window output is enabled.
This term refers to a style of programming, or a type of programming language, that emphasizes the application of functions to arguments, and avoids changes of state and mutable data. An applicative program is one which reaches a result by applying successive functions to its data. "Applicative programming" and "functional programming" are very nearly synonyms.
Scheme is not quite an applicative language, but insofar as only a few Scheme procedures and special forms change state -- those whose identifiers end with a "!" -- it is relatively easy to write applicative programs in Scheme.
The term "binding" is Lisp jargon referring to some, but not all, kinds of assignments of a value to a variable. The distinction being made is whether the actual data are stored somewhere where another process or program can get at them, and change them, without actually having access to the variable in question. When the data are of that nature, the variable is said to be bound to the data. The word is perhaps intended to indicate that the data and the variable are tied together, so that when the data are changed by whatever means, the value associated with the variable necessarily changes as well.
If you are familiar with the concept of a pointer, or a memory reference, as used in other programming languages, then the essence of binding is easy to explain: When a variable is bound to data, the actual value of the variable is a pointer to the data. Unfortunately, there is more to it than that.
In Lisp systems, the means whereby another process or program can get at the data are understood to be normal Lisp operations; we are not considering the possibility of someone going in with a debugger or a monitor. Thus to speak of a binding in a Lisp system, the memory reference or pointer involved must point into the main memory of the Lisp system itself, and the Lisp system must provide a standard way to follow the pointer and change the data to which it points.
For example, in Wraith Scheme -- as is typical of Lisp systems -- a pair is a data object in main memory; when you let a variable stand for a pair, via a command like
(define my-pair (cons 1 2))
then what in most other computer languages would be called the "value" of "my-pair" is a pointer into main memory, to the place where the newly-allocated pair is located. (To be very precise, in Wraith Scheme the value of "my-pair" is a tagged aval -- which see -- whose tag bits identify the value as a pointer to a pair, and whose 32-bit field is the actual pointer in question.)
Scheme provides built-in primitives to alter a pair; they are "set-car!" and "set-cdr!". Thus, here is an example in which some "other program" alters data associated with a variable by binding:
;; Make a cons cell and bind it to a variable: (define my-pair (cons 1 2)) ;; ==> my-pair my-pair ;; ==> (1 . 2) ;; Make a copy of the binding; that is, of the pointer: (define another-pair my-pair) ;; ==> another-pair another-pair ;; ==> (1 . 2) ;; Change "another-pair" -- actually, change the ;; data pointed to: (set-car! another-pair 42) ;; ==> #t another-pair ;; ==> (42 . 2) ;; But "my-pair" has been changed as well, since ;; its pointer points to the data we just changed: my-pair ;; ==> (42 . 2)
Just which kinds of objects are associated with variables by bindings and which are not will vary from Lisp system to Lisp system. In Wraith Scheme, objects which require bindings include pairs (and therefore all non-empty lists), strings, and vectors; objects which do not require bindings include booleans, characters, the empty list, numbers, ports, symbols and procedures.
That list is a little fuzzy, because Wraith Scheme has some non-standard procedures, like "e::set-tag!", which allow you to cheat, and modify the structure of things even when there are no standard Scheme procedures to do so. (For example, you can use "e::set-tag!" to "change" lots of objects into pairs, then go in with "set-car!" and "set-cdr!" to do what you will. Just be careful not to crash the system, and note that not everything can be "changed" to a pair without immediate ill effect.)
Note that there are plenty of cases when the actual value of a variable is a pointer to something, in which most Lisp users would not speak of a binding, because there are no procedures to follow the pointer and alter the data. For example, 64-bit flonums are too big to fit in the 32-bit field of a Wraith Scheme tagged aval, so they are stored in separately-allocated bits of main memory, and what goes into the 32-bit field of the tagged aval is a pointer thereto. Yet since Wraith Scheme does not provide any procedure like "e::set-flonum-bit" (or whatever), there is no way to dereference the pointer and change the data without a lot of cheating. So if you
(define my-flonum (sqrt 42)) ;; ==> 6.4807406984078604
no standard Scheme procedure can change the value without having explicit access to the variable "my-flonum".
Much written material about Lisps blurs the distinction between binding and simple assignment of values to variables. I tend to use the word "binding" to refer to both, if only to keep reminding you -- and myself -- that there is something complicated going on.
Jargon for operations whose intent is to affect specific bits of a datum, often in parallel. For example, a bitwise and of two 32-bit words returns a word whose least-significant bit is 1 if and only if the least significant bits of both operands are 1, whose next-to-least-significant bit is 1 if and only if the next-to-least significant bits of both operands are 1, and so on.
Wraith Scheme provides several bit-wise operations which act on numbers stored as 32-bit fixnums.
Semi-official name given to a simple animal-like icon used in one of the "symbol" fonts provided with very early Macintoshes. No one seemed to be quite sure whether the creature depicted was dog or a cow, and after a while, a consensus emerged that Clarus was really -- or perhaps un-really -- a hybrid species.
Clarus was reported to have several vocalizations: The most common was "Moof!&trade" (and I have never been quite sure how to pronounce the "&trade"), but when very agitated, Clarus would give voice to an enthusiastic "Boo-woo! Boo-woo!"
Clarus was a source of much entertainment and good fellowship to Macintosh programmers in the early days, and I didn't want him -- or is it her? -- to be forgotten.
The resemblance of the name "Clarus" to the name of a software company once spun off by Apple is, of course, mere coincidence.
Yes, both "DogCow" and "Moof" are trademarks of Apple Computer Corporation.
A widely-known and well-standardized Lisp dialect, that has been implemented on many platforms. See Guy L. Steele Jr.'s Common Lisp (Digital Press, 1984).
Common Lisp has a very thick manual. Scheme has a rather thin one.
A compiler is a computer program that translates instructions for the computer that are written in a form that is easy for humans to read and use -- called "source code", into instructions in a form that are easy for the computer to read and use.
Many compilers translate source code into "machine language", or "binary" -- the native language, so to speak, of the computer on which the compiled source code will be used. The compiler used by Wraith Scheme does not undertake such a complete transformation of the source code. what it does is perform as much as possible of the time-consuming work of looking up the values or bindings of variables, at the time of compilation, and store the result in the compiled code. For symbols whose values or bindings that have been declared "permanent", the compiler considers it safe to store the actual value or binding in the compiled code; for others, it stores shorthand information about where in the environment to look for whatever binding actually obtains at run-time.
If you make a "permanent" symbol un-permanent, and then change its value or binding, you must recompile any procedures that use that symbol in order for the compiled code to reflect the new value or binding.
Lisp jargon for "allocating memory". The term seems to have originated via guilt-by-association from the Lisp (and Scheme) primitive operation "cons", which does indeed allocate memory. For a program to cons excessively is generally considered bad, but is sometimes unavoidable.
The term "continuation" has two meanings in Lisp jargon.
Continuation -- First Meaning:
To begin with "continuation" may refer, somewhat vaguely, to the entire future of the world, or at least that part of it that affects the result or side effects of a calculation in progress. In this sense, the Scheme function "call-with-current-continuation" provides time travel, at least metaphorically, in that it is supposed to package up the current state of Scheme for future use, with the intent that any Scheme procedure or program using the package will achieve the same result as if it had run at the moment that "call-with-current-continuation" was itself called.
It can't really do that, for several reasons:
Therefore, Scheme implementations are perhaps more likely to package up a pointer to any large, identifiable portion of Scheme memory that is part of the continuation. That means that if anything happens to change the memory pointed to between the time "call-with-current-continuation" is called, and the time the packaged continuation is used, the use will "see" the modified memory.
What Wraith Scheme packages up as a continuation, for "call-with-current-continuation", is a complete copy of the Wraith Scheme call stack. This copy is not a "deep" copy, in that many things on the call stack are pointers, and the copy merely duplicates the pointers rather than copying the things they point to. Among the objects pointed to are various continuations in the second sense of the term, described immediately below, and various environments. Thus if anything alters either those continuations or those environments before the packaged "continuation" is used, the use will reflect those alterations.
Continuation -- Second Meaning:
The second meaning of "continuation" is more specific: It then refers to a list of the instructions of the currently-active Scheme procedure that are yet to be accomplished before the procedure returns. That list is often very short, even for a long or complicated procedure, for the procedure may gain its length and complexity by calling other procedures of by calling itself recursively.
In many register-level models of processors designed to implement Lisp-like languages, there is a specific register -- often called the "C register" -- which contains a pointer to the "continuation" in the present sense. The C register is analogous to the program counter of a more conventional processor, though at a rather different level of logical abstraction: A conventional program counter is an index into a sequence of machine-language instructions, whereas a "C register" points to a list of individual Lisp or Scheme expressions that may well be readable, parseable source code -- some portion of the body of a function or lambda expression.
Wraith Scheme is based on a register-level model of a Lisp processor called an "SECD machine", and does use a "C register" of this kind. For further discussion of SECD machines, see, for example, Peter Henderson's Functional Programming Application and Implementation (Prentice-Hall, 1980).
The term "environment" has several meanings in the context of Lisp and Scheme.
Environment -- First Meaning:
Informally, "environment" refers to the context in which an expression is evaluated, most notably to the values or bindings of symbols used in the evaluation.
Environment -- Second Meaning:
Rather more formally, there is not one environment but a hierarchy of them, in order of lexical scope, from the one most closely enclosing the program location where the "environment" is referenced, out through successively less-enclosing environments, to the top-level environment, which might also be called the global environment or the interaction environment, which contains all all non-Scheme-report-environment and non-null-environment bindings "visible" in the top-level loop of Wraith Scheme, then to the Scheme report environment, which contains all non-null-environment bindings required by the R5 report or listed therein as optional and provided by Wraith Scheme, then to the null environment, which is supposed to contain only bindings for the syntactic keywords of Scheme but which contains a few more in the case of Wraith Scheme.
The hierarchy of environments might make more sense if you consider it in the opposite direction. The null environment contains the syntactic keywords of Scheme, plus a few extras for Wraith Scheme macros that implement some of the syntactic keywords. The Scheme report environment adds everything else from the R5 report that Wraith Scheme implements. The interaction environment adds Wraith Scheme's enhancements to R5 Scheme, plus whatever other bindings the user has chosen to put there. The environments of executing lambda expressions add local variables accessible from within those expressions.
When a Scheme implementation looks up the value or binding of a symbol, it starts looking in the most closely enclosing environment, then works outward through successive environments until it finds a value or binding; it is probably an error if there is none to be found.
The second meaning of "environment" is the entire hierarchy just described.
Environment -- Third Meaning:
The third meaning of "environment" is any of the individual environments in the hierarchy just described.
By way of illustration, here is an example in which there are three environments (in the third sense) in the hierarchy. We are going to print out (list a b c) in three different environments, in which the values or bindings of those variables are not all the same. Each time we print the list, Wraith Scheme will use the binding of each variable that exists in the closest lexical scope to the place where the print occurs.
;; The first three definitions result in bindings ;; in the top-level environment. (define a 'a-from-top-level) ;; ==> a (define b 'b-from-top-level) ;; ==> b (define c 'c-from-top-level) ;; ==> c (begin (let ((a 'a-from-let) ;; These bindings are in an (b 'b-from-let)) ;; environment created by the let. ;; Within the let, they override ;; the top-level bindings to a and b. ((lambda (a) ;; The lambda's formal argument ;; creates a new instance of variable ;; a, in the lambda's environment ;; environment. Within the lambda, ;; that instance's value or binding ;; will override the values and ; bindings of a in the let and at ;; top level. (set! a 'a-from-lambda) ;; Change a in the lambda. (display "In the lambda: ") ;; Print some output. (display (list a b c)) (newline) ) a) ;; Pass the value of a as seen by ;; the let, to the lambda, which ;; will bind that value to its own ;; "a", and then change it! (display "In the let: ") ;; Print some output. (display (list a b c)) (newline) ) (display "In the begin: ") ;; Print some output. (display (list a b c)) (newline) ) ;; ==> In the lambda: (a-from-lambda b-from-let c-from-top-level) In the let: (a-from-let b-from-let c-from-top-level) In the begin: (a-from-top-level b-from-top-level c-from-top-level) #t
The term "environment list" refers to the hierarchy of environments described as the second meaning of "environment" in the discussion above. Wraith Scheme represents that hierarchy as a list, though there is no formal requirement to use such a representation.
Evaluation is the act of performing all necessary Scheme computations to determine what value a Scheme expression represents; loosely, it is the act of running a program, or a portion thereof.
All Scheme systems evaluate. Yet there has been a substantial issue in the evolution of the Scheme programming language, about how and whether a Scheme system should evaluate an expression created by the user while a program is running, as opposed to one that was written down in source code beforehand.
Since Scheme programs have the same syntactic form as any other kind of data, it is quite easy to for a program build up a chunk of code as it runs, and then to evaluate that code. For example:
(define my-expression '(+ 2 2)) ;; ==> my-expression my-expression ;; ==> (+ 2 2)
The question is, when -- if ever -- is Scheme allowed to turn "my-expression" into "4".
If all expressions to be evaluated were as simple as "my-expression", there probably wouldn't have been much debate. But there is a possibility of great confusion when the expression contains references to variables that have different values or bindings in different environments. Suppose we had built up "my-expression" to be a simple list, perhaps
my-expression ;; ==> (a b c)
If "my-expression" is going to be evaluated, Scheme must look up the values of the variables "a", "b", and "c", but those variables may have different values or bindings in different environments. Which environment, or environments, should Scheme use when it looks up the values or bindings of those symbols?
Here is an example, based on the example given under the discussion of "Environment", that might illustrate the problem. In it, we define variables "a", "b", and "c", with different values in different environments, and construct some lists using those variable names.
(define a 'a-from-top-level) ;; ==> a (define b 'b-from-top-level) ;; ==> b (define c 'c-from-top-level) ;; ==> c ;; Start with empty lists -- set! their ;; values later ... (define top-level-list '()) ;; ==> top-level-list (define let-list '()) ;; ==> let-list (define lambda-list '()) ;; ==> lambda-list (let ((a 'a-from-let) (b 'b-from-let)) ((lambda (a) (set! a 'a-from-lambda) (set! lambda-list '(list a b c)) ) a) (set! let-list '(list a b c)) ) ;; ==> #t (set! top-level-list '(list a b c)) ;; ==> #t
So far, so good, but what we have done is deceptive. The three lists, "top-level-list", "let-list", and "lambda-list", are all just lists of symbols:
top-level-list ;; ==> (list a b c) let-list ;; ==> (list a b c) lambda-list ;; ==> (list a b c)
There is nothing in the lists per se to show that "a", "b" or "c" have particular values or bindings. There isn't even anything to show that "list" names a procedure -- though we know it does. The example is constructed to give the impression that "lambda-list" somehow captures the values of "a", "b" and "c" that obtained within the lambda expression, but that's not so: The symbols in the three lists do not have specific values associated with them.
Therefore, if we were somehow to "evaluate" the three lists, the evaluation would "get" whatever values of "a", "b", and "c" obtained in the environment in which the evaluation took place, and those values wouldn't necessarily be the values that obtained in the place where the lists were constructed.
If you think that's confusing, it would not be hard to construct an example that built up (list a b c) by splicing in the "a", "b", and "c" in different environments. The list would be passed around from environment to environment, with different things being added in different places. Yet it would still end up just a list of symbols, with no special values associated with them.
The R5 version of the Scheme standard has defined a somewhat complicated "eval", which allows some choice over which environment is used. Wraith Scheme provides an implementation of that "eval".
Wraith Scheme also provides is the procedure "e::cons-with-continuation", which evaluates its argument in the environment where "e::cons-with-continuation" is called. Many Lisps have an "eval" function which does exactly that. Let's use "e::cons-with-continuation" like eval, and try it out on our lists:
(define eval e::cons-with-continuation) ;; ==> eval (eval top-level-list) ;; ==> (a-from-top-level b-from-top-level c-from-top-level) (eval let-list) ;; ==> (a-from-top-level b-from-top-level c-from-top-level) (eval lambda-list) ;; ==> (a-from-top-level b-from-top-level c-from-top-level)
So indeed, each of the three lists evaluates using the bindings to "a", "b" and "c" that obtained in the top level.
This term refers to a style of programming, or a type of programming language, that envisions computation as a series of applications of mathematical functions to data, and avoids dealing directly with changes of state and mutable data. An applicative program is one which reaches a result by applying successive functions to its data. "Applicative programming" and "functional programming" are very nearly synonyms.
Scheme is not quite a functional language, but insofar as only a few Scheme procedures and special forms change state -- those whose identifiers end with a "!" -- it is relatively easy to do functional programming in Scheme.
Things in the main memory of a Lisp system, which are provably not usable in future operations of that system, are called "garbage", in the sense of waste material that takes up space. The storage space containing them may in principle be reclaimed for other uses.
The proof that an item is not usable in future operations of a Lisp system might, for example, be a demonstration that no sequence of pointer dereferences starting from pointers "officially" known to the Lisp system, can reach the item. The canonical way to do that is to start with the pointers officially known and mark everything reachable from them. Any part of main memory that is left over, is garbage.
The process of identifying garbage and reclaiming its space for subsequent reuse is called "garbage collection".
Wraith Scheme uses two main memory spaces -- one at a time -- and performs garbage collection by
The term "gensym" is Unix slang for "generate symbol". Wraith Scheme, like many other languages, has a procedure -- "e::gensym" -- for creating new symbols that are guaranteed not to have any value or binding at the time of creation.
The essence of any "gensym" procedure is likely the ability to generate new symbols randomly, coupled with the ability to test each symbol so created, to make sure that the random process has not inadvertently created a symbol that is already in use.
An "inf" is a special value of a flonum used to indicate that a calculation has produced a number too large to represent. The intended value of the calculation might be a mathematical infinity, or it might not.
One of my personal rules for software engineering is "Never create a data structure without creating a procedure that can describe it in human-readable form". For that reason, Wraith Scheme is full of procedures that describe its internal structure at a more intimate level than required by the Scheme standard. The procedure "e::inspect" is probably the most widely useful of these -- it will tell something useful about any Scheme object. There are other procedures for Scheme objects that do not have values, and so cannot be used as arguments to "e::inspect". Scan this document for words like "inspect", "describe", and "show", to find them.
Scheme allows definitions -- using define -- not only at top level, but also at particular positions within procedures and special forms: Any number of "define" statements may occur at the beginning of the body of a begin, lambda, let, let*, letrec, let-syntax, letrec-syntax, or a define.
Quantities so defined have lexical scope local to the expression where the definition occurs, except that quantities defined at the beginning of a begin have the same lexical scope as the begin itself.
When running several instances of Wraith Scheme cooperatively in parallel, all processes which are not the MomCat -- that is, all processes whose kitten number is greater than zero -- are called kittens.
Computer programs often let a variable for represent different things in different places. The variable "x" may stand for "3" in one part of the code, and for "(list a b c)" in another.
The scope of a value or binding of a variable is the range of the program within which it is visible; that is, it is the range within which a reference to the variable name will obtain that value or binding instead of some other one.
To say that a scope is "lexical" is to say that you can tell what the scope is by looking at the program source code without worrying about control flow: Even if you don't know about calls, jumps, if/else branches, and "call-with-current-continuation", you can tell what is going on just by reading the code.
In Scheme, certain expressions define a source-code domain within which a variable value or binding may be created and used without being visible, or perhaps the word should be "accessible", outside the domain. Such bindings may be said to be local to the domain. These expressions include "let", "let*", "letrec", and "lambda". The first three have particular syntax for creating values and bindings for new symbols. Lambda allows new values and bindings only to the symbols which are its formal parameters. New symbols may also be created and defined at top-level -- outside any local domain of the kind just mentioned -- using "define".
With each such domain is associated an environment -- in the third sense of the term as defined in this glossary -- which contains all the symbols that exist solely in that domain, together with their values or bindings.
The point of lexical scoping is that domains may be nested. In particular, any "let", "let*", "letrec" or "lambda" is necessarily nested in some other domain, if only the top-level one. The same symbol may have different values or bindings in any number of nested domains. When Scheme looks up the value or binding of a variable, it obtains the one in the most closely enclosing nested domain in which the variable has a value or binding. That's how lexical scoping works.
To expedite variable lookup, the environments of the various domains are represented in a way that makes it easy to go through them in order from most closely-enclosing to least closely-enclosing. That representation is typically a list.
For example, consider the following, just as source code -- perhaps as text to be cut-and-pasted into Wraith Scheme at top level.
;; "a", "b", and "c" have bindings in the top-level ;; domain, which includes this code and lots more. (define a 'a-from-top-level) ;; ==> a (define b 'b-from-top-level) ;; ==> b (define c 'c-from-top-level) ;; ==> c ;; Here come two local domains: There is a "let" ;; nested within the top-level domain, and a "lambda" ;; nested within the "let". (let ((a 'a-from-let) ;; Here are bindings of "a " and (b 'b-from-let)) ;; "b" that are local to the "let". ((lambda (a) ;; Lambda uses the symbol "a" in ;; its own domain ... (set! a 'a-from-lambda) ) 3) ;; Lambda has no way to initialize ;; its "a" other than by the parameter ;; passed during a procedure call. )
MacLisp was one of the first widely used Lisps, and in this case, the initial syllable "Mac" does not indicate a product designed for use on the Apple Macintosh: MacLisp originated in the late 1960s and early 1970s in MIT's "Project MAC". Unfortunately, no one seems to remember for sure what the "MAC" in "Project MAC" did stand for.
MacLisp originally ran on various computers produced by Digital Equipment Corporation. It was the first Lisp that I myself encountered, at a time in the early 1980s when I was working for a company that had bought a DEC-20 and didn't know what to do with it: In essence, I had a mainframe computer for personal use, via a terminal on my desktop. I only knew one computer language at the time -- 1966 Fortran -- and I decided to learn another one, that was as different from Fortran as I could readily find. The '20 had a MacLisp installation, so I decided to learn Lisp, and it warped my mind forever.
MacLisp was an excellent Lisp, and there were plenty of books about Lisp programming that were source-code compatible with it. The DEC 20 was a fine machine for its day, though I suspect that here in the early twenty-first century there are toasters in production that have more processor power. They probably don't run MacLisp, though -- you might burn the toast while you were garbage-collecting.
(Remember, if you don't have a 36-bit word, you're not playing with a full DEC!) (Remember, that December 20 is DEC-20 day, when we all celebrate the greatness and glory of the DEC-20 computer!)
(Yes, the '20 did have a 36-bit word: That was so you could pack two 18-bit addresses into one word of memory -- just think, a whole 256K of address space! Or, you could cram in five 7-bit characters -- this was before ASCII -- with a bit left over for parity. There was a 36-bit floating-point number format, too.)
But I digress ...
Loosely, macros provide a systematic way to alter program source code under program control.
The R5 Scheme report defines a macro facility for R5 Scheme. That is only part of what is discussed here. Wraith Scheme also has a built-in macro low-level macro capability that works as follows:
A Wraith Scheme macro is a special kind of object that has a lambda expression of one parameter associated with it. When a macro occurs as the car of a Wraith Scheme list, the Wraith Scheme evaluator calls the lambda expression associated with the macro, passing it the entire list as parameter, and evaluates whatever the lambda expression returns. Typically, the macro's lambda expression will transform or alter the list in some way.
For further details, see the entry for "e::macro" in the Command Summary portion of this document.
One of several particular identifiers whose use usually indicates that it doesn't really matter what identifier is used or what value or binding it has. Or, perhaps, a default default identifier when there are no defaults to default to.
Metasyntactic variables in use in the Lisp community have included "foo", "bar", "baz", "frob", "mumble", "quux", and "grundoon".
For example:
"You can use "call-with-current-continuation" with any function foo ..."
(define (frob-with foo) ...)
If you think this makes complete sense, or if you think that it makes no sense whatsoever, you are missing the point.
When running several instances of Wraith Scheme cooperatively in parallel, one of them, which has a kitten number of zero, is of particular importance: It is called the "MomCat". For example, only the MomCat can load or save worlds, and only the MomCat will read any file specified in the Wraith Scheme preferences to load at startup. The MomCat also has an organizational role in arranging for garbage collection.
The MomCat is of sufficient importance that Wraith Scheme programs cannot run in parallel without it; thus, anything that causes the MomCat to terminate -- such as its "Quit" command -- will also cause any kittens present to terminate.
A "nan" is a special value of a flonum used to indicate that a calculation cannot produce a numerical result. Floating-point operations that are given nans as input generally produce nans as output. Thus a nan produced deep within a calculation will propagate through to the final result, where perhaps someone will notice it.
The central idea of numerical accuracy is that we are trying to use one number to model another. There is some number we would like to know -- perhaps something that can be calculated, like pi, or perhaps a physical quantity that needs to be measured, like the distance to the Moon, in miles. Unfortunately, the number we've got is not necessarily the number we want: The issue is, how close is it. When we speak of "numerical accuracy", we are talking about that closeness.
Note that it is meaningless to talk about the accuracy of a number: Accuracy has to do with two numbers, not just one. For example, consider the number 3. If we were trying to calculate the value of the integer that lies between 2 and 4, then "3" is very accurate -- it's dead on. On the other hand, if we were trying to calculate pi, we have missed it by several percent.
Numerical accuracy and numerical precision are often confused, and one of the sources of confusion is a common convention for implicitly characterizing accuracy by means of precision. Many of us were at one time or another taught, for example, that the number "3.5" stands for, or should stand for, or ought to stand for, any number from 3.45 through 3.55; that is, for any number that rounds to 3.5 when the usual rounding rules are applied.
That convention uses precision -- the number of digits used to represent a number -- to make a statement about accuracy. Sometimes that convention is useful, and sometimes not, but in any case, precision and accuracy are different concepts.
The Scheme programming language deals intrinsically with accuracy in only one way; namely, by means of the concept of "exactness", which has to do with whether Scheme's internal representation of a number is or is not precisely what the user provided as data or what a mathematical operation was trying to calculate. Thus if I type in "123", Wraith Scheme can indeed store the integer 123 with no problem, and will annotate it as an exact number, whereas if I type "4/3", Wraith Scheme will store an inexact number whose value is close to 1.333333 ... . Similarly, the mathematical primitives that Wraith Scheme uses are capable of noticing whether certain algorithms return approximate or exact results. Thus Wraith Scheme will store the result of (sqrt 4) as an exact 2, but will store the result of (acos 0) as an inexact number close to pi/2.
There are several related ways to look at numerical precision. We might consider it in essence a typographical property of the representations of numbers. Thus we say that "3.00000000000" is more precise than "3.00" because the former contains more digits than the latter.
By close analogy, though getting a bit away from typography, we say that a 64-bit floating-point number is more precise than a 32-bit floating-point number because the former uses more bits to store its value than does the latter.
These notions are closely related to the mathematical discipline of information theory, and to the physical notion of entropy. To provide information is to indicate which of many alternatives is in fact in effect, and the greater the number of alternatives, the more information is being provided when we actually pick one. Thus we say that a 32-bit quantity contains more information than a 16-bit one simply because there are 4294967296 different 32-bit quantities but only 65536 different 16-bit quantities. That is, to specify a 32-bit quantity is to pick one in four billion, whereas to specify a 16-bit quantity is merely to pick one in sixty-five thousand.
Precision is different from accuracy: Thus, "3.000000000" could be either a perfectly accurate representation of the integer "three", or a representation of "pi" that is inaccurate by several percent.
Numerical accuracy and numerical precision are often confused, and one of the sources of confusion is a common convention for implicitly characterizing accuracy by means of precision. Many of us were at one time or another taught, for example, that the number "3.5" stands for, or should stand for, or ought to stand for, any number from 3.45 through 3.55; that is, for any number that rounds to 3.5 when the usual rounding rules are applied.
That convention uses precision -- the number of digits used to represent a number -- to make a statement about accuracy. Sometimes that convention is useful, and sometimes not, but in any case, precision and accuracy are different concepts.
Scheme's "number->string" procedure attempts to print out an external representation with enough precision accurately to represent the internal value of the number that was provided as its argument.
An ob-list is a list of all the symbols in use in a Lisp system. Wraith Scheme uses one in such a way that there is always only one copy of each symbol in use: That is, if there is need in many different places to use "the same" symbol, each of those places will get a pointer to the single copy of the symbol in use, rather than a new duplicate of it. That way, symbols can be compared by pointer equality, rather than by comparing the strings that name them -- and pointer equality is faster.
Technical Note: Actually, there is a little more to it. Internally, Wraith Scheme defines a symbol as a pointer to a small Scheme data structure that contains the symbol's name -- which is a string -- and a few other items of data about it, and makes sure that there is only one such data structure -- in the ob-list -- for any given name. Symbols are compared for equality by comparing these pointers. A symbol's names is printed by following the pointer to get to the appropriate string.
Wraith Scheme allows the symbols to be declared "permanent", which means that Wraith Scheme will report an error if you try to change the value or binding of such a symbol. (If you really want to change one, there is a way to make a symbol un-permanent again.) Making a symbol permanent reduces the probability of changing what it stands for by mistake, and also allows the Wraith Scheme compiler to use the actual value or binding for the symbol, instead of just the symbol itself, in compiled code.
Pixie was the cat for whom Wraith Scheme's predecessor, Pixie Scheme, is named. He was one of Wraith's kittens. He was a classic Hallowe'en cat -- coal-black, with brilliant yellow eyes. He also seemed a little bit fey, rather more so than most cats.
Pixie Scheme was an "R3" Scheme for mid- to late-1980s versions of the Apple Macintosh, that I created and developed from 1987 through 1991. It was available as shareware at that time -- for that matter, it still is. Pixie Scheme is the direct ancestor of Wraith Scheme; indeed, much of Pixie Scheme's source code was incorporated in the first release of Wraith Scheme without change.
"Referential Transparency" is the idea that you can "refer" to something as many times as you like and always have the same result. The result is "transparent" to how many times the reference has occurred. A "reference" might be a procedure call, a variable-value lookup, or something else.
Here is a Scheme procedure which is referentially transparent:
(define (increment x) (+ x 1))
Thus for example, you may call it with "3" as an argument as many times as you like, and you will get back "4" each and every time.
Here is a Scheme procedure which is not referentially transparent:
(define next-number 1) (define (get-next-number) (let ((return-value next-number)) (set! next-number (+ next-number 1)) return-value))
Consecutive calls to "next-number" will return 1, 2, 3 ...
Here is another Scheme procedure which is not referentially transparent:
char-read
This standard Scheme procedure returns the next character from some port -- typically the keyboard. There is no guarantee that it will always return the same value.
To "reset" Wraith Scheme is to make it stop whatever processing it is doing and restart the top-level loop.
The "R5 Report" is the Revised5 report on the Algorithmic Language Scheme, edited by Richard Kelsey, William Clinger and Jonathan Rees. It is the definitive standard for "R5" Scheme. As the name may suggest, there have been, are, and no doubt will be, "RN" reports for other values of N. An "R6" report has been released, but Wraith Scheme does not presently implement R6 Scheme.
People working in computer science sometimes find it useful to create a mental model of a computer that does not actually exist, as an aid to understanding a particular kind of computer language or programming style. One such model is the "SECD machine". I first encountered it in Peter Henderson's Functional Programming Application and Implementation (Prentice-Hall, 1980).
An SECD machine is envisioned as a special kind of processor, designed for working with lexically scoped Lisp-class programming languages. It can address memory and perform operations in the usual way, and has four special-purpose registers that contain pointers to four special lists.
The four registers are called "S", "E", "C", and "D". Those letters stand respectively for "Stack", "Environment", "Continuation", and "Dump".
This use of a stack is somewhat simpler than the most common stack use in conventional processors. Conventional processors generally use a stack not only for calculations, but also for maintaining information about functions that have been called but have not yet returned.
The kind of stack used by an SECD machine resembles the kind explicitly modeled in the programming language "Forth".
An SECD machine processes a procedure call by making a list of the current content of the S, E, and C registers, pushing that list onto the Dump, clearing the Stack, and loading the E and C registers respectively with the environment and code for the newly-called procedure. An SECD machine processes a return from a procedure by popping the car of the Dump -- that car will be a three-element list -- and reloading the S, E, and C registers from its elements.
Wraith Scheme's predecessor, Pixie Scheme, started out as an SECD machine -- not a non-existent one, but not quite a real one, either; it was a virtual SECD machine, implemented as a program in the programming language C, pretty much as outlined by Henderson. It soon changed somewhat: I re-implemented the Stack as a more traditional kind of stack in separately-allocated memory, and arranged to save what would otherwise have gone into the Dump, on the Stack. Thus Pixie Scheme had no S or D registers. I also added several additional registers to the model, for purposes other than process control and memory management. Wraith Scheme uses the same kind of virtual machine model and implementation that Pixie Scheme did.
The term "Special Form" is Lisp jargon for any kind of Lisp expression, that is bounded by parentheses, that is not a procedure call. The distinction is useful because every argument to a procedure call is evaluated before being passed to the procedure itself, whereas what happens to the arguments to special forms depends on the form. For example, the special form "set!" evaluates its second argument but not its first.
Macros are typically special forms, though to be technical, it is possible -- though not necessarily useful -- to define a macro that evaluates all its arguments, just like a procedure.
Every Wraith Scheme object has associated with it an instance of a data type peculiar to Wraith Scheme, that I call a "tagged aval". Such an instance is composed of a 32-bit tag field that further identifies the type of the object and provides a place to store information about how it fits into Wraith Scheme main memory, and a 32-bit field that is either the actual data the object represents, or a pointer to that data. The term "aval" refers to the latter field; I intend it to be analogous to "rval" or "lval" (which are programmer jargon in themselves), but to mean "ambiguous value", for the 32-bit field may either be literal data -- an "rval", or a place to put data -- an "lval".
By and large, when the 32-bit field is literal data, the tagged aval represents the value of a Wraith Scheme object, and when the 32-bit field is a pointer, the tagged aval represents the binding of a Wraith Scheme object.
A tagged-object Lisp -- or indeed, a tagged-object implementation any kind of programming language -- associates some kind of "tag" with every object, to tell what kind of thing the object is. Such a tagging system is a rather specialized class mechanism, in which the number of classes is restricted to the number of available tags, and in which the the means of defining and using new classes and new methods are not necessarily made visible to the user of the language.
Since Lisp-class languages are often very polymorphic, a tagged-object Lisp constitutes an interesting canard, in which strong typing at a very low level is used to implement a system that is essentially type-free at a higher level.
Wraith Scheme is a tagged-object Lisp. See "tagged aval", above.
There are other ways to identify objects; for example, one might have a number of disjoint memory regions in which to put objects, one for each kind of object. Memory-address arithmetic would allow determining which region an object was in, and therefore, what kind of object it was.
In most computer systems, calling a procedure necessarily requires allocating some memory for it to use. Possible memory uses might include storage space for the procedure's local variables, "scratchpad" space for calculations, storage space for a pointer to the environment to use, and so on.
Such a memory allocation is only temporary. The memory used can be reclaimed, and used for something else, after the procedure returns. Yet if a computer program involves a deeply-nested series of procedure calls, the total amount of space temporarily allocated for those calls may become quite large, perhaps so large that the system will run out of allocatable memory. In that case, the program will fail.
For example, here is a simple function to find the length of a list:
(define (lnth l) (if (null? l) 0 (+ 1 (lnth (cdr l)))))
This function works recursively. It keeps calling itself with successively shorter portions of the given list, until it finally reaches the end of the list. Then all those calls return, computing the answer in the process.
If this function were used to calculate the length of a list that contained, say, a hundred million items, it would use a whole lot of memory.
Fortunately, it is sometimes possible to free up a procedure call's temporary memory before the procedure returns. The general idea is to free the temporary memory as soon as the procedure is finished with it. That will be so, in particular, when the last thing a procedure does before returning is to call another procedure.
For example, consider procedure "foo":
(define (foo n) ... (bar (- n 1)) )
This procedure does some things that we don't care about, indicated by the ellipsis, then calls another procedure, "bar". At the time of the call to "bar", "foo" has nothing else to do: It is going to return whatever "bar" returns, without any further computation. Thus any temporary memory allocated for the use of "foo" could be reclaimed before the call to "bar", provided we patched our call stack, or whatever, so that "bar" returned to wherever "foo" was going to return.
It doesn't even matter if "bar" never returns at all. The little bit of space that "foo" was using can get cleaned up before "bar" even begins to run. All we do is start off "bar" set up so that when and if it ever returns, it goes back to whatever location is expecting the return from "foo".
That example shows how to save a little space, but not much. On the other hand, suppose that "foo" had been a recursive procedure, written like this:
(define (foo n) (foo (- n 1)) )
Procedure "foo" is said to be "tail recursive", because the last thing it does -- the code in the tail of its continuation -- is to call itself.
The same logic about reclaiming memory applies: We reclaim the temporary memory used for one call of "foo", and allocate some more memory for another such call, with an argument smaller by 1. We are in effect reusing the temporary memory for foo, and if the computer system is so designed, it may in fact actually reuse that memory, rather than freeing one chunk and then allocating another identical chunk.
Now suppose we call the recursive version of "foo" with some starting argument. Do you see what happens? If we do not reuse the temporary memory, the system will keep allocating new, separate blocks of temporary memory, one for each call to "foo". And since "foo", as written, never returns, the system will eventually run out of memory.
On the other hand, if the system is reclaiming temporary memory in the manner described, it will reuse just one block of temporary memory forever. It doesn't matter that "foo" never returns.
The procedure "lnth", a few paragraphs back, is not tail-recursive. After a recursive call, there is some addition to be done before returning a value. But it is not hard to write a tail-recursive procedure to find the length of a list. It uses an auxiliary procedure, like this:
(define (lnth-aux l n) (if (null? l) n (lnth-aux (cdr l) (+ n 1))) ) (define (lnth l) (lnth-aux l 0))
When the procedure "lnth-aux" recurses, it does so in a tail-recursive manner -- there is nothing to do after "lnth-aux" returns. Thus the system can reclaim the temporary memory for "lnth-aux" before the recursive call is made. Procedure "lnth" is just used to get things going -- it calls "lnth-aux" with starting values. Thus with these definitions, we can find the length of a list of 100 million items without running out of memory.
Note that although the business of freeing up temporary memory when there is no further use for it is traditionally associated with tail recursion, the idea is more widely applicable -- as shown by the example in which "foo" calls "bar".
Wraith Scheme checks for the possibility of reclaiming temporary space at run-time: When one procedure is about to call another, if the continuation of the current procedure contains nothing other than the call, then the temporary space for the current procedure is reclaimed.
Transcript files are a Scheme feature, described in the R5 report, for logging user interactions with Scheme. See the discussion of "transcript-on" and "transcript-off" in the Command Summary portion of this document.
A world file is a special kind of binary file that contains the entire non-garbage content of Scheme memory, and can be reloaded when necessary, to restore the state of the Scheme world to what it was when the world file was created.
Wraith Scheme has enhancements to save and load world files; look for "e::save-world" and "e::load-world!" in the Command Summary portion of this document.
You might consider using a world file to save work in progress, just as you might save copies of a document you were working on in a word processor. You might also use a world file to save a standard starting state of some kind of work session, if it took a long time to create that state -- perhaps there were lots of files to load and lots of preliminary calculations to be done. Wraith Scheme loads a world file at startup, that was created with this latter function in mind.
The cat for whom Wraith Scheme is named. I named her Wraith not because of any supernatural qualities she possessed, but because she was wary of humans, stealthy, pale gray in color and thus well camouflaged in many circumstances, and when I first encountered her you could count every rib: She was living wild in my new back yard in Davenport, California, trying to be a good mother to three kittens, and slowly starving.
So I took them all in. Wraith was feral to the point of being vicious: My hands were in ribbons for several months after I acquired her. She eventually turned into a sweetheart. I miss her.