r7rs-small-texinfo

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 6d8fb87a18e924fff9aa1b057ea86ec6f42769a5
parent d743997938d6490c32bcdfe4fc3b8d5046c4ca0c
Author: Yuval Langer <yuval.langer@gmail.com>
Date:   Mon, 29 Jan 2024 18:55:52 +0200

Add some more examples.

Diffstat:
Mdoc/r7rs-small/r7rs-small.texinfo | 494+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 423 insertions(+), 71 deletions(-)

diff --git a/doc/r7rs-small/r7rs-small.texinfo b/doc/r7rs-small/r7rs-small.texinfo @@ -4826,11 +4826,15 @@ procedure: (cddr pair) These procedures are compositions of car and cdr as follows: +@example + (define (caar x) (car (car x))) (define (cadr x) (car (cdr x))) (define (cdar x) (cdr (car x))) (define (cddr x) (cdr (cdr x))) +@end example + cxr library procedure: (caaar pair) cxr library procedure: (caadr pair) 1 ⋮: 0 ⋮ @@ -4840,7 +4844,13 @@ cxr library procedure: (cddddr pair) These twenty-four procedures are further compositions of car and cdr on the same principles. For example, caddr could be defined by -(define caddr (lambda (x) (car (cdr (cdr x))))). Arbitrary compositions up to four deep are +@example + +(define caddr (lambda (x) (car (cdr (cdr x))))). + +@end example + +Arbitrary compositions up to four deep are provided. procedure: (null? obj) @@ -4856,6 +4866,8 @@ Returns #t if obj is a list. Otherwise, it returns #f. By definition, all lists have finite length and are terminated by the empty list. +@example + (list? '(a b c)) ⟹ #t (list? '()) ⟹ #t (list? '(a . b)) ⟹ #f @@ -4863,6 +4875,8 @@ terminated by the empty list. (set-cdr! x x) (list? x)) ⟹ #f +@end example + procedure: (make-list k) procedure: (make-list k fill) @@ -4872,38 +4886,48 @@ k elements. If a second argument is given, then each element is initialized to fill. Otherwise the initial contents of each element is unspecified. +@example + (make-list 2 3) ⟹ (3 3) +@end example + procedure: (list obj …) Returns a newly allocated list of its arguments. +@example + (list 'a (+ 3 4) 'c) ⟹ (a 7 c) (list) ⟹ () -procedure: (length list) +@end example -Returns the length of +procedure: (length @var{list}) -list. +Returns the length of @var{list}. + +@example (length '(a b c)) ⟹ 3 (length '(a (b) (c d e))) ⟹ 3 (length '()) ⟹ 0 -procedure: (append list …) +@end example + +procedure: (append @var{list} …) The last argument, if there is one, can be of any type. -Returns a list consisting of the elements of the first - -list followed by the elements of the other +Returns a list consisting of the elements of the first @var{list} +followed by the elements of the other @var{lists}. If there are no +arguments, the empty list is returned. If there is exactly one +argument, it is returned. Otherwise the resulting list is always newly +allocated, except that it shares structure with the last argument. An +improper list results if the last argument is not a proper list. -lists. If there are no arguments, the empty list is returned. If there is exactly one -argument, it is returned. Otherwise the resulting list is always newly allocated, except -that it shares structure with the last argument. An improper list results if the last -argument is not a proper list. +@example (append '(x) '(y)) ⟹ (x y) (append '(a) '(b c d)) ⟹ (a b c d) @@ -4912,16 +4936,21 @@ argument is not a proper list. (append '(a b) '(c . d)) ⟹ (a b c . d) (append '() 'a) ⟹ a -procedure: (reverse list) +@end example + +procedure: (reverse @var{list}) Returns a newly allocated list consisting of the elements of +@var{list} in reverse order. -list in reverse order. +@example (reverse '(a b c)) ⟹ (c b a) (reverse '(a (b c) d (e (f)))) ⟹ ((e (f)) d (b c) a) +@end example + procedure: (list-tail list k) @@ -4937,12 +4966,16 @@ list obtained by omitting the first k elements. The list-tail procedure could be defined by +@example + (define list-tail (lambda (x k) (if (zero? k) x (list-tail (cdr x) (- k 1))))) +@end example + procedure: (list-ref list k) @@ -4964,11 +4997,15 @@ list k).) +@example + (list-ref '(a b c d) 2) ⟹ c (list-ref '(a b c d) (exact (round 1.8))) ⟹ c +@end example + procedure: (list-set! list k obj) It is an error if @@ -4985,6 +5022,8 @@ k of list. +@example + (let ((ls (list 'one 'two 'five!))) (list-set! ls 2 'three) ls) @@ -4993,6 +5032,8 @@ list. (list-set! '(0 1 2) 1 "oops") ⟹ error ; constant list +@end example + procedure: (memq obj list) procedure: (memv obj list) procedure: (member obj list) @@ -5024,6 +5065,8 @@ list, while memv uses eqv? and member uses compare, if given, and equal? otherwise. +@example + (memq 'a '(a b c)) ⟹ (a b c) (memq 'b '(a b c)) ⟹ (b c) (memq 'a '(b c d)) ⟹ #f @@ -5036,6 +5079,8 @@ compare, if given, and equal? otherwise. (memq 101 '(100 101 102)) ⟹ unspecified (memv 101 '(100 101 102)) ⟹ (101 102) +@end example + procedure: (assq obj alist) procedure: (assv obj alist) procedure: (assoc obj alist) @@ -5062,6 +5107,8 @@ alist, while assv uses eqv?​ ​and assoc uses compare if given and equal? otherwise. +@example + (define e '((a 1) (b 2) (c 3))) (assq 'a e) ⟹ (a 1) (assq 'b e) ⟹ (b 2) @@ -5077,7 +5124,9 @@ compare if given and equal? otherwise. (assv 5 '((2 3) (5 7) (11 13))) ⟹ (5 7) - Rationale: Although they are often used as predicates, memq, memv, member, assq, +@end example + +Rationale: Although they are often used as predicates, memq, memv, member, assq, assv, and assoc do not have question marks in their names because they return potentially useful values rather than just #t or #f. @@ -5097,12 +5146,16 @@ obj which is not a list is returned unchanged. It is an error if obj is a circular list. +@example + (define a '(1 8 2 8)) ; a may be immutable (define b (list-copy a)) (set-car! b 3) ; b is mutable b ⟹ (3 8 2 8) a ⟹ (1 8 2 8) +@end example + @node Symbols @section Symbols @@ -5128,6 +5181,8 @@ Returns #t if obj is a symbol, otherwise returns #f. +@example + (symbol? 'foo) ⟹ #t (symbol? (car '(a b))) ⟹ #t (symbol? "bar") ⟹ #f @@ -5135,6 +5190,8 @@ obj is a symbol, otherwise returns #f. (symbol? '()) ⟹ #f (symbol? #f) ⟹ #f +@end example + procedure: (symbol=? symbol1 symbol2 symbol3 …) @@ -5150,6 +5207,8 @@ Returns the name of symbol as a string, but without adding escapes. It is an error to apply mutation procedures like string-set! to strings returned by this procedure. +@example + (symbol->string 'flying-fish) ⟹ "flying-fish" (symbol->string 'Martin) ⟹ "Martin" @@ -5157,6 +5216,8 @@ procedures like string-set! to strings returned by this procedure. (string->symbol "Malvina")) ⟹ "Malvina" +@end example + procedure: (string->symbol string) Returns the symbol whose name is @@ -5164,6 +5225,8 @@ Returns the symbol whose name is string. This procedure can create symbols with names containing special characters that would require escaping when written, but does not interpret escapes in its input. +@example + (string->symbol "mISSISSIppi") ⟹mISSISSIppi (eqv? 'bitBlt (string->symbol "bitBlt")) @@ -5177,6 +5240,8 @@ would require escaping when written, but does not interpret escapes in its input (string->symbol "K. Harper, M.D."))) ⟹ #t +@end example + @node Characters @section Characters @@ -5315,11 +5380,15 @@ char library procedure: (digit-value char) This procedure returns the numeric value (0 to 9) of its argument if it is a numeric digit (that is, if char-numeric? returns #t), or #f on any other character. +@example + (digit-value #\3) ⟹ 3 (digit-value #\x0664) ⟹ 4 (digit-value #\x0AE6) ⟹ 0 (digit-value #\x0EA6) ⟹ #f +@end example + procedure: (char->integer char) procedure: (integer->char n) @@ -5482,6 +5551,8 @@ k of string. There is no requirement for this procedure to execute in constant time. +@example + (define (f) (make-string 3 #\*)) (define (g) "***") (string-set! (f) 0 #\?) ⟹ unspecified @@ -5490,6 +5561,8 @@ string. There is no requirement for this procedure to execute in constant time. 0 #\?) ⟹ error +@end example + procedure: (string=? string1 string2 string3 …) @@ -5645,11 +5718,15 @@ destination overlap, copying takes place as if the source is first copied into a string and then into the destination. This can be achieved without allocating storage by making sure to copy in the correct direction in such circumstances. +@example + (define a "12345") (define b (string-copy "abcde")) (string-copy! b 1 a 0 2) b ⟹ "a12de" +@end example + procedure: (string-fill! string fill) procedure: (string-fill! string fill start) procedure: (string-fill! string fill start end) @@ -5709,8 +5786,12 @@ procedure: (vector obj …) Returns a newly allocated vector whose elements contain the given arguments. It is analogous to list. +@example + (vector 'a 'b 'c) ⟹ #(a b c) +@end example + procedure: (vector-length vector) Returns the number of elements in @@ -5731,6 +5812,8 @@ k of vector. +@example + (vector-ref '#(1 1 2 3 5 8 13 21) 5) ⟹ 8 @@ -5739,6 +5822,8 @@ vector. (round (* 2 (acos -1))))) ⟹ 13 +@end example + procedure: (vector-set! vector k obj) It is an error if @@ -5755,6 +5840,8 @@ k of vector. +@example + (let ((vec (vector 0 '(2 2 2 2) "Anna"))) (vector-set! vec 1 '("Sue" "Sue")) vec) @@ -5763,6 +5850,8 @@ vector. (vector-set! '#(0 1 2) 1 "doe") ⟹ error ; constant vector +@end example + procedure: (vector->list vector) procedure: (vector->list vector start) procedure: (vector->list vector start end) @@ -5782,6 +5871,8 @@ list. In both procedures, order is preserved. +@example + (vector->list '#(dah dah didah)) ⟹ (dah dah didah) (vector->list '#(dah dah didah) 1 2) @@ -5789,6 +5880,8 @@ In both procedures, order is preserved. (list->vector '(dididit dah)) ⟹ #(dididit dah) +@end example + procedure: (vector->string vector) procedure: (vector->string vector start) procedure: (vector->string vector start end) @@ -5822,10 +5915,14 @@ end. In both procedures, order is preserved. +@example + (string->vector "ABC") ⟹ #(#\A #\B #\C) (vector->string #(#\1 #\2 #\3) ⟹ "123" +@end example + procedure: (vector-copy vector) procedure: (vector-copy vector start) procedure: (vector-copy vector start end) @@ -5839,6 +5936,8 @@ start and end. The elements of the new vector are the same (in the sense of eqv?) as the elements of the old. +@example + (define a #(1 8 2 8)) ; a may be immutable (define b (vector-copy a)) (vector-set! b 0 3) ; b is mutable @@ -5846,6 +5945,8 @@ b ⟹ #(3 8 2 8) (define c (vector-copy b 1 3)) c ⟹ #(8 2) +@end example + procedure: (vector-copy! to at from) procedure: (vector-copy! to at from start) procedure: (vector-copy! to at from start end) @@ -5879,20 +5980,28 @@ destination overlap, copying takes place as if the source is first copied into a vector and then into the destination. This can be achieved without allocating storage by making sure to copy in the correct direction in such circumstances. +@example + (define a (vector 1 2 3 4 5)) (define b (vector 10 20 30 40 50)) (vector-copy! b 1 a 0 2) b ⟹ #(10 1 2 40 50) +@end example + procedure: (vector-append vector …) Returns a newly allocated vector whose elements are the concatenation of the elements of the given vectors. +@example + (vector-append #(a b c) #(d e f)) ⟹ #(a b c d e f) +@end example + procedure: (vector-fill! vector fill) procedure: (vector-fill! vector fill start) procedure: (vector-fill! vector fill start end) @@ -5907,11 +6016,15 @@ start and end. +@example + (define a (vector 1 2 3 4 5)) (vector-fill! a 'smash 2 4) a ⟹ #(1 2 smash smash 5) +@end example + @node Bytevectors @section Bytevectors @@ -5949,16 +6062,24 @@ byte is given, then all elements of the bytevector are initialized to byte, otherwise the contents of each element are unspecified. +@example + (make-bytevector 2 12) ⟹ #u8(12 12) +@end example + procedure: (bytevector byte …) Returns a newly allocated bytevector containing its arguments. +@example + (bytevector 1 3 5 1 3 5) ⟹ #u8(1 3 5 1 3 5) (bytevector) ⟹ #u8() +@end example + procedure: (bytevector-length bytevector) Returns the length of @@ -5979,10 +6100,14 @@ kth byte of bytevector. +@example + (bytevector-u8-ref '#u8(1 1 2 3 5 8 13 21) 5) ⟹ 8 +@end example + procedure: (bytevector-u8-set! bytevector k byte) It is an error if @@ -5999,11 +6124,15 @@ kth byte of bytevector. +@example + (let ((bv (bytevector 1 2 3 4))) (bytevector-u8-set! bv 1 3) bv) ⟹ #u8(1 3 3 4) +@end example + procedure: (bytevector-copy bytevector) procedure: (bytevector-copy bytevector start) procedure: (bytevector-copy bytevector start end) @@ -6016,9 +6145,13 @@ start and end. +@example + (define a #u8(1 2 3 4 5)) (bytevector-copy a 2 4)) ⟹ #u8(3 4) +@end example + procedure: (bytevector-copy! to at from) procedure: (bytevector-copy! to at from start) procedure: (bytevector-copy! to at from start end) @@ -6052,12 +6185,16 @@ destination overlap, copying takes place as if the source is first copied into a bytevector and then into the destination. This can be achieved without allocating storage by making sure to copy in the correct direction in such circumstances. +@example + (define a (bytevector 1 2 3 4 5)) (define b (bytevector 10 20 30 40 50)) (bytevector-copy! b 1 a 0 2) b ⟹ #u8(10 1 2 40 50) - Note: This procedure appears in R6RS, but places the source before the destination, +@end example + +Note: This procedure appears in R6RS, but places the source before the destination, contrary to other such procedures in Scheme. procedure: (bytevector-append bytevector …) @@ -6066,9 +6203,13 @@ procedure: (bytevector-append bytevector …) Returns a newly allocated bytevector whose elements are the concatenation of the elements in the given bytevectors. +@example + (bytevector-append #u8(0 1 2) #u8(3 4 5)) ⟹ #u8(0 1 2 3 4 5) +@end example + procedure: (utf8->string bytevector) procedure: (utf8->string bytevector start) procedure: (utf8->string bytevector start end) @@ -6093,9 +6234,13 @@ start and end and returns the corresponding bytevector. +@example + (utf8->string #u8(#x41)) ⟹ "A" (string->utf8 "λ") ⟹ #u8(#xCE #xBB) +@end example + @node Control features @section Control features @@ -6110,6 +6255,8 @@ Returns #t if obj is a procedure, otherwise returns #f. +@example + (procedure? car) ⟹ #t (procedure? 'car) ⟹ #f (procedure? (lambda (x) (* x x))) @@ -6119,6 +6266,8 @@ obj is a procedure, otherwise returns #f. (call-with-current-continuation procedure?) ⟹ #t +@end example + procedure: (apply proc arg1 … args) @@ -6164,6 +6313,8 @@ proc is applied to the elements of the lists is unspecified. If multiple returns occur from map, the values returned by earlier returns are not mutated. +@example + (map cadr '((a b) (d e) (g h))) ⟹ (b e h) @@ -6181,6 +6332,8 @@ returns are not mutated. or (2 1) +@end example + procedure: (string-map proc string1 string2 …) @@ -6203,6 +6356,8 @@ proc is applied to the elements of the strings is unspecified. If multiple returns occur from string-map, the values returned by earlier returns are not mutated. +@example + (string-map char-foldcase "AbdEgH") ⟹ "abdegh" @@ -6220,6 +6375,8 @@ earlier returns are not mutated. "ululululul") ⟹ "StUdLyCaPs" +@end example + procedure: (vector-map proc vector1 vector2 …) @@ -6241,6 +6398,8 @@ proc is applied to the elements of the vectors is unspecified. If multiple returns occur from vector-map, the values returned by earlier returns are not mutated. +@example + (vector-map cadr '#((a b) (d e) (g h))) ⟹ #(b e h) @@ -6260,6 +6419,8 @@ earlier returns are not mutated. or #(2 1) +@end example + procedure: (for-each proc list1 list2 …) @@ -6286,12 +6447,16 @@ It is an error for proc to mutate any of the lists. +@example + (let ((v (make-vector 5))) (for-each (lambda (i) (vector-set! v i (* i i))) '(0 1 2 3 4)) v) ⟹ #(0 1 4 9 16) +@end example + procedure: (string-for-each proc string1 string2 …) @@ -6315,12 +6480,16 @@ the shortest string runs out. It is an error for proc to mutate any of the strings. +@example + (let ((v '())) (string-for-each (lambda (c) (set! v (cons (char->integer c) v))) "abcde") v) ⟹ (101 100 99 98 97) +@end example + procedure: (vector-for-each proc vector1 vector2 …) @@ -6344,12 +6513,16 @@ the shortest vector runs out. It is an error for proc to mutate any of the vectors. +@example + (let ((v (make-list 5))) (vector-for-each (lambda (i) (list-set! v i (* i i))) '#(0 1 2 3 4)) v) ⟹ (0 1 4 9 16) +@end example + procedure: (call-with-current-continuation proc) procedure: (call/cc proc) @@ -6392,6 +6565,8 @@ call-with-current-continuation is used. If all real uses were as simple as these there would be no need for a procedure with the power of call-with-current-continuation. +@example + (call-with-current-continuation (lambda (exit) (for-each (lambda (x) @@ -6416,7 +6591,9 @@ call-with-current-continuation. (list-length '(a b . c)) ⟹ #f - Rationale: A common use of call-with-current-continuation is for structured, +@end example + +Rationale: A common use of call-with-current-continuation is for structured, non-local exits from loops or procedure bodies, but in fact call-with-current-continuation is useful for implementing a wide variety of advanced control structures. In fact, raise and guard provide a more structured mechanism @@ -6440,10 +6617,14 @@ procedure: (values obj …) Delivers all of its arguments to its continuation. The values procedure might be defined as follows: +@example + (define (values . things) (call-with-current-continuation (lambda (cont) (apply cont things)))) +@end example + procedure: (call-with-values producer consumer) Calls its @@ -6455,12 +6636,16 @@ consumer procedure with those values as arguments. The continuation for the call consumer is the continuation of the call to call-with-values. +@example + (call-with-values (lambda () (values 4 5)) (lambda (a b) b)) ⟹ 5 (call-with-values * -) ⟹ -1 +@end example + procedure: (dynamic-wind before thunk after) Calls @@ -6529,6 +6714,8 @@ before or after is unspecified. +@example + (let ((path '()) (c #f)) (let ((add (lambda (s) @@ -6548,6 +6735,8 @@ after is unspecified. ⟹ (connect talk1 disconnect connect talk2 disconnect) +@end example + @node Exceptions @section Exceptions @@ -6582,6 +6771,8 @@ for the invocation of thunk. +@example + (call-with-current-continuation (lambda (k) (with-exception-handler @@ -6603,6 +6794,8 @@ thunk. prints something went wrong After printing, the second example then raises another exception. +@end example + procedure: (raise obj) @@ -6656,6 +6849,8 @@ message, as well as any objs, known as the irritants. The procedure error-object? must return #t on such objects. +@example + (define (null-list? l) (cond ((pair? l) #f) ((null? l) #t) @@ -6664,6 +6859,8 @@ objs, known as the irritants. The procedure error-object? must return #t on such "null-list?: argument out of domain" l)))) +@end example + procedure: (error-object? obj) Returns #t if @@ -6765,6 +6962,8 @@ returned. If it is a definition, the specified identifier(s) are defined in the environment, provided the environment is not immutable. Implementations may extend eval to allow other objects. +@example + (eval '(* 7 3) (environment '(scheme base))) ⟹ 21 @@ -6776,6 +6975,8 @@ eval to allow other objects. (environment '(scheme base))) ⟹ error is signaled +@end example + @node Input and output @section Input and output @@ -6946,6 +7147,8 @@ port was not created with open-output-string. Returns a string consisting of the characters that have been output to the port so far in the order they were output. If the result string is modified, the effect is unspecified. +@example + (parameterize ((current-output-port (open-output-string))) @@ -6957,6 +7160,8 @@ the order they were output. If the result string is modified, the effect is unsp ⟹ "piece by piece by piece.\n" +@end example + procedure: (open-input-bytevector bytevector) Takes a bytevector and returns a binary input port that delivers bytes from the @@ -7388,9 +7593,13 @@ to encode the name and decode the value of the environment variable. It is an er get-environment-variable can’t decode the value. It is also an error to mutate the resulting string. +@example + (get-environment-variable "PATH") ⟹ "/usr/local/bin:/usr/bin:/bin" +@end example + process-context library procedure: (get-environment-variables) Returns the names and values of all the environment variables as an alist, where the car @@ -7398,9 +7607,13 @@ of each entry is the name of an environment variable and the cdr is its value, b strings. The order of the list is unspecified. It is an error to mutate any of these strings or the alist itself. +@example + (get-environment-variables) ⟹ (("USER" . "root") ("HOME" . "/")) +@end example + time library procedure: (current-second) Returns an inexact number representing the current time on the International Atomic @@ -7433,6 +7646,8 @@ time library procedure: (jiffies-per-second) Returns an exact integer representing the number of jiffies per SI second. This value is an implementation-specified constant. +@example + (define (time-length) (let ((list (make-list 100000)) (start (current-jiffy))) @@ -7440,11 +7655,15 @@ an implementation-specified constant. (/ (- (current-jiffy) start) (jiffies-per-second)))) +@end example + procedure: (features) Returns a list of the feature identifiers which cond-expand treats as true. It is an error to modify this list. Here is an example of what features might return: +@example + (features) ⟹ (r7rs ratios exact-complex full-unicode gnu-linux little-endian @@ -7452,6 +7671,8 @@ modify this list. Here is an example of what features might return: fantastic-scheme-1.0 space-ship-control-system) +@end example + @node Formal syntax and semantics @chapter Formal syntax and semantics @@ -7898,6 +8119,8 @@ quasiquote. Conditional derived syntax types: +@example + (define-syntax cond (syntax-rules (else =>) ((cond (else result1 result2 ...)) @@ -7923,6 +8146,7 @@ Conditional derived syntax types: (if test (begin result1 result2 ...) (cond clause1 clause2 ...))))) + (define-syntax case (syntax-rules (else =>) ((case (key ...) @@ -7955,12 +8179,14 @@ Conditional derived syntax types: (if (memv key '(atoms ...)) (begin result1 result2 ...) (case key clause clauses ...))))) + (define-syntax and (syntax-rules () ((and) #t) ((and test) test) ((and test1 test2 ...) (if test1 (and test2 ...) #f)))) + (define-syntax or (syntax-rules () ((or) #f) @@ -7968,18 +8194,25 @@ Conditional derived syntax types: ((or test1 test2 ...) (let ((x test1)) (if x x (or test2 ...)))))) + (define-syntax when (syntax-rules () ((when test result1 result2 ...) (if test (begin result1 result2 ...))))) + (define-syntax unless (syntax-rules () ((unless test result1 result2 ...) (if (not test) (begin result1 result2 ...))))) + +@end example + Binding constructs: +@example + (define-syntax let (syntax-rules () ((let ((name val) ...) body1 body2 ...) @@ -7990,6 +8223,7 @@ Binding constructs: body1 body2 ...))) tag) val ...)))) + (define-syntax let* (syntax-rules () ((let* () body1 body2 ...) @@ -7999,12 +8233,17 @@ Binding constructs: (let ((name1 val1)) (let* ((name2 val2) ...) body1 body2 ...))))) + +@end example + The following letrec macro uses the symbol <undefined> in place of an expression which returns something that when stored in a location makes it an error to try to obtain the value stored in the location. (No such expression is defined in Scheme.) A trick is used to generate the temporary names needed to avoid specifying the order in which the values are evaluated. This could also be accomplished by using an auxiliary macro. +@example + (define-syntax letrec (syntax-rules () ((letrec ((var1 init1) ...) body ...) @@ -8033,102 +8272,113 @@ are evaluated. This could also be accomplished by using an auxiliary macro. (newtemp temp ...) ((var1 init1) ...) body ...)))) + (define-syntax letrec* (syntax-rules () ((letrec* ((var1 init1) ...) body1 body2 ...) (let ((var1 <undefined>) ...) (set! var1 init1) ... - (let () body1 body2 ...))))) (define-syntax let-values + (let () body1 body2 ...))))) + +(define-syntax let-values (syntax-rules () ((let-values (binding ...) body0 body1 ...) (let-values "bind" - (binding ...) () (begin body0 body1 ...))) + (binding ...) () (begin body0 body1 ...))) ((let-values "bind" () tmps body) (let tmps body)) ((let-values "bind" ((b0 e0) - binding ...) tmps body) + binding ...) tmps body) (let-values "mktmp" b0 e0 () - (binding ...) tmps body)) + (binding ...) tmps body)) ((let-values "mktmp" () e0 args - bindings tmps body) + bindings tmps body) (call-with-values - (lambda () e0) + (lambda () e0) (lambda args (let-values "bind" - bindings tmps body)))) + bindings tmps body)))) ((let-values "mktmp" (a . b) e0 (arg ...) - bindings (tmp ...) body) + bindings (tmp ...) body) (let-values "mktmp" b e0 (arg ... x) - bindings (tmp ... (a x)) body)) + bindings (tmp ... (a x)) body)) ((let-values "mktmp" a e0 (arg ...) - bindings (tmp ...) body) + bindings (tmp ...) body) (call-with-values - (lambda () e0) + (lambda () e0) (lambda (arg ... . x) (let-values "bind" - bindings (tmp ... (a x)) body)))))) + bindings (tmp ... (a x)) body)))))) + (define-syntax let*-values (syntax-rules () ((let*-values () body0 body1 ...) (let () body0 body1 ...)) ((let*-values (binding0 binding1 ...) - body0 body1 ...) + body0 body1 ...) (let-values (binding0) (let*-values (binding1 ...) body0 body1 ...))))) + (define-syntax define-values (syntax-rules () ((define-values () expr) (define dummy (call-with-values (lambda () expr) - (lambda args #f)))) + (lambda args #f)))) ((define-values (var) expr) (define var expr)) ((define-values (var0 var1 ... varn) expr) (begin (define var0 (call-with-values (lambda () expr) - list)) + list)) (define var1 (let ((v (cadr var0))) (set-cdr! var0 (cddr var0)) v)) ... - (define varn - (let ((v (cadr var0))) - (set! var0 (car var0)) - v)))) + (define varn + (let ((v (cadr var0))) + (set! var0 (car var0)) + v)))) ((define-values (var0 var1 ... . varn) expr) (begin (define var0 (call-with-values (lambda () expr) - list)) + list)) (define var1 (let ((v (cadr var0))) (set-cdr! var0 (cddr var0)) v)) ... - (define varn - (let ((v (cdr var0))) - (set! var0 (car var0)) - v)))) + (define varn + (let ((v (cdr var0))) + (set! var0 (car var0)) + v)))) ((define-values var expr) (define var (call-with-values (lambda () expr) - list))))) + list))))) + (define-syntax begin (syntax-rules () ((begin exp ...) ((lambda () exp ...))))) + +@end example + The following alternative expansion for begin does not make use of the ability to write more than one expression in the body of a lambda expression. In any case, note that these rules apply only if the body of the begin contains no definitions. +@example + (define-syntax begin (syntax-rules () ((begin exp) @@ -8138,59 +8388,111 @@ these rules apply only if the body of the begin contains no definitions. (lambda () exp1) (lambda args (begin exp2 ...)))))) + +@end example + The following syntax definition of do uses a trick to expand the variable clauses. As with letrec above, an auxiliary macro would also work. The expression (if #f #f) is used to obtain an unspecific value. +@example + (define-syntax do (syntax-rules () ((do ((var init step ...) ...) (test expr ...) - command ...) + command ...) (letrec - ((loop - (lambda (var ...) - (if test - (begin - (if #f #f) - expr ...) - (begin - command - ... - (loop (do "step" var step ...) - ...)))))) + ((loop + (lambda (var ...) + (if test + (begin + (if #f #f) + expr ...) + (begin + command + ... + (loop (do "step" var step ...) + ...)))))) (loop init ...))) ((do "step" x) x) ((do "step" x y) y))) -Here is a possible implementation of delay, force and delay-force. We define the -expression -(delay-force <expression>) to have the same meaning as the procedure call +@end example + +Here is a possible implementation of delay, force and delay-force. We +define the expression + +@example + +(delay-force <expression>) + +@end example + +to have the same meaning as the procedure call + +@example + +(make-promise #f (lambda () <expression>)) + +@end example + +as follows -(make-promise #f (lambda () <expression>)) as follows +@example (define-syntax delay-force (syntax-rules () ((delay-force expression) - (make-promise #f (lambda () expression))))) and we define the expression + (make-promise #f (lambda () expression))))) -(delay <expression>) to have the same meaning as: +@end example -(delay-force (make-promise #t <expression>)) as follows +and we define the expression + +@example + +(delay <expression>) + +@end example + +to have the same meaning as: + +@example + +(delay-force (make-promise #t <expression>)) + +@end example + +as follows + +@example (define-syntax delay (syntax-rules () ((delay expression) - (delay-force (make-promise #t expression))))) where make-promise is defined as -follows: + (delay-force (make-promise #t expression))))) + +@end example + +where make-promise is defined as follows: + +@example (define make-promise (lambda (done? proc) - (list (cons done? proc)))) Finally, we define force to call the procedure expressions in -promises iteratively using a trampoline technique following [38] until a non-lazy result -(i.e. a value created by delay instead of delay-force) is returned, as follows: + (list (cons done? proc)))) + +@end example + +Finally, we define force to call the procedure expressions in promises +iteratively using a trampoline technique following [38] until a +non-lazy result (i.e. a value created by delay instead of delay-force) +is returned, as follows: + +@example (define (force promise) (if (promise-done? promise) @@ -8198,7 +8500,13 @@ promises iteratively using a trampoline technique following [38] until a non-laz (let ((promise* ((promise-value promise)))) (unless (promise-done? promise) (promise-update! promise* promise)) - (force promise)))) with the following promise accessors: + (force promise)))) + +@end example + +with the following promise accessors: + +@example (define promise-done? (lambda (x) (car (car x)))) @@ -8208,11 +8516,17 @@ promises iteratively using a trampoline technique following [38] until a non-laz (lambda (new old) (set-car! (car old) (promise-done? new)) (set-cdr! (car old) (promise-value new)) - (set-car! new (car old)))) The following implementation of make-parameter and + (set-car! new (car old)))) + +@end example + +The following implementation of make-parameter and parameterize is suitable for an implementation with no threads. Parameter objects are implemented here as procedures, using two arbitrary unique objects <param-set!> and <param-convert>: +@example + (define (make-parameter init . o) (let* ((converter (if (pair? o) (car o) (lambda (x) x))) @@ -8226,9 +8540,15 @@ implemented here as procedures, using two arbitrary unique objects <param-set!> ((eq? (car args) <param-convert>) converter) (else - (error "bad parameter syntax")))))) Then parameterize uses dynamic-wind to + (error "bad parameter syntax")))))) + +@end example + +Then parameterize uses dynamic-wind to dynamically rebind the associated value: +@example + (define-syntax parameterize (syntax-rules () ((parameterize ("step") @@ -8255,9 +8575,14 @@ dynamically rebind the associated value: () ((param value) ...) body)))) + +@end example + The following implementation of guard depends on an auxiliary macro, here called guard-aux. +@example + (define-syntax guard (syntax-rules () ((guard (var clause ...) e1 e2 ...) @@ -8315,6 +8640,7 @@ guard-aux. (if test (begin result1 result2 ...) (guard-aux reraise clause1 clause2 ...))))) + (define-syntax case-lambda (syntax-rules () ((case-lambda (params body0 ...) ...) @@ -8340,9 +8666,13 @@ guard-aux. (cl . rest)))))) (cl (params body0 ...) ...))))))) +@end example + This definition of cond-expand does not interact with the features procedure. It requires that each feature identifier provided by the implementation be explicitly mentioned. +@example + (define-syntax cond-expand ;; Extend this to mention all feature ids and libraries (syntax-rules (and or not else r7rs library scheme base) @@ -8402,6 +8732,8 @@ that each feature identifier provided by the implementation be explicitly mentio more-clauses ...) (cond-expand more-clauses ...)))) +@end example + @node Appendices @chapter Appendices @@ -9205,6 +9537,8 @@ The procedure runge-kutta-4 takes a function, f, that produces a system derivative from a system state. It produces a function that takes a system state and produces a new system state. +@example + (define (runge-kutta-4 f h) (let ((*h (scale-vector h)) (*2 (scale-vector 2)) @@ -9244,20 +9578,34 @@ produces a new system state. (define add-vectors (elementwise +)) (define (scale-vector s) - (elementwise (lambda (x) (* x s)))) The map-streams procedure is analogous to map: it + (elementwise (lambda (x) (* x s)))) + +@end example + +The map-streams procedure is analogous to map: it applies its first argument (a procedure) to all the elements of its second argument (a stream). +@example + (define (map-streams f s) (cons (f (head s)) - (delay (map-streams f (tail s))))) Infinite streams are implemented as pairs whose car + (delay (map-streams f (tail s))))) + +@end example + +Infinite streams are implemented as pairs whose car holds the first element of the stream and whose cdr holds a promise to deliver the rest of the stream. +@example + (define head car) (define (tail stream) (force (cdr stream))) +@end example + The following illustrates the use of integrate-system in integrating the system C dvC = −iL vC @@ -9270,6 +9618,8 @@ The following illustrates the use of integrate-system in integrating the system which models a damped oscillator. +@example + (define (damped-oscillator R L C) (lambda (state) (let ((Vc (vector-ref state 0)) @@ -9283,6 +9633,8 @@ which models a damped oscillator. '#(1 0) .01)) +@end example + @node References @chapter References