2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-04 06:07:52 +01:00
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Scheme library functions
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-12 00:43:51 +01:00
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; helpers
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-02-28 06:31:08 +01:00
|
|
|
(define-syntax define-inline
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ (id v ...) rid expr)
|
|
|
|
(begin
|
|
|
|
(define-syntax id
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ v ...) expr] ; NB: do not use the same var twice!
|
2023-03-04 19:44:37 +01:00
|
|
|
[(_ . r) (rid . r)] ; NB: use syntax-error?
|
2023-02-28 06:31:08 +01:00
|
|
|
[_ rid]))
|
|
|
|
(define rid (lambda (v ...) expr)))]))
|
|
|
|
|
|
|
|
|
2023-03-12 00:43:51 +01:00
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Derived expression types
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
;cond
|
|
|
|
;case
|
|
|
|
;and
|
|
|
|
;or
|
|
|
|
;when
|
|
|
|
;unless
|
|
|
|
;cond-expand
|
|
|
|
|
|
|
|
;let -- including named let
|
|
|
|
;let*
|
|
|
|
;letrec
|
|
|
|
;letrec*
|
|
|
|
;let-values
|
|
|
|
;let*-values
|
|
|
|
|
|
|
|
;do
|
|
|
|
;delay
|
|
|
|
;delay-force
|
|
|
|
|
|
|
|
|
2023-02-28 06:31:08 +01:00
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Equivalence predicates
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-20 04:31:28 +01:00
|
|
|
; integrables:
|
|
|
|
;
|
|
|
|
; (eq? x y)
|
|
|
|
; (eqv? x y)
|
|
|
|
; (equal? x y)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
|
2023-03-12 00:43:51 +01:00
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Boxes, aka cells
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-20 04:31:28 +01:00
|
|
|
; integrables:
|
|
|
|
;
|
|
|
|
; (box? x)
|
|
|
|
; (box x)
|
|
|
|
; (unbox x)
|
|
|
|
; (set-box! x y)
|
2023-03-12 00:43:51 +01:00
|
|
|
|
|
|
|
|
2023-02-28 06:31:08 +01:00
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Exact integer numbers (fixnums)
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-20 04:31:28 +01:00
|
|
|
; integrables:
|
|
|
|
;
|
|
|
|
; (fixnum? x)
|
|
|
|
; (fxzero? x)
|
|
|
|
; (fxpositive? x)
|
|
|
|
; (fxnegative? x)
|
2023-03-20 18:49:00 +01:00
|
|
|
; (fx+ x ...)
|
|
|
|
; (fx* x ...)
|
|
|
|
; (fx- x y ...)
|
|
|
|
; (fx/ x y ...)
|
2023-03-20 04:31:28 +01:00
|
|
|
; (fxquotient x y)
|
|
|
|
; (fxremainder x y)
|
|
|
|
; (fxmodquo x y)
|
|
|
|
; (fxmodulo x y)
|
2023-03-20 23:47:10 +01:00
|
|
|
; (fxeucquo x y) a.k.a. euclidean-quotient, R6RS div
|
|
|
|
; (fxeucrem x y) a.k.a. euclidean-remainder, R6RS mod
|
2023-03-20 04:31:28 +01:00
|
|
|
; (fxneg x)
|
|
|
|
; (fxabs x)
|
2023-03-20 18:49:00 +01:00
|
|
|
; (fx<? x y z ...)
|
|
|
|
; (fx<=? x y z ...)
|
|
|
|
; (fx>? x y z ...)
|
|
|
|
; (fx>=? x y z ...)
|
|
|
|
; (fx=? x y z ...)
|
|
|
|
; (fx!=? x y)
|
2023-03-20 04:31:28 +01:00
|
|
|
; (fxmin x y)
|
|
|
|
; (fxmax x y)
|
|
|
|
; (fixnum->flonum x)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Inexact floating-point numbers (flonums)
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-20 04:31:28 +01:00
|
|
|
; integrables:
|
|
|
|
;
|
|
|
|
; (flonum? x)
|
|
|
|
; (flzero? x)
|
|
|
|
; (flpositive? x)
|
|
|
|
; (flnegative? x)
|
|
|
|
; (flinteger? x)
|
|
|
|
; (flnan? x)
|
|
|
|
; (flinfinite? x)
|
|
|
|
; (flfinite? x)
|
|
|
|
; (fleven? x)
|
|
|
|
; (flodd? x)
|
2023-03-20 18:49:00 +01:00
|
|
|
; (fl+ x ...)
|
|
|
|
; (fl* x ...)
|
|
|
|
; (fl- x y ...)
|
|
|
|
; (fl/ x y ...)
|
2023-03-20 04:31:28 +01:00
|
|
|
; (flneg x)
|
|
|
|
; (flabs x)
|
2023-03-20 18:49:00 +01:00
|
|
|
; (fl<? x y z ...)
|
|
|
|
; (fl<=? x y z ...)
|
|
|
|
; (fl>? x y z ...)
|
|
|
|
; (fl>=? x y z ...)
|
|
|
|
; (fl=? x y z ...)
|
2023-03-20 19:42:40 +01:00
|
|
|
; (fl!=? x y)
|
2023-03-20 04:31:28 +01:00
|
|
|
; (flmin x y)
|
|
|
|
; (flmax x y)
|
|
|
|
; (flonum->fixnum x)
|
2023-03-19 01:09:46 +01:00
|
|
|
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Numbers (fixnums or flonums)
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-20 19:42:40 +01:00
|
|
|
; integrables:
|
|
|
|
;
|
|
|
|
; (number? x)
|
|
|
|
; (integer? x)
|
2023-03-20 23:47:10 +01:00
|
|
|
; (complex? x) == number? what about inf and nan?
|
|
|
|
; (real? x) == number? what about inf and nan?
|
|
|
|
; (rational? x) == number? what about inf and nan?
|
|
|
|
; (exact-integer? x) == fixnum?
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
; (exact? x)
|
|
|
|
; (inexact? x)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-20 19:42:40 +01:00
|
|
|
; (finite? x)
|
|
|
|
; (infinite? x)
|
|
|
|
; (nan? x)
|
|
|
|
; (zero? x)
|
|
|
|
; (positive? x)
|
|
|
|
; (negative? x)
|
|
|
|
; (even? x)
|
|
|
|
; (odd? x)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-20 19:42:40 +01:00
|
|
|
; (+ x ...)
|
|
|
|
; (* x ...)
|
|
|
|
; (- x y ...)
|
|
|
|
; (/ x y ...)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-20 19:42:40 +01:00
|
|
|
; (< x y z ...)
|
|
|
|
; (<= x y z ...)
|
|
|
|
; (> x y z ...)
|
|
|
|
; (>= x y z ...)
|
|
|
|
; (= x y z ...)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-20 19:42:40 +01:00
|
|
|
; (abs x)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
; (truncate-quotient x y)
|
|
|
|
; (truncate-remainder x y)
|
|
|
|
; (quotient x y) == truncate-quotient
|
|
|
|
; (remainder x y) == truncate-remainder
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
; (floor-quotient x y)
|
|
|
|
; (floor-remainder x y)
|
|
|
|
; (modulo x y) = floor-remainder
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-07 23:48:27 +01:00
|
|
|
(define (floor/ x y)
|
2023-03-21 18:43:26 +01:00
|
|
|
(values (floor-quotient x y) (floor-remainder x y)))
|
2023-03-07 23:48:27 +01:00
|
|
|
|
|
|
|
(define (truncate/ x y)
|
2023-03-21 18:43:26 +01:00
|
|
|
(values (truncate-quotient x y) (truncate-remainder x y)))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Booleans
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-20 04:31:28 +01:00
|
|
|
; integrables:
|
|
|
|
;
|
|
|
|
; (boolean? x)
|
|
|
|
; (not x)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Characters
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-21 01:00:18 +01:00
|
|
|
; (char? x)
|
|
|
|
|
|
|
|
; (char-cmp c1 c2)
|
|
|
|
; (char=? c1 c2 c ...)
|
|
|
|
; (char<? c1 c2 c ...)
|
|
|
|
; (char>? c1 c2 c ...)
|
|
|
|
; (char<=? c1 c2 c ...)
|
|
|
|
; (char>=? c1 c2 c ...)
|
|
|
|
|
|
|
|
; (char-ci-cmp c1 c2)
|
|
|
|
; (char-ci=? c1 c2 c ...)
|
|
|
|
; (char-ci<? c1 c2 c ...)
|
|
|
|
; (char-ci>? c1 c2 c ...)
|
|
|
|
; (char-ci<=? c1 c2 c ...)
|
|
|
|
; (char-ci>=? c1 c2 c ...)
|
|
|
|
|
|
|
|
; (char-alphabetic? c)
|
|
|
|
; (char-numeric? x)
|
|
|
|
; (char-whitespace? c)
|
|
|
|
; (char-upper-case? c)
|
|
|
|
; (char-lower-case? c)
|
|
|
|
; (char-upcase c)
|
|
|
|
; (char-downcase c)
|
|
|
|
|
|
|
|
; (char->integer c)
|
|
|
|
; (integer->char n)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
;char-foldcase
|
|
|
|
;digit-value
|
|
|
|
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Symbols
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-21 01:00:18 +01:00
|
|
|
; (symbol? x)
|
|
|
|
; (symbol->string y)
|
|
|
|
; (string->symbol s)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Null and Pairs
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-20 04:31:28 +01:00
|
|
|
; integrables:
|
|
|
|
;
|
|
|
|
; (null? x)
|
|
|
|
; (pair? x)
|
|
|
|
; (car x)
|
|
|
|
; (set-car! x v)
|
|
|
|
; (cdr x)
|
|
|
|
; (set-cdr! x v)
|
|
|
|
; (caar x) ... (cddddr x)
|
|
|
|
; (cons x y)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Lists
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
; (list? x)
|
2023-03-21 03:32:33 +01:00
|
|
|
; (list x ...)
|
2023-03-21 18:43:26 +01:00
|
|
|
; (make-list n (i #f))
|
2023-03-20 23:47:10 +01:00
|
|
|
; (length l)
|
|
|
|
; (list-ref l i)
|
2023-03-21 01:00:18 +01:00
|
|
|
; (list-set! l i x)
|
|
|
|
; (list-cat l1 l2)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-21 18:43:26 +01:00
|
|
|
(define (%append . args)
|
|
|
|
(let loop ([args args])
|
|
|
|
(cond [(null? args) '()]
|
|
|
|
[(null? (cdr args)) (car args)]
|
|
|
|
[else (list-cat (car args) (loop (cdr args)))])))
|
|
|
|
|
2023-02-28 06:31:08 +01:00
|
|
|
(define-syntax append
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_) '()] [(_ x) x]
|
2023-03-21 01:00:18 +01:00
|
|
|
[(_ x y) (list-cat x y)]
|
|
|
|
[(_ x y z ...) (list-cat x (append y z ...))]
|
2023-03-21 18:43:26 +01:00
|
|
|
[_ %append]))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
; (memq v l)
|
|
|
|
; (memv v l) ; TODO: make sure memv checks list
|
|
|
|
; (meme v l) ; TODO: make sure meme checks list
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
(define (%member v l . ?eq)
|
|
|
|
(if (null? ?eq)
|
|
|
|
(meme v l)
|
|
|
|
(let loop ([v v] [l l] [eq (car ?eq)])
|
|
|
|
(and (pair? l)
|
|
|
|
(if (eq v (car l))
|
|
|
|
l
|
|
|
|
(loop v (cdr l) eq))))))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
(define-syntax member
|
|
|
|
(syntax-rules ()
|
2023-03-20 23:47:10 +01:00
|
|
|
[(_ v l) (meme v l)]
|
|
|
|
[(_ . args) (%member . args)]
|
|
|
|
[_ %member]))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
; (assq v y)
|
|
|
|
; (assv v y) ; TODO: make sure assv checks list
|
|
|
|
; (asse v y) ; TODO: make sure asse checks list
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
(define (%assoc v al . ?eq)
|
|
|
|
(if (null? ?eq)
|
|
|
|
(asse v al)
|
|
|
|
(let loop ([v v] [al al] [eq (car ?eq)])
|
|
|
|
(and (pair? al)
|
|
|
|
(if (eq v (caar al))
|
|
|
|
(car al)
|
|
|
|
(loop v (cdr al) eq))))))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
(define-syntax assoc
|
|
|
|
(syntax-rules ()
|
2023-03-20 23:47:10 +01:00
|
|
|
[(_ v al) (asse v al)]
|
|
|
|
[(_ . args) (%assoc . args)]
|
|
|
|
[_ %assoc]))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-07 01:36:15 +01:00
|
|
|
(define-inline (list-copy x) %residual-list-copy (%lcat x '()))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
; (list-tail l i)
|
|
|
|
; (last-pair l)
|
|
|
|
; (reverse l)
|
|
|
|
; (reverse! l)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-21 18:43:26 +01:00
|
|
|
(define (%list* x . l)
|
|
|
|
(let loop ([x x] [l l])
|
|
|
|
(if (null? l) x (cons x (loop (car l) (cdr l))))))
|
|
|
|
|
2023-02-28 06:31:08 +01:00
|
|
|
(define-syntax list*
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ x) x]
|
2023-03-19 19:52:49 +01:00
|
|
|
[(_ x y) (cons x y)]
|
|
|
|
[(_ x y z ...) (cons x (list* y z ...))]
|
2023-03-21 18:43:26 +01:00
|
|
|
[(_ . args) (%list* . args)]
|
|
|
|
[_ %list*]))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
(define-syntax cons* list*)
|
|
|
|
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Vectors
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-21 01:00:18 +01:00
|
|
|
; (vector? x)
|
2023-03-21 03:32:33 +01:00
|
|
|
; (vector x ...)
|
2023-03-21 01:00:18 +01:00
|
|
|
; (make-vector n (i #f))
|
|
|
|
; (vector-length v)
|
|
|
|
; (vector-ref v i)
|
|
|
|
; (vector-set! v i x)
|
|
|
|
; (list->vector x)
|
|
|
|
; (vector-cat v1 v2)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-07 23:48:27 +01:00
|
|
|
(define (subvector->list vec start end)
|
|
|
|
(let loop ([i (fx- end 1)] [l '()])
|
|
|
|
(if (fx<? i start) l (loop (fx- i 1) (cons (vector-ref vec i) l)))))
|
|
|
|
|
2023-03-21 01:00:18 +01:00
|
|
|
(define %vector->list
|
2023-03-07 23:48:27 +01:00
|
|
|
(case-lambda
|
2023-03-21 18:43:26 +01:00
|
|
|
[(vec) (%vector->list1 vec)]
|
2023-03-07 23:48:27 +01:00
|
|
|
[(vec start) (subvector->list vec start (vector-length vec))]
|
|
|
|
[(vec start end) (subvector->list vec start end)]))
|
|
|
|
|
2023-03-21 01:00:18 +01:00
|
|
|
(define-syntax vector->list
|
|
|
|
(syntax-rules ()
|
2023-03-21 18:43:26 +01:00
|
|
|
[(_ x) (%vector->list1 x)]
|
2023-03-21 01:00:18 +01:00
|
|
|
[(_ . r) (%vector->list . r)]
|
|
|
|
[_ %vector->list]))
|
|
|
|
|
2023-03-07 23:48:27 +01:00
|
|
|
(define (subvector-copy! to at from start end)
|
|
|
|
(let ([limit (fxmin end (fx+ start (fx- (vector-length to) at)))])
|
|
|
|
(if (fx<=? at start)
|
|
|
|
(do ([i at (fx+ i 1)] [j start (fx+ j 1)])
|
|
|
|
[(fx>=? j limit)]
|
|
|
|
(vector-set! to i (vector-ref from j)))
|
|
|
|
(do ([i (fx+ at (fx- (fx- end start) 1)) (fx- i 1)] [j (fx- limit 1) (fx- j 1)])
|
|
|
|
[(fx<? j start)]
|
|
|
|
(vector-set! to i (vector-ref from j))))))
|
|
|
|
|
|
|
|
(define vector-copy!
|
|
|
|
(case-lambda
|
|
|
|
[(to at from) (subvector-copy! to at from 0 (vector-length from))]
|
|
|
|
[(to at from start) (subvector-copy! to at from start (vector-length from))]
|
|
|
|
[(to at from start end) (subvector-copy! to at from start end)]))
|
|
|
|
|
|
|
|
(define (subvector vec start end) ; TODO: %vsub?
|
|
|
|
(let ([v (make-vector (fx- end start))])
|
|
|
|
(subvector-copy! v 0 vec start end)
|
|
|
|
v))
|
|
|
|
|
|
|
|
(define vector-copy
|
|
|
|
(case-lambda
|
|
|
|
[(vec) (subvector vec 0 (vector-length vec))] ; TODO: %vcpy ?
|
|
|
|
[(vec start) (subvector vec start (vector-length vec))]
|
|
|
|
[(vec start end) (subvector vec start end)]))
|
|
|
|
|
|
|
|
(define (subvector-fill! vec x start end)
|
|
|
|
(do ([i start (fx+ i 1)]) [(fx>=? i end)] (vector-set! vec i x)))
|
|
|
|
|
|
|
|
(define vector-fill!
|
|
|
|
(case-lambda
|
|
|
|
[(vec x) (subvector-fill! vec x 0 (vector-length vec))]
|
|
|
|
[(vec x start) (subvector-fill! vec x start (vector-length vec))]
|
|
|
|
[(vec x start end) (subvector-fill! vec x start end)]))
|
|
|
|
|
|
|
|
(define (subvector-string-copy! to at from start end)
|
|
|
|
(let ([limit (fxmin end (fx+ start (fx- (string-length to) at)))])
|
|
|
|
(do ([i at (fx+ i 1)] [j start (fx+ j 1)])
|
|
|
|
[(fx>=? j limit) to]
|
|
|
|
(string-set! to i (vector-ref from j)))))
|
|
|
|
|
|
|
|
(define (subvector->string vec start end)
|
|
|
|
(subvector-string-copy! (make-string (fx- end start)) 0 vec start end))
|
|
|
|
|
|
|
|
(define vector->string
|
|
|
|
(case-lambda
|
|
|
|
[(vec) (subvector->string vec 0 (vector-length vec))]
|
|
|
|
[(vec start) (subvector->string vec start (vector-length vec))]
|
|
|
|
[(vec start end) (subvector->string vec start end)]))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-08 19:03:39 +01:00
|
|
|
(define (vectors-sum-length vecs)
|
|
|
|
(let loop ([vecs vecs] [l 0])
|
|
|
|
(if (null? vecs) l (loop (cdr vecs) (fx+ l (vector-length (car vecs)))))))
|
|
|
|
|
|
|
|
(define (vectors-copy-into! to vecs)
|
|
|
|
(let loop ([vecs vecs] [i 0])
|
|
|
|
(if (null? vecs)
|
|
|
|
to
|
|
|
|
(let ([vec (car vecs)] [vecs (cdr vecs)])
|
|
|
|
(let ([len (vector-length vec)])
|
|
|
|
(subvector-copy! to i vec 0 len)
|
|
|
|
(loop vecs (fx+ i len)))))))
|
|
|
|
|
2023-03-21 01:00:18 +01:00
|
|
|
(define (%vector-append . vecs)
|
2023-03-08 19:03:39 +01:00
|
|
|
(vectors-copy-into! (make-vector (vectors-sum-length vecs)) vecs))
|
|
|
|
|
|
|
|
(define-syntax vector-append
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_) '#()] [(_ x) (%ckv x)]
|
2023-03-21 01:00:18 +01:00
|
|
|
[(_ x y) (vector-cat x y)]
|
|
|
|
[(_ . r) (%vector-append . r)]
|
|
|
|
[_ %vector-append]))
|
2023-03-08 19:03:39 +01:00
|
|
|
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Strings
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-21 01:00:18 +01:00
|
|
|
; (string? x)
|
2023-03-21 03:32:33 +01:00
|
|
|
; (string c ...)
|
2023-03-21 01:00:18 +01:00
|
|
|
; (make-string n (i #\space))
|
|
|
|
; (string-length s)
|
|
|
|
; (string-ref x i)
|
2023-03-21 03:32:33 +01:00
|
|
|
; (string-set! x i v)
|
2023-03-21 01:00:18 +01:00
|
|
|
; (list->string l)
|
|
|
|
; (string-cat s1 s2)
|
|
|
|
; (substring s from to)
|
2023-03-07 23:48:27 +01:00
|
|
|
|
|
|
|
(define (substring->list str start end)
|
|
|
|
(let loop ([i (fx- end 1)] [l '()])
|
|
|
|
(if (fx<? i start) l (loop (fx- i 1) (cons (string-ref str i) l)))))
|
|
|
|
|
2023-03-21 01:00:18 +01:00
|
|
|
(define %string->list
|
2023-03-07 23:48:27 +01:00
|
|
|
(case-lambda
|
2023-03-21 18:43:26 +01:00
|
|
|
[(str) (%string->list1 str)]
|
2023-03-07 23:48:27 +01:00
|
|
|
[(str start) (substring->list str start (string-length str))]
|
|
|
|
[(str start end) (substring->list str start end)]))
|
|
|
|
|
2023-03-21 01:00:18 +01:00
|
|
|
(define-syntax string->list
|
|
|
|
(syntax-rules ()
|
2023-03-21 18:43:26 +01:00
|
|
|
[(_ x) (%string->list1 x)]
|
2023-03-21 01:00:18 +01:00
|
|
|
[(_ . r) (%string->list . r)]
|
|
|
|
[_ %string->list]))
|
|
|
|
|
2023-03-07 23:48:27 +01:00
|
|
|
(define (substring-copy! to at from start end)
|
|
|
|
(let ([limit (fxmin end (fx+ start (fx- (string-length to) at)))])
|
|
|
|
(if (fx<=? at start)
|
|
|
|
(do ([i at (fx+ i 1)] [j start (fx+ j 1)])
|
|
|
|
[(fx>=? j limit)]
|
|
|
|
(string-set! to i (string-ref from j)))
|
|
|
|
(do ([i (fx+ at (fx- (fx- end start) 1)) (fx- i 1)] [j (fx- limit 1) (fx- j 1)])
|
|
|
|
[(fx<? j start)]
|
|
|
|
(string-set! to i (string-ref from j))))))
|
|
|
|
|
|
|
|
(define string-copy!
|
|
|
|
(case-lambda
|
|
|
|
[(to at from) (substring-copy! to at from 0 (string-length from))]
|
|
|
|
[(to at from start) (substring-copy! to at from start (string-length from))]
|
|
|
|
[(to at from start end) (substring-copy! to at from start end)]))
|
|
|
|
|
|
|
|
(define string-copy
|
|
|
|
(case-lambda
|
|
|
|
[(str) (substring str 0 (string-length str))] ; TODO: %scpy ?
|
|
|
|
[(str start) (substring str start (string-length str))]
|
|
|
|
[(str start end) (substring str start end)]))
|
|
|
|
|
|
|
|
(define (substring-fill! str c start end)
|
|
|
|
(do ([i start (fx+ i 1)]) [(fx>=? i end)] (string-set! str i c)))
|
|
|
|
|
|
|
|
(define string-fill!
|
|
|
|
(case-lambda
|
|
|
|
[(str c) (substring-fill! str c 0 (string-length str))]
|
|
|
|
[(str c start) (substring-fill! str c start (string-length str))]
|
|
|
|
[(str c start end) (substring-fill! str c start end)]))
|
|
|
|
|
|
|
|
(define (substring-vector-copy! to at from start end)
|
|
|
|
(let ([limit (fxmin end (fx+ start (fx- (vector-length to) at)))])
|
|
|
|
(do ([i at (fx+ i 1)] [j start (fx+ j 1)])
|
|
|
|
[(fx>=? j limit) to]
|
|
|
|
(vector-set! to i (string-ref from j)))))
|
|
|
|
|
|
|
|
(define (substring->vector str start end)
|
|
|
|
(substring-vector-copy! (make-vector (fx- end start)) 0 str start end))
|
|
|
|
|
|
|
|
(define string->vector
|
|
|
|
(case-lambda
|
|
|
|
[(str) (substring->vector str 0 (string-length str))]
|
|
|
|
[(str start) (substring->vector str start (string-length str))]
|
|
|
|
[(str start end) (substring->vector str start end)]))
|
|
|
|
|
2023-03-08 19:03:39 +01:00
|
|
|
(define (strings-sum-length strs)
|
|
|
|
(let loop ([strs strs] [l 0])
|
|
|
|
(if (null? strs) l (loop (cdr strs) (fx+ l (string-length (car strs)))))))
|
|
|
|
|
|
|
|
(define (strings-copy-into! to strs)
|
|
|
|
(let loop ([strs strs] [i 0])
|
|
|
|
(if (null? strs)
|
|
|
|
to
|
|
|
|
(let ([str (car strs)] [strs (cdr strs)])
|
|
|
|
(let ([len (string-length str)])
|
|
|
|
(substring-copy! to i str 0 len)
|
|
|
|
(loop strs (fx+ i len)))))))
|
|
|
|
|
2023-03-21 01:00:18 +01:00
|
|
|
(define (%string-append . strs)
|
2023-03-08 19:03:39 +01:00
|
|
|
(strings-copy-into! (make-string (strings-sum-length strs)) strs))
|
|
|
|
|
|
|
|
(define-syntax string-append
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_) ""] [(_ x) (%cks x)]
|
2023-03-21 01:00:18 +01:00
|
|
|
[(_ x y) (string-cat x y)]
|
|
|
|
[(_ . r) (%string-append . r)]
|
|
|
|
[_ %string-append]))
|
|
|
|
|
|
|
|
; (string-cmp s1 s2)
|
|
|
|
; (string=? s1 s2 s ...)
|
|
|
|
; (string<? s1 s2 s ...)
|
|
|
|
; (string>? s1 s2 s ...)
|
|
|
|
; (string<=? s1 s2 s ...)
|
|
|
|
; (string>=? s1 s2 s ...)
|
|
|
|
|
|
|
|
; (string-ci-cmp s1 s2)
|
|
|
|
; (string-ci=? s1 s2 s ...)
|
|
|
|
; (string-ci<? s1 s2 s ...)
|
|
|
|
; (string-ci>? s1 s2 s ...)
|
|
|
|
; (string-ci<=? s1 s2 s ...)
|
|
|
|
; (string-ci>=? s1 s2 s ...)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
;string-upcase
|
|
|
|
;string-downcase
|
|
|
|
;string-foldcase
|
|
|
|
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Conversions
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-20 21:43:06 +01:00
|
|
|
; (fixnum->string x (r 10))
|
2023-03-20 23:47:10 +01:00
|
|
|
; (string->fixnum s (r 10))
|
2023-03-20 21:43:06 +01:00
|
|
|
; (flonum->string x)
|
2023-03-20 23:47:10 +01:00
|
|
|
; (string->flonum s)
|
|
|
|
; (number->string x (r 10))
|
|
|
|
; (string->number s (r 10))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Control features
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-21 01:00:18 +01:00
|
|
|
; (procedure? x)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-21 18:43:26 +01:00
|
|
|
(define (%apply p x . l)
|
|
|
|
(apply-to-list p
|
|
|
|
(let loop ([x x] [l l])
|
|
|
|
(if (null? l) x (cons x (loop (car l) (cdr l)))))))
|
|
|
|
|
2023-02-28 06:31:08 +01:00
|
|
|
(define-syntax apply
|
|
|
|
(syntax-rules ()
|
2023-03-21 18:43:26 +01:00
|
|
|
[(_ p l) (apply-to-list p l)]
|
|
|
|
[(_ p a b ... l) (apply-to-list p (list* a b ... l))]
|
|
|
|
[(_ . args) (%apply . args)]
|
|
|
|
[_ %apply]))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-21 18:43:26 +01:00
|
|
|
; (%call/cc p)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-21 18:43:26 +01:00
|
|
|
(define-syntax call/cc
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ p) (letcc k (p k))]
|
|
|
|
[(_ . args) (%call/cc . args)]
|
|
|
|
[_ %call/cc]))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-21 18:43:26 +01:00
|
|
|
(define-syntax call-with-current-continuation call/cc)
|
2023-03-06 21:53:37 +01:00
|
|
|
|
2023-03-21 18:43:26 +01:00
|
|
|
; (values x ...)
|
|
|
|
; (call-with-values thunk receiver)
|
|
|
|
|
|
|
|
(define (%map1 p l)
|
|
|
|
(let loop ([l l] [r '()])
|
|
|
|
(if (pair? l)
|
|
|
|
(loop (cdr l) (cons (p (car l)) r))
|
|
|
|
(reverse! r))))
|
|
|
|
|
|
|
|
(define (%map2 p l1 l2)
|
|
|
|
(let loop ([l1 l1] [l2 l2] [r '()])
|
|
|
|
(if (and (pair? l1) (pair? l2))
|
|
|
|
(loop (cdr l1) (cdr l2) (cons (p (car l1) (car l2)) r))
|
|
|
|
(reverse! r))))
|
|
|
|
|
|
|
|
(define (%map p l . l*)
|
|
|
|
(cond [(null? l*) (%map1 p l)]
|
|
|
|
[(null? (cdr l*)) (%map2 p l (car l*))]
|
|
|
|
[else
|
|
|
|
(let loop ([l* (cons l l*)] [r '()])
|
|
|
|
(if (let lp ([l* l*])
|
|
|
|
(or (null? l*) (and (pair? (car l*)) (lp (cdr l*)))))
|
|
|
|
(loop (%map1 cdr l*) (cons (apply p (%map1 car l*)) r))
|
|
|
|
(reverse! r)))]))
|
2023-03-06 21:53:37 +01:00
|
|
|
|
|
|
|
(define-syntax map
|
|
|
|
(syntax-rules ()
|
2023-03-21 18:43:26 +01:00
|
|
|
[(_ p l) (%map1 p l)]
|
|
|
|
[(_ p l1 l2) (%map2 p l1 l2)]
|
|
|
|
[(_ . args) (%map . args)]
|
|
|
|
[_ %map]))
|
|
|
|
|
|
|
|
(define (%for-each1 p l)
|
|
|
|
(let loop ([l l])
|
|
|
|
(if (pair? l)
|
|
|
|
(begin (p (car l))
|
|
|
|
(loop (cdr l))))))
|
|
|
|
|
|
|
|
(define (%for-each2 p l1 l2)
|
|
|
|
(let loop ([l1 l1] [l2 l2])
|
|
|
|
(if (and (pair? l1) (pair? l2))
|
|
|
|
(begin (p (car l1) (car l2))
|
|
|
|
(loop (cdr l1) (cdr l2))))))
|
|
|
|
|
|
|
|
(define (%for-each p l . l*)
|
|
|
|
(cond [(null? l*) (%for-each1 p l)]
|
|
|
|
[(null? (cdr l*)) (%for-each2 p l (car l*))]
|
|
|
|
[else
|
|
|
|
(let loop ([l* (cons l l*)])
|
|
|
|
(if (let lp ([l* l*])
|
|
|
|
(or (null? l*) (and (pair? (car l*)) (lp (cdr l*)))))
|
|
|
|
(begin (apply p (map car l*)) (loop (map cdr l*)))))]))
|
2023-03-06 21:53:37 +01:00
|
|
|
|
|
|
|
(define-syntax for-each
|
|
|
|
(syntax-rules ()
|
2023-03-21 18:43:26 +01:00
|
|
|
[(_ p l) (%for-each1 p l)]
|
|
|
|
[(_ p l1 l2) (%for-each2 p l1 l2)]
|
|
|
|
[(_ . args) (%for-each . args)]
|
|
|
|
[_ %for-each]))
|
2023-03-06 21:53:37 +01:00
|
|
|
|
|
|
|
(define (string-map p s . s*)
|
|
|
|
(if (null? s*)
|
|
|
|
(let* ([len (string-length s)] [res (make-string len)])
|
|
|
|
(do ([i 0 (fx+ i 1)]) [(fx>=? i len) res]
|
|
|
|
(string-set! res i (p (string-ref s i)))))
|
|
|
|
(list->string (apply map p (map string->list (cons s s*))))))
|
|
|
|
|
|
|
|
(define (vector-map p v . v*)
|
|
|
|
(if (null? v*)
|
|
|
|
(let* ([len (vector-length v)] [res (make-vector len)])
|
|
|
|
(do ([i 0 (fx+ i 1)]) [(fx>=? i len) res]
|
|
|
|
(vector-set! res i (p (vector-ref v i)))))
|
|
|
|
(list->vector (apply map p (map vector->list (cons v v*))))))
|
|
|
|
|
|
|
|
(define (string-for-each p s . s*)
|
|
|
|
(if (null? s*)
|
|
|
|
(let ([len (string-length s)])
|
|
|
|
(do ([i 0 (fx+ i 1)]) [(fx>=? i len)] (p (string-ref s i))))
|
|
|
|
(apply for-each p (map string->list (cons s s*)))))
|
|
|
|
|
|
|
|
(define (vector-for-each p v . v*)
|
|
|
|
(if (null? v*)
|
|
|
|
(let ([len (vector-length v)])
|
|
|
|
(do ([i 0 (fx+ i 1)]) [(fx>=? i len)] (p (vector-ref v i))))
|
|
|
|
(apply for-each p (map vector->list (cons v v*)))))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; I/O Ports
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
; (input-port? x)
|
|
|
|
; (output-port? x)
|
|
|
|
; (input-port-open? p)
|
|
|
|
; (output-port-open? p)
|
|
|
|
; (current-input-port)
|
|
|
|
; (current-output-port)
|
|
|
|
; (current-error-port)
|
|
|
|
; (open-output-string)
|
|
|
|
; (open-input-file s)
|
|
|
|
; (open-output-file x)
|
|
|
|
; (open-input-string x)
|
|
|
|
; (close-input-port x)
|
|
|
|
; (close-output-port x)
|
|
|
|
; (get-output-string x)
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-07 05:52:38 +01:00
|
|
|
(define (port? x) (or (input-port? x) (output-port? x)))
|
|
|
|
|
|
|
|
(define (close-port p)
|
|
|
|
(if (input-port? p) (close-input-port p))
|
|
|
|
(if (output-port? p) (close-output-port p)))
|
|
|
|
|
|
|
|
(define (call-with-port port proc)
|
|
|
|
(call-with-values (lambda () (proc port))
|
|
|
|
(lambda vals (close-port port) (apply values vals))))
|
|
|
|
|
|
|
|
(define (call-with-input-file fname proc)
|
|
|
|
(call-with-port (open-input-file fname) proc))
|
|
|
|
|
|
|
|
(define (call-with-output-file fname proc)
|
|
|
|
(call-with-port (open-output-file fname) proc))
|
|
|
|
|
|
|
|
;with-input-from-file -- requires parameterize
|
|
|
|
;with-output-to-file -- requires parameterize
|
2023-03-06 21:53:37 +01:00
|
|
|
;open-binary-input-file
|
|
|
|
;open-binary-output-file
|
|
|
|
;open-input-bytevector
|
|
|
|
;open-output-bytevector
|
|
|
|
;get-output-bytevector
|
|
|
|
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Input
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-07 05:52:38 +01:00
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
; (read-char (p (current-input-port)))
|
|
|
|
; (peek-char (p (current-input-port)))
|
|
|
|
; (char-ready? (p (current-input-port)))
|
2023-03-07 05:52:38 +01:00
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
(define (read-line . ?p)
|
|
|
|
(let ([p (if (null? ?p) (current-input-port) (car ?p))]
|
|
|
|
[op (open-output-string)])
|
2023-03-07 05:52:38 +01:00
|
|
|
(let loop ([read-nothing? #t])
|
2023-03-20 23:47:10 +01:00
|
|
|
(let ([c (read-char p)])
|
|
|
|
(cond [(or (eof-object? c) (char=? c #\newline))
|
|
|
|
(if (and (eof-object? c) read-nothing?)
|
|
|
|
c
|
|
|
|
(let ([s (get-output-string op)])
|
|
|
|
(close-output-port op)
|
|
|
|
s))]
|
2023-03-07 05:52:38 +01:00
|
|
|
[(char=? c #\return) (loop #f)]
|
2023-03-20 23:47:10 +01:00
|
|
|
[else (write-char c op) (loop #f)])))))
|
2023-03-07 05:52:38 +01:00
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
; (eof-object? x)
|
|
|
|
; (eof-object)
|
2023-03-07 05:52:38 +01:00
|
|
|
|
2023-03-06 21:53:37 +01:00
|
|
|
;read
|
|
|
|
;read-string
|
|
|
|
;read-u8
|
|
|
|
;peek-u8
|
|
|
|
;u8-ready?
|
|
|
|
;read-bytevector
|
|
|
|
;read-bytevector!
|
|
|
|
|
|
|
|
|
2023-02-28 06:31:08 +01:00
|
|
|
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Output
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
2023-03-20 23:47:10 +01:00
|
|
|
|
|
|
|
; (write-char c (p (current-output-port)))
|
|
|
|
; (write-string s (p (current-output-port)))
|
|
|
|
; (display x (p (current-output-port)))
|
|
|
|
; (write x (p (current-output-port)))
|
|
|
|
; (newline (p (current-output-port)))
|
|
|
|
; (write-shared x (p (current-output-port)))
|
|
|
|
; (write-simple x (p (current-output-port)))
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-07 05:52:38 +01:00
|
|
|
;flush-output-port
|
|
|
|
|
2023-02-28 06:31:08 +01:00
|
|
|
|
2023-03-06 21:53:37 +01:00
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; System interface
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
;load
|
|
|
|
;file-exists?
|
|
|
|
;delete-file
|
|
|
|
;command-line
|
|
|
|
;exit
|
|
|
|
;emergency-exit
|
|
|
|
;get-environment-variable
|
|
|
|
;get-environment-variables
|
|
|
|
;current-second
|
|
|
|
;current-jiffy
|
|
|
|
;jiffies-per-second
|
|
|
|
;features
|
|
|
|
|
|
|
|
|
2023-02-28 06:31:08 +01:00
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
; Residual versions of vararg procedures
|
|
|
|
;---------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
(define-syntax nullary-unary-adaptor
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ f)
|
|
|
|
(lambda args
|
|
|
|
(if (null? args) (f) (f (car args))))]))
|
|
|
|
|
|
|
|
(define-syntax nullary-unary-binary-adaptor
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ f)
|
|
|
|
(lambda args
|
|
|
|
(if (null? args) (f) (if (null? (cdr args)) (f (car args)) (f (car args) (cadr args)))))]))
|
|
|
|
|
|
|
|
(define-syntax unary-binary-adaptor
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ f)
|
|
|
|
(lambda (x . args)
|
|
|
|
(if (null? args) (f x) (f x (car args))))]))
|
|
|
|
|
|
|
|
(define-syntax unary-binary-ternary-adaptor
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ f)
|
|
|
|
(lambda (x . args)
|
|
|
|
(if (null? args) (f x) (if (null? (cdr args)) (f x (car args)) (f x (car args) (cadr args)))))]))
|
|
|
|
|
|
|
|
(define-syntax unary-binary-ternary-quaternary-adaptor
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ f)
|
|
|
|
(lambda (x . args)
|
|
|
|
(if (null? args) (f x) (if (null? (cdr args)) (f x (car args))
|
|
|
|
(if (null? (cddr args)) (f x (car args) (cadr args)) (f x (car args) (cadr args) (caddr args))))))]))
|
|
|
|
|
|
|
|
(define-syntax binary-ternary-adaptor
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ f)
|
|
|
|
(lambda (x y . args)
|
|
|
|
(if (null? args) (f x y) (f x y (car args))))]))
|
|
|
|
|
|
|
|
(define-syntax cmp-reducer
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ f)
|
|
|
|
(lambda args
|
|
|
|
(or (null? args)
|
|
|
|
(let loop ([x (car args)] [args (cdr args)])
|
|
|
|
(or (null? args)
|
|
|
|
(let ([y (car args)])
|
|
|
|
(and (f x y) (loop y (cdr args))))))))]))
|
|
|
|
|
|
|
|
(define-syntax minmax-reducer
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ f)
|
|
|
|
(lambda (x . args)
|
|
|
|
(let loop ([x x] [args args])
|
|
|
|
(if (null? args)
|
|
|
|
x
|
|
|
|
(loop (f x (car args)) (cdr args)))))]))
|
|
|
|
|
|
|
|
(define-syntax addmul-reducer
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ f s)
|
|
|
|
(lambda args
|
|
|
|
(if (null? args)
|
|
|
|
s
|
|
|
|
(let loop ([x (car args)] [args (cdr args)])
|
|
|
|
(if (null? args)
|
|
|
|
x
|
|
|
|
(loop (f x (car args)) (cdr args))))))]))
|
|
|
|
|
|
|
|
(define-syntax subdiv-reducer
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ f)
|
|
|
|
(lambda (x . args)
|
|
|
|
(if (null? args)
|
|
|
|
(f x)
|
|
|
|
(let loop ([x x] [args args])
|
|
|
|
(if (null? args)
|
|
|
|
x
|
|
|
|
(loop (f x (car args)) (cdr args))))))]))
|
|
|
|
|
|
|
|
(define-syntax append-reducer
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ f s)
|
|
|
|
(lambda args
|
|
|
|
(let loop ([args args])
|
|
|
|
(cond [(null? args) s]
|
|
|
|
[(null? (cdr args)) (car args)]
|
|
|
|
[else (f (car args) (loop (cdr args)))])))]))
|
|
|
|
|
|
|
|
(define %residual-append (append-reducer append '()))
|