The Little Schemer

Friedman, Daniel P. and Felleisen, Matthias and Bibby, Duane, 1996. The Little Schemer. 4th edition, The MIT Press,

test/base/combinators: pass

(define (test/base/combinators _)
  (⊦= 7 ((K 7) 1 2))
  (⊦= '(1 2) (receive ((K* 1 2) 'x)))
  (⊦= 6 (((S* +) (λ (x) (* 2 x))) 2))
  (⊦= '(3 5 7) (mappair + '(1 2 3 4)))
  (⊦= '() (mappair + '(1)))
  (⊦= '(1 2 3) (foldr/concat '((1) () (2 3))))
  (⊦= #t (foldr/and '(1 2 3)))
  (⊦= #f (foldr/and '(1 #f 3)))
  (⊦= 2 (foldr/or '(#f 2 3)))
  (⊦= #f (foldr/or '(#f #f)))
  (⊦= 12 (((curry₁ *) 3) 4))
  (⊦= '(1 . 2) ((Λ (,a ,b) (cons a b)) 1 2))
  (⊦= 6 ((((λ-curry (a b c) (+ a b c)) 1) 2) 3)))
((eta 0.0) (memory #(12582912 2856384 1048576)) (stdout "") (stderr ""))

test/define-many: pass

(define (test/define-many _)
  (define-many (a b c) (1 2 3))
  (⊦= 1 a)
  (⊦= 2 b)
  (⊦= 3 c))
((eta 0.0) (memory #(12582912 2857672 1048576)) (stdout "") (stderr ""))

test/let1: pass

(define (test/let1 _) (let1 (a 1) (⊦= a 1)))
((eta 0.0) (memory #(12582912 2858928 1048576)) (stdout "") (stderr ""))

test/letcar&cdr: pass

(define (test/letcar&cdr _)
  (letcar&cdr
    (((a d) (cons 1 '())) ((aa dd) (cons 2 3)))
    (⊦= a 1)
    (⊦= d '())
    (⊦= aa 2)
    (⊦= dd 3)))
((eta 0.0) (memory #(12582912 2860104 1048576)) (stdout "") (stderr ""))

test/λ: pass

(define (test/λ _)
  (⊦= 5 ((λ (x) (+ x 2)) 3))
  (⊦= 5 ((λ (x) ((λ (y) (+ x y)) 2)) 3))
  (⊦= 5 ((λ (x y) (+ x y)) 2 3)))
((eta 0.0) (memory #(12582912 2861048 1048576)) (stdout "") (stderr ""))

test/μ: pass

Curried: one variable per application, so no variables at all is a thunk, as with τ.

(define (test/μ _)
  (⊦= 42 ((μ () 42)))
  (⊦= 5 ((μ x (+ x 2)) 3))
  (⊦= 5 (((μ (x y) (+ x y)) 2) 3)))
((eta 0.0) (memory #(12582912 2862200 1048576)) (stdout "") (stderr ""))

test/letmaptensor: pass

(define (test/letmaptensor _)
  (⊦= '((((2 a #t) (2 a #t)) ((2 1 #t) (2 1 #f)))
        (((3 a #f) (3 a #t)) ((3 2 #f) (3 2 #f)))
        (((4 a #t) (4 a #t)) ((4 3 #t) (4 3 #f))))
      (letmaptensor
        ((x (list 1 2 3)) (y `(a ,x)) (z (list (odd? x) (symbol? y))))
        (list (add1 x) y z))))
((eta 0.0) (memory #(12582912 2863320 1048576)) (stdout "") (stderr ""))

test/letmap: pass

(define (test/letmap _)
  (⊦= '((2 a #t)
        (2 a #t)
        (2 1 #t)
        (2 1 #f)
        (3 a #f)
        (3 a #t)
        (3 2 #f)
        (3 2 #f)
        (4 a #t)
        (4 a #t)
        (4 3 #t)
        (4 3 #f))
      (letmap
        ((x (list 1 2 3)) (y `(a ,x)) (z (list (odd? x) (symbol? y))))
        (list (add1 x) y z))))
((eta 0.0) (memory #(12582912 2864464 1048576)) (stdout "") (stderr ""))

test/procc/λ-memo: pass

(define (test/procc/λ-memo _)
  (define count 0)
  (define fib
    (λ (n)
       (add1! count)
       (cond ((< n 2) n)
             (else (let1 (m (sub1 n)) (+ (fib m) (fib (sub1 m))))))))
  (let1 (v (fib 10)) (⊦= 55 v) (⊦= 177 count))
  (set! count 0)
  (define fib-memo
    (λ-memo
      (n)
      (add1! count)
      (cond ((< n 2) n)
            (else (let1 (m (sub1 n)) (+ (fib-memo m) (fib-memo (sub1 m))))))))
  (let1 (v (fib-memo 10)) (⊦= 55 v) (⊦= 11 count)))
((eta 0.0) (memory #(12582912 2859768 1048576)) (stdout "") (stderr ""))

test/pairwise-different?: pass

Short lists use a linear scan, long ones a hash table; both compare with equal?.

(define (test/pairwise-different? _)
  (⊦= #t (pairwise-different? '()))
  (⊦= #t (pairwise-different? '(1 2 3 a "b" (c))))
  (⊦= #f (pairwise-different? '(1 2 3 (c) a "b" (c))))
  (⊦= #f (pairwise-different? '(#f 1 #f)))
  (⊦= #t (pairwise-different? (ι 100)))
  (⊦= #f (pairwise-different? (append (ι 100) '(42))))
  (⊦= #t (pairwise-different? (map list (ι 100))))
  (⊦= #f (pairwise-different? (cons '(99) (map list (ι 100))))))
((eta 0.0) (memory #(12582912 2868632 1048576)) (stdout "") (stderr ""))

test/enumerate: pass

(define (test/enumerate _)
  (⊦= '() (enumerate '()))
  (⊦= '((0 a) (1 b) (2 c)) (enumerate '(a b c)))
  (⊦= 1000 (length (enumerate (ι 1000))))
  (⊦= '(999 999) (list-ref (enumerate (ι 1000)) 999)))
((eta 0.0) (memory #(12582912 2869960 1048576)) (stdout "") (stderr ""))

test/length/>?: pass

The witness is the tail after the first n elements, so a #f element there still answers that the list is longer.

(define (test/length/>? _)
  (⊦= '(3 4) (length/>? '(1 2 3 4) 2))
  (⊦= '(#f 4) (length/>? '(1 2 #f 4) 2))
  (⊦= #f (length/>? '(1 2 3) 3))
  (⊦= #f (length/>? '() 0))
  (⊦= 'a (car (length/>? (list/circular 'a 'b) 4)))
  (⊦= '(1) (length/>? '(1) -1))
  (⊦= '(2) (length/>? '(1 2) 1.0))
  (⊦= '(2) (length/>? '(1 2) 1.5))
  (⊦= #f (length/>? '(1 2) 2.0))
  (⊦= 'a (car (length/>? (list/circular 'a 'b) -1))))
((eta 0.0) (memory #(12582912 2871712 1048576)) (stdout "") (stderr ""))

test/letassoc: pass

(define (test/letassoc _)
  (⊦= 1 (letassoc ('a '((a 1) (b 2))) (else 'none)))
  (⊦= '(2) (letassoc/cdr ('b '((a 1) (b 2))) (else 'none)))
  (⊦= 'none (letassoc/cdr ('c '((a 1) (b 2))) (else 'none))))
((eta 0.0) (memory #(12582912 2873072 1048576)) (stdout "") (stderr ""))

test/load/string: pass

(define (test/load/string _) (⊦= '(+ 3 4) (load/string "(+ 3 4)")))
((eta 0.0) (memory #(12582912 2874400 1048576)) (stdout "") (stderr ""))

test/absent?: pass

A compound term is detected as a subterm too, not only atoms at the leaves.

(define (test/absent? _)
  (⊦= #t (absent? 'x '(a (b #(c d)))))
  (⊦= #f (absent? 'd '(a (b #(c d)))))
  (⊦= #f (absent? '(1 2) '(a (1 2))))
  (⊦= #f (absent? (vector 1) (list (vector 1))))
  (⊦= #f (absent? '() '()))
  (⊦= #t (absent? '(1 2) '(a (1 3))))
  (⊦= #f (absent? '(c d) (vector 'a (list 'b 'c 'd))))
  (⊦= #t (absent? 'e (vector 'a (list 'b (vector 'c 'd))))))
((eta 0.0) (memory #(12582912 2875712 1048576)) (stdout "") (stderr ""))

test/letport/string: pass

With an input string only the body value is returned; with out the captured string comes second.

(define (test/letport/string _)
  (⊦= '(1 2) (letport/string (p "(1 2)") (read p)))
  (⊦= '(3 "4")
      (call-with-values (λ () (letport/string (p out) (display 4 p) 3)) list)))
((eta 0.0) (memory #(12582912 2878056 1048576)) (stdout "") (stderr ""))

test/foldr/avg&var: pass

Degenerate inputs yield +nan.0 instead of a division by zero.

(define (test/foldr/avg&var _)
  (⊦= 2 (foldr/avg '(1 2 3)))
  (⊦= 1 (foldr/var '(1 2 3)))
  (⊦= #t (nan? (foldr/avg '())))
  (⊦= #t (nan? (foldr/var '())))
  (⊦= #t (nan? (foldr/var '(5))))
  (⊦= #t (nan? (foldr/stddev '(5)))))
((eta 0.0) (memory #(12582912 2878768 1048576)) (stdout "") (stderr ""))

test/foldr/concat-strings: pass

(define (test/foldr/concat-strings _)
  (⊦= "" (foldr/concat-strings '()))
  (⊦= "abc" (foldr/concat-strings '("a" "" "bc")))
  (⊦= 40000 (string-length (foldr/concat-strings (map (K "ab") (ι 20000))))))
((eta 0.002) (memory #(12582912 2907912 1048576)) (stdout "") (stderr ""))

test/simdjson/version: pass

The current version of simdjson is 4.6.6.

(define (test/simdjson/version _))
((eta 0.0) (memory #(12582912 2909528 1048576)) (stdout "") (stderr ""))

test/simdjson/load-twitter: pass

Loaded a testbed json file twitter.jsontwitter.json : a twitter search result JSON file with the simdjsonsimdjson : parsing gigabytes of JSON per secondsimdjson : user manual and documentation library. The file contains a twitter search result with 100 tweets.

(define (test/simdjson/load-twitter _)
  (define twitter-json (simdjson-load/ondemand "twitter.json"))
  (⊦= 2 (length twitter-json))
  (⊦= '(search_metadata
         ((completed_in 0.087)
          (max_id 505874924095815700)
          (max_id_str "505874924095815681")
          (next_results
            "?max_id=505874847260352512&q=%E4%B8%80&count=100&include_entities=1")
          (query "%E4%B8%80")
          (refresh_url
            "?since_id=505874924095815681&q=%E4%B8%80&include_entities=1")
          (count 100)
          (since_id 0)
          (since_id_str "0")))
      (cadr twitter-json))
  (⊦= 100 (vector-length (cadar twitter-json))))
((eta 0.01) (memory #(12582912 4300904 1048576)) (stdout "") (stderr ""))

test/simdjson/load-twitter/ondemand: pass

Here we show the on demand parsing mode of simdjsonsimdjson : Documents are iterators, which yields equivalent Scheme objects with respect to the DOM parsing.

(define (test/simdjson/load-twitter/ondemand _)
  (⊦= (simdjson-load "twitter.json") (simdjson-load/ondemand "twitter.json")))
((eta 0.02) (memory #(12582912 5725376 1048576)) (stdout "") (stderr ""))

test/simdjson/->string: pass

Test for simdjson-load, which loads and parses a JSON file into a Scheme representation.

(define (test/simdjson/->string _)
  (⊦= test/simdjson/->string/expected
      (->string/json (simdjson-load "twitter.json"))))
((eta 0.024) (memory #(12582912 4827904 1048576)) (stdout "") (stderr ""))

test/simdjson/->string/valid-json: pass

Strings and keys are escaped the JSON way, control characters as \u00XX, an exact ratio is written as the nearest flonum, and a number JSON cannot spell, infinite, not a number or not real, is an error, as is a string holding a surrogate code point, which is how CHICKEN reads a byte of invalid UTF-8. A flonum is written with the fewest digits, 15 to 17, that read back as the same double, where the default 15 would print the largest double out of range; so every text ->string/json writes parses back to what it wrote.

(define (test/simdjson/->string/valid-json _)
  (⊦= "[\"\\u0001\",\"\\u001f\",\"tab\\there\",\"q\\\"b\\\\s\",\"caffè\"]"
      (->string/json
        (vector
          (string (integer->char 1))
          (string (integer->char 31))
          "tab\there"
          "q\"b\\s"
          "caffè")))
  (⊦= "{\"ke\\\"y\":1,\"a\\\\b\":2}"
      (->string/json `((,(string->symbol "ke\"y") 1) ("a\\b" 2))))
  (⊦= "[0.25,-3,22.0]" (->string/json #(1/4 -3 22.0)))
  (⊦= '(raised raised raised raised)
      (map (λ (n) (condition-case (->string/json (vector n)) ((exn) 'raised)))
           (list +inf.0 -inf.0 +nan.0 1+2i)))
  (⊦= '(raised raised raised raised)
      (map (λ (s) (condition-case (->string/json (vector s)) ((exn) 'raised)))
           (list (string (integer->char 55296))
                 (string #\a (integer->char 57343))
                 (string #\c #\a #\f #\f (integer->char 56515))
                 `((,(string->symbol (string (integer->char 56448))) 1)))))
  (let1 (v (vector
             (string
               (integer->char 55295)
               (integer->char 57344)
               (integer->char 65535)
               (integer->char 1114111))
             "caffè 一 😋"))
        (⊦= v (simdjson-parse/ondemand (->string/json v))))
  (let1 (v `((text ,(string
                      #\a
                      (integer->char 1)
                      #\"
                      (integer->char 0)
                      #\\
                      #\newline
                      #\x4e00))
             (,(string->symbol "k\"ey") #(0.5 "caffè"))))
        (⊦= v (simdjson-parse/ondemand (->string/json v))))
  (⊦= "[0.30000000000000004,1.7976931348623157e+308,4.94065645841247e-324,0.1,-0.0,1e+100]"
      (->string/json
        (vector
          (+ 0.1 0.2)
          1.79769313486232e+308
          4.94065645841247e-324
          0.1
          -0.0
          1e+100)))
  (let1 (v (vector
             (+ 0.1 0.2)
             1.79769313486232e+308
             4.94065645841247e-324
             2.2250738585072e-308
             (/ 1.0 3.0)
             -1.2345678e-87
             1.23456789012346e+20
             1000000000000000.0
             4503599627370497.0
             -7.0))
        (⊦= v (simdjson-parse/ondemand (->string/json v)))))
((eta 0.0) (memory #(12582912 4830080 1048576)) (stdout "") (stderr ""))

test/simdjson/parse: pass

Test for simdjson-parse/ondemand, which parses a JSON string into a Scheme representation on demand.

(define (test/simdjson/parse _)
  (⊦= #(((a 1) (b #(2 5)) (c #t)) ((c 3) (d 4)))
      (simdjson-parse/ondemand
        "[{\"a\":1,\"b\":[2,5],\"c\":true},{\"c\":3,\"d\":4}]")))
((eta 0.0) (memory #(12582912 4831360 1048576)) (stdout "") (stderr ""))

test/simdjson/parse/scalar: pass

A JSON text may be a bare scalar, and it decodes like the same scalar inside an array. Literals are checked in full: nul is an error, not null. Nothing but white space may follow the root value, be it a scalar, an array or an object.

(define (test/simdjson/parse/scalar _)
  (⊦= 5 (simdjson-parse/ondemand "5"))
  (⊦= -3.5 (simdjson-parse/ondemand " -3.5 "))
  (⊦= 18446744073709551615 (simdjson-parse/ondemand "18446744073709551615"))
  (⊦= "s" (simdjson-parse/ondemand "\"s\""))
  (⊦= #t (simdjson-parse/ondemand "true"))
  (⊦= #f (simdjson-parse/ondemand "false"))
  (⊦= (void) (simdjson-parse/ondemand "null"))
  (⊦= "TRAILING_CONTENT"
      (simdjson-error-code (λ () (simdjson-parse/ondemand "5 6"))))
  (⊦= "INCORRECT_TYPE"
      (simdjson-error-code (λ () (simdjson-parse/ondemand "nul"))))
  (⊦= "INCORRECT_TYPE"
      (simdjson-error-code (λ () (simdjson-parse/ondemand "[nul]"))))
  (⊦= '("TRAILING_CONTENT"
        "TRAILING_CONTENT"
        "TRAILING_CONTENT"
        "TRAILING_CONTENT"
        "TRAILING_CONTENT")
      (map (λ (s) (simdjson-error-code (λ () (simdjson-parse/ondemand s))))
           (list "[1][2]"
                 "[1]]"
                 "{}}"
                 "{\"a\":1} {\"b\":2}"
                 "{\"a\":{}},\"b\":1,\"c\":2}")))
  (⊦= '(#(1) ((a 1)) 5)
      (map simdjson-parse/ondemand (list " [1] " "{\"a\":1}\n" "5\n"))))
((eta 0.0) (memory #(12582912 4833320 1048576)) (stdout "") (stderr ""))

test/simdjson/parse/utf-8: pass

The parser is given the length of the text in bytes, not in characters: counting characters, each multi-byte one cut a byte off the end of the document.

(define (test/simdjson/parse/utf-8 _)
  (⊦= '((k "cafè")) (simdjson-parse/ondemand "{\"k\": \"cafè\"}"))
  (⊦= #("一" "😋" "è") (simdjson-parse/ondemand "[\"一\", \"😋\", \"\\u00e8\"]"))
  (⊦= '((è 1)) (simdjson-parse/ondemand "{\"è\":1}")))
((eta 0.0) (memory #(12582912 4834688 1048576)) (stdout "") (stderr ""))

test/simdjson/parse/nul: pass

A JSON string may hold \u0000, in values and in keys alike; the characters after it are kept, where a C string would end there.

(define (test/simdjson/parse/nul _)
  (let1 (nul (string (integer->char 0)))
        (⊦= `((k ,(string-append "a" nul "b")))
            (simdjson-parse/ondemand "{\"k\": \"a\\u0000b\"}"))
        (⊦= `#(,(string-append "caffè" nul "一") ,nul)
            (simdjson-parse/ondemand "[\"caffè\\u0000一\", \"\\u0000\"]"))
        (⊦= `((,(string->symbol (string-append "a" nul "b")) 1))
            (simdjson-parse/ondemand "{\"a\\u0000b\": 1}"))))
((eta 0.0) (memory #(12582912 4836240 1048576)) (stdout "") (stderr ""))

test/simdjson/frees-the-tree: pass

The C side mallocs the whole tree it hands over, and simdjson->scheme/free releases it even when the conversion raises, as it does on the error node of a rejected document: leaking that node, 200000 rejections of {bad grow the process by some 40 MB. Leaking the tree, 40 loads of twitter.json grow it by some 75 MB. An integer too large for 64 bits is refused by the C side, which frees the half-built tree and hands over such an error node, so the error carries simdjson's message, BIGINT_ERROR, and no pointer into the freed tree.

(define (test/simdjson/frees-the-tree _)
  (⊨ (eq? simdjson-load/ondemand simdjson-load))
  (⊨ (< (resident-growth (λ () (simdjson-load "twitter.json"))) 16384))
  (let1 (s (string-append
             "{\"s\":\""
             (make-string 1000000 #\x)
             "\",\"n\":123456789012345678901234567890}"))
        (⊨ (< (resident-growth
                (λ () (condition-case (simdjson-parse/ondemand s) ((exn) #f))))
              16384)))
  (let1 (rejects
          (λ ()
             (let loop ((n 5000))
               (unless
                 (zero? n)
                 (condition-case (simdjson-parse/ondemand "{bad") ((exn) #f))
                 (loop (sub1 n))))))
        (⊨ (< (resident-growth rejects) 16384)))
  (⊦= '("BIGINT_ERROR" "BIGINT_ERROR" "BIGINT_ERROR" "BIGINT_ERROR")
      (map (λ (s) (simdjson-error-code (λ () (simdjson-parse/ondemand s))))
           (list "18446744073709551616"
                 "-9223372036854775809"
                 "[123456789012345678901234567890]"
                 "{\"a\":-123456789012345678901234567890}")))
  (⊦= '()
      (condition-case
        (simdjson-parse/ondemand "[123456789012345678901234567890]")
        (e (exn) (get-condition-property e 'exn 'arguments)))))
((eta 3.681) (memory #(12582912 2889424 1048576)) (stdout "") (stderr ""))

test/simdjson/errors: pass

A document simdjson rejects raises a Scheme error carrying simdjson's own message, instead of letting the C++ exception reach std::terminate. A value starting with a character no JSON value starts with, as x or ], is an improper structure too, at the root as inside a container. On a broken structure, the children simdjson counted ahead of an array or an object may be fewer than those the walk then meets; they are checked, not written past the end of the heap block, which glibc found corrupted at a later free. The walk recurses once per nesting level, so a document nesting more than 1024 arrays or objects raises DEPTH_ERROR instead of overflowing the C stack.

(define (test/simdjson/errors _)
  (⊦= "INCOMPLETE_ARRAY_OR_OBJECT"
      (simdjson-error-code (λ () (simdjson-parse/ondemand "{bad json"))))
  (⊦= "INCOMPLETE_ARRAY_OR_OBJECT"
      (simdjson-error-code (λ () (simdjson-parse/ondemand "[1,2,{\"a\":[1,"))))
  (⊦= "NUMBER_ERROR"
      (simdjson-error-code (λ () (simdjson-parse/ondemand "[1, 2, 1e999]"))))
  (⊦= "IO_ERROR"
      (simdjson-error-code
        (λ () (simdjson-load/ondemand "no-such-file.json"))))
  (⊦= "TAPE_ERROR"
      (simdjson-error-code
        (λ () (simdjson-parse/ondemand "[[}],1,2,3,4,5,6,7,8]"))))
  (⊦= "TAPE_ERROR"
      (simdjson-error-code
        (λ () (simdjson-parse/ondemand "{\"\":[[}],\"\":\"\"}"))))
  (⊦= '("TAPE_ERROR"
        "TAPE_ERROR"
        "TAPE_ERROR"
        "TAPE_ERROR"
        "TAPE_ERROR"
        "TAPE_ERROR")
      (map (λ (s) (simdjson-error-code (λ () (simdjson-parse/ondemand s))))
           (list "x" "]" "] [1]" "[1, x, 2]" "{\"a\": x}" "[1, ], 2]")))
  (⊦= #(1 2 ((a "x"))) (simdjson-parse/ondemand "[1,2,{\"a\":\"x\"}]"))
  (let1 (nested
          (λ (n) (string-append (make-string n #\[) (make-string n #\]))))
        (⊦= 1 (vector-length (simdjson-parse/ondemand (nested 1024))))
        (⊦= '("DEPTH_ERROR" "DEPTH_ERROR" "DEPTH_ERROR")
            (map (λ (s)
                    (simdjson-error-code (λ () (simdjson-parse/ondemand s))))
                 (list (nested 1025)
                       (nested 100000)
                       (let loop ((n 1025) (s "1"))
                         (if (zero? n)
                           s
                           (loop (sub1 n) (string-append "{\"a\":" s "}")))))))))
((eta 0.308) (memory #(12582912 3106000 1048576)) (stdout "") (stderr ""))

test/libc/fma: pass

Taken from fma, fmaf, fmal

(define (test/libc/fma _)
  (⊦ fp= 0.0 (+ (* 0.1 10.0) -1.0))
  (⊦ fp= (fp*+ 0.1 10.0 -1.0) (libc-fma 0.1 10.0 -1.0)))
((eta 0.0) (memory #(12582912 3107712 1048576)) (stdout "") (stderr ""))

test/documentation: pass

An initial attempt to support our own documentation framework. The following tests check that documentation can be set and retrieved for functions.

(define (test/documentation _)
  (set! (documentation +) "Returns the sum of its arguments.")
  (define-documented
    (a (λ (x) (+ x 1)))
    (documentation (comment `(p " some comment here"))))
  (documentation! a 'comment "some other comment here.")
  (⊦= '(C_plus ("Returns the sum of its arguments.")) (documentation +))
  (⊦= '((a x)
        ((name a)
         (def (λ (x) (+ x 1)))
         (comment (p " some comment here"))
         (comment "some other comment here.")))
      (documentation a)))
((eta 0.0) (memory #(12582912 3099920 1048576)) (stdout "") (stderr ""))

test/documentation/documentation: pass

Test for documentation of the documentation function itself.

(define (test/documentation/documentation _)
  (documentation!
    documentation
    'comment
    "Test for documentation of the documentation function itself.")
  (⊦= '((aux.base#documentation func)
        ((sxml (p "This function is the fundamental documentation storage and retrieval mechanism."))
         (comment
           "Test for documentation of the documentation function itself.")))
      (documentation documentation)))
((eta 0.0) (memory #(12582912 3101448 1048576)) (stdout "") (stderr ""))
Categories: scheme  books 

See also

The Seasoned Schemer Cogen in six lines The (aux anthropic) module The Anthropic Messages API, offline The (aux cml) module Events, threads, synchronous variables, the library and I/O The (aux hakaru10) modules Random sources, distributions, the language, exact inference and examples The (aux kanren) modules Arithmetic, dates, presentation of answers and a union-find miniKanren The (aux games dice-of-doom) module Dice of Doom The (aux machine) modules Environments, the SC machine and the SECD machine The (aux schemer seasoned) module The Seasoned Schemer The (aux continuation) modules Classic operators, escapers, amb and Collatz sequences The (aux category) modules Monads: list, maybe, probability, ziplist, difference lists and state The (aux timsort) module Sorting and the trace buffer The (aux fds) modules Functional queues and union-find The (aux sxml) module Rendering SXML to HTML The (aux variable) module Logic variables introduced by fresh The (aux tabling) module Memoization and tabled definitions The (aux commons) module Learning tests for CHICKEN Scheme Promises delay and make-promise The Ackermann function On unary numbers, as lists Concurrent ML for CHICKEN Scheme Porting SML/NJ CML as the (aux cml) library CHICKEN Scheme Versions and implementation notes The SBRAL data structure Skew Binary Random-Access Lists Pattern matching Scheme macrology: a generalized pattern matcher The (aux hansei) modules Inference, random sources, lazy lists, logic programming and example models The (aux nondeterministic) module Learning tests for Scheme The (aux stream) modules Streams, streams after SICP, and sequences and power series The (aux unittest) module Bootstrapping a unittest framework TAOCP: Volume 4, Fascicle 6. Satisfiability Scheme lang: Chez, 48 and Chicken Some docs, refs and containers, respectively. The Reasoned Schemer miniKanren, microKanren and some implementations Aggregation predicates for µkanren Groups, window functions, sets and enumerations miniKanren, live and untagged Quine generation via relational interpreters Pure, declarative, and constructive arithmetic relations A declarative pearl Final shift for call/cc Direct implementation of shift and reset Call with Current Continuation Patterns Adding generic functions to Scheme Handling control