diff --git a/.codex b/.codex new file mode 100644 index 00000000..e69de29b diff --git a/README.md b/README.md index 0dedd898..3db397c0 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,7 @@ Just like S7 Scheme, [src/goldfish.hpp](src/goldfish.hpp) and [src/goldfish.cpp] | `(srfi srfi-9)` | Complete | Provide `define-record-type` | | `(srfi srfi-13)` | Complete | String Library | | `(srfi srfi-16)` | Complete | Provide `case-lambda` | +| `(srfi srfi-117)` | Complete | List Queues | | `(srfi srfi-39)` | Complete | Parameter Objects | | `(srfi srfi-78)` | Part | Lightweigted Test Framework | | `(srfi srfi-125)` | Part | Hash Table | diff --git a/devel/215_5.md b/devel/215_5.md new file mode 100644 index 00000000..c230fe3a --- /dev/null +++ b/devel/215_5.md @@ -0,0 +1,39 @@ +# [215_5] srfi-117 list-queue 实现 + +## srfi-117 list-queue 实现 + +## 如何测试 + +```bash +# 1. 构建 +xmake b goldfish + +# 2. 运行入口文件 +bin/gf tests/scheme/list-test.scm + +# 3. 运行单个测试文件 +bin/gf tests/scheme/list/make-list-queue-test.scm +bin/gf tests/scheme/list/list-queue-test.scm +bin/gf tests/scheme/list/list-queue-copy-test.scm +bin/gf tests/scheme/list/list-queue-unfold-test.scm +bin/gf tests/scheme/list/list-queue-unfold-right-test.scm +bin/gf tests/scheme/list/list-queue-p-test.scm +bin/gf tests/scheme/list/list-queue-empty-p-test.scm +bin/gf tests/scheme/list/list-queue-front-test.scm +bin/gf tests/scheme/list/list-queue-back-test.scm +bin/gf tests/scheme/list/list-queue-list-test.scm +bin/gf tests/scheme/list/list-queue-first-last-test.scm +bin/gf tests/scheme/list/list-queue-add-front-bang-test.scm +bin/gf tests/scheme/list/list-queue-add-back-bang-test.scm +bin/gf tests/scheme/list/list-queue-remove-front-bang-test.scm +bin/gf tests/scheme/list/list-queue-remove-back-bang-test.scm +bin/gf tests/scheme/list/list-queue-remove-all-bang-test.scm +bin/gf tests/scheme/list/list-queue-set-list-bang-test.scm +bin/gf tests/scheme/list/list-queue-append-test.scm +bin/gf tests/scheme/list/list-queue-append-bang-test.scm +bin/gf tests/scheme/list/list-queue-concatenate-test.scm +bin/gf tests/scheme/list/list-queue-map-test.scm +bin/gf tests/scheme/list/list-queue-map-bang-test.scm +bin/gf tests/scheme/list/list-queue-for-each-test.scm +``` + diff --git a/goldfish/srfi/srfi-117.scm b/goldfish/srfi/srfi-117.scm new file mode 100644 index 00000000..d5efb7a1 --- /dev/null +++ b/goldfish/srfi/srfi-117.scm @@ -0,0 +1,373 @@ +; +; SRFI-117: Queues based on lists +; +; Based on the SRFI-117 reference implementation: +; Copyright (C) 2017 Alex Shinn +; +; SPDX-License-Identifier: BSD-3-Clause +; +; Adapted for Goldfish Scheme. +; + +(define-library (srfi srfi-117) + (import (scheme base) + (scheme case-lambda) + (only (srfi srfi-1) list-copy last-pair) + (srfi srfi-9) + ) ;import + (export make-list-queue + list-queue + list-queue-copy + list-queue-unfold + list-queue-unfold-right + + list-queue? + list-queue-empty? + + list-queue-front + list-queue-back + list-queue-list + list-queue-first-last + + list-queue-add-front! + list-queue-add-back! + list-queue-remove-front! + list-queue-remove-back! + list-queue-remove-all! + list-queue-set-list! + list-queue-append + list-queue-append! + list-queue-concatenate + + list-queue-map + list-queue-map! + list-queue-for-each + ) ;export + (begin + + (define-record-type + (raw-make-list-queue first last) + list-queue? + (first list-queue-first-pair set-list-queue-first-pair!) + (last list-queue-last-pair set-list-queue-last-pair!) + ) ;define-record-type + + (define (%ensure-list-queue who obj) + (if (list-queue? obj) + obj + (error 'wrong-type-arg (string-append who ": expected list-queue") obj) + ) ;if + ) ;define + + (define (%ensure-pair-or-null who obj) + (unless (or (pair? obj) (null? obj)) + (error 'wrong-type-arg (string-append who ": expected pair or empty list") obj) + ) ;unless + ) ;define + + (define (%ensure-not-empty who queue) + (%ensure-list-queue who queue) + (when (list-queue-empty? queue) + (error 'out-of-range (string-append who ": empty list-queue")) + ) ;when + ) ;define + + (define (%validate-first-last who first last) + (%ensure-pair-or-null who first) + (%ensure-pair-or-null who last) + (when (or (and (null? first) (pair? last)) + (and (pair? first) (null? last))) + (error 'wrong-type-arg + (string-append who ": invalid first/last pair combination") + first + last + ) ;error + ) ;when + ) ;define + + (define (%penult-pair pairs) + (let loop ((pairs pairs)) + (cond ((null? (cdr pairs)) '()) + ((null? (cddr pairs)) pairs) + (else (loop (cdr pairs))) + ) ;cond + ) ;let + ) ;define + + (define (%map! proc pairs) + (let loop ((pairs pairs)) + (when (pair? pairs) + (set-car! pairs (proc (car pairs))) + (loop (cdr pairs)) + ) ;when + ) ;let + ) ;define + + (define (%join! result queue) + (let ((source (if (eq? result queue) + (list-queue-copy queue) + queue)) + ) ;let + (unless (list-queue-empty? source) + (if (list-queue-empty? result) + (begin + (set-list-queue-first-pair! result (list-queue-first-pair source)) + (set-list-queue-last-pair! result (list-queue-last-pair source)) + ) ;begin + (begin + (set-cdr! (list-queue-last-pair result) + (list-queue-first-pair source) + ) ;set-cdr! + (set-list-queue-last-pair! result (list-queue-last-pair source)) + ) ;begin + ) ;if + (when (eq? source queue) + (set-list-queue-first-pair! queue '()) + (set-list-queue-last-pair! queue '()) + ) ;when + ) ;unless + result + ) ;define + ) ;begin + + (define make-list-queue + (case-lambda + ((first) + (%ensure-pair-or-null "make-list-queue" first) + (if (null? first) + (raw-make-list-queue '() '()) + (raw-make-list-queue first (last-pair first)) + ) ;if + ) ; + ((first last) + (%validate-first-last "make-list-queue" first last) + (raw-make-list-queue first last) + ) ; + ) ;case-lambda + ) ;define + + (define (list-queue . elements) + (make-list-queue elements) + ) ;define + + (define (list-queue-copy queue) + (%ensure-list-queue "list-queue-copy" queue) + (make-list-queue (list-copy (list-queue-first-pair queue))) + ) ;define + + (define list-queue-unfold + (case-lambda + ((stop? mapper successor seed) + (list-queue-unfold stop? mapper successor seed (list-queue)) + ) ; + ((stop? mapper successor seed queue) + (%ensure-list-queue "list-queue-unfold" queue) + (let loop ((seed seed)) + (if (stop? seed) + queue + (begin + (list-queue-add-front! (loop (successor seed)) (mapper seed)) + queue + ) ;begin + ) ;if + ) ;let + ) ; + ) ;case-lambda + ) ;define + + (define list-queue-unfold-right + (case-lambda + ((stop? mapper successor seed) + (list-queue-unfold-right stop? mapper successor seed (list-queue)) + ) ; + ((stop? mapper successor seed queue) + (%ensure-list-queue "list-queue-unfold-right" queue) + (let loop ((seed seed)) + (if (stop? seed) + queue + (begin + (list-queue-add-back! (loop (successor seed)) (mapper seed)) + queue + ) ;begin + ) ;if + ) ;let + ) ; + ) ;case-lambda + ) ;define + + (define (list-queue-empty? queue) + (%ensure-list-queue "list-queue-empty?" queue) + (null? (list-queue-first-pair queue)) + ) ;define + + (define (list-queue-front queue) + (%ensure-not-empty "list-queue-front" queue) + (car (list-queue-first-pair queue)) + ) ;define + + (define (list-queue-back queue) + (%ensure-not-empty "list-queue-back" queue) + (car (list-queue-last-pair queue)) + ) ;define + + (define (list-queue-list queue) + (%ensure-list-queue "list-queue-list" queue) + (list-queue-first-pair queue) + ) ;define + + (define (list-queue-first-last queue) + (%ensure-list-queue "list-queue-first-last" queue) + (values (list-queue-first-pair queue) + (list-queue-last-pair queue) + ) ;values + ) ;define + + (define (list-queue-add-front! queue element) + (%ensure-list-queue "list-queue-add-front!" queue) + (let* ((old-first (list-queue-first-pair queue)) + (new-first (cons element old-first)) + ) ;let* + (when (null? old-first) + (set-list-queue-last-pair! queue new-first) + ) ;when + (set-list-queue-first-pair! queue new-first) + ) ;let* + ) ;define + + (define (list-queue-add-back! queue element) + (%ensure-list-queue "list-queue-add-back!" queue) + (let ((new-last (list element))) + (if (list-queue-empty? queue) + (set-list-queue-first-pair! queue new-last) + (set-cdr! (list-queue-last-pair queue) new-last) + ) ;if + (set-list-queue-last-pair! queue new-last) + ) ;let + ) ;define + + (define (list-queue-remove-front! queue) + (%ensure-not-empty "list-queue-remove-front!" queue) + (let* ((old-first (list-queue-first-pair queue)) + (element (car old-first)) + (new-first (cdr old-first)) + ) ;let* + (when (null? new-first) + (set-list-queue-last-pair! queue '()) + ) ;when + (set-list-queue-first-pair! queue new-first) + element + ) ;let* + ) ;define + + (define (list-queue-remove-back! queue) + (%ensure-not-empty "list-queue-remove-back!" queue) + (let* ((old-last (list-queue-last-pair queue)) + (element (car old-last)) + (new-last (%penult-pair (list-queue-first-pair queue))) + ) ;let* + (if (null? new-last) + (set-list-queue-first-pair! queue '()) + (set-cdr! new-last '()) + ) ;if + (set-list-queue-last-pair! queue new-last) + element + ) ;let* + ) ;define + + (define (list-queue-remove-all! queue) + (%ensure-list-queue "list-queue-remove-all!" queue) + (let ((result (list-queue-first-pair queue))) + (set-list-queue-first-pair! queue '()) + (set-list-queue-last-pair! queue '()) + result + ) ;let + ) ;define + + (define list-queue-set-list! + (case-lambda + ((queue first) + (%ensure-list-queue "list-queue-set-list!" queue) + (%ensure-pair-or-null "list-queue-set-list!" first) + (set-list-queue-first-pair! queue first) + (if (null? first) + (set-list-queue-last-pair! queue '()) + (set-list-queue-last-pair! queue (last-pair first)) + ) ;if + ) ; + ((queue first last) + (%ensure-list-queue "list-queue-set-list!" queue) + (%validate-first-last "list-queue-set-list!" first last) + (set-list-queue-first-pair! queue first) + (set-list-queue-last-pair! queue last) + ) ; + ) ;case-lambda + ) ;define + + (define (list-queue-append . queues) + (list-queue-concatenate queues) + ) ;define + + (define list-queue-append! + (case-lambda + (() (list-queue)) + ((queue) + (%ensure-list-queue "list-queue-append!" queue) + queue + ) ; + (queues + (for-each + (lambda (queue) + (%ensure-list-queue "list-queue-append!" queue) + ) ;lambda + queues + ) ;for-each + (let ((result (car queues))) + (for-each + (lambda (queue) + (%join! result queue) + ) ;lambda + (cdr queues) + ) ;for-each + result + ) ;let + ) ;queues + ) ;case-lambda + ) ;define + + (define (list-queue-concatenate queues) + (let loop ((queues queues) + (result (list-queue)) + ) ;let + (if (null? queues) + result + (begin + (%ensure-list-queue "list-queue-concatenate" (car queues)) + (list-queue-for-each + (lambda (element) + (list-queue-add-back! result element) + ) ;lambda + (car queues) + ) ;list-queue-for-each + (loop (cdr queues) result) + ) ;begin + ) ;if + ) ;let + ) ;define + + (define (list-queue-map proc queue) + (%ensure-list-queue "list-queue-map" queue) + (make-list-queue (map proc (list-queue-first-pair queue))) + ) ;define + + (define (list-queue-map! proc queue) + (%ensure-list-queue "list-queue-map!" queue) + (%map! proc (list-queue-first-pair queue)) + ) ;define + + (define (list-queue-for-each proc queue) + (%ensure-list-queue "list-queue-for-each" queue) + (for-each proc (list-queue-first-pair queue)) + ) ;define + + ) ;begin +) ;define-library diff --git a/src/goldfish_repl.cpp b/src/goldfish_repl.cpp index d0b7d51d..53696bcf 100644 --- a/src/goldfish_repl.cpp +++ b/src/goldfish_repl.cpp @@ -86,6 +86,7 @@ eval_string (const char* code) { s7_eval_c_string (wasm_sc, "(load \"srfi/sicp.scm\")"); s7_eval_c_string (wasm_sc, "(load \"srfi/srfi-1.scm\")"); s7_eval_c_string (wasm_sc, "(load \"srfi/srfi-113.scm\")"); + s7_eval_c_string (wasm_sc, "(load \"srfi/srfi-117.scm\")"); s7_eval_c_string (wasm_sc, "(load \"srfi/srfi-125.scm\")"); s7_eval_c_string (wasm_sc, "(load \"srfi/srfi-128.scm\")"); s7_eval_c_string (wasm_sc, "(load \"srfi/srfi-13.scm\")"); diff --git a/tests/scheme/list-test.scm b/tests/scheme/list-test.scm new file mode 100644 index 00000000..676cc074 --- /dev/null +++ b/tests/scheme/list-test.scm @@ -0,0 +1,17 @@ +;; +;; Copyright (C) 2024-2026 The Goldfish Scheme Authors +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +;; WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +;; License for the specific language governing permissions and limitations +;; under the License. +;; + +;; (srfi srfi-117) 中相关的测试用例都在 tests/scheme/list 目录中 diff --git a/tests/scheme/list/list-queue-add-back-bang-test.scm b/tests/scheme/list/list-queue-add-back-bang-test.scm new file mode 100644 index 00000000..508d8c5d --- /dev/null +++ b/tests/scheme/list/list-queue-add-back-bang-test.scm @@ -0,0 +1,26 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-add-back! +;; 将元素追加到队尾。 +;; +;; 语法 +;; ---- +;; (list-queue-add-back! queue element) + +(let ((queue (list-queue))) + (list-queue-add-back! queue 1) + (list-queue-add-back! queue 2) + (list-queue-add-back! queue 3) + (check (list-queue-list queue) => '(1 2 3)) + (check (list-queue-front queue) => 1) + (check (list-queue-back queue) => 3) +) ;let + +;; 错误处理测试 +(check-catch 'wrong-type-arg (list-queue-add-back! 1 'a)) + +(check-report) diff --git a/tests/scheme/list/list-queue-add-front-bang-test.scm b/tests/scheme/list/list-queue-add-front-bang-test.scm new file mode 100644 index 00000000..1a842cef --- /dev/null +++ b/tests/scheme/list/list-queue-add-front-bang-test.scm @@ -0,0 +1,25 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-add-front! +;; 将元素插入到队首。 +;; +;; 语法 +;; ---- +;; (list-queue-add-front! queue element) + +(let ((queue (list-queue))) + (list-queue-add-front! queue 2) + (list-queue-add-front! queue 1) + (check (list-queue-list queue) => '(1 2)) + (check (list-queue-front queue) => 1) + (check (list-queue-back queue) => 2) +) ;let + +;; 错误处理测试 +(check-catch 'wrong-type-arg (list-queue-add-front! 1 'a)) + +(check-report) diff --git a/tests/scheme/list/list-queue-append-bang-test.scm b/tests/scheme/list/list-queue-append-bang-test.scm new file mode 100644 index 00000000..d1350770 --- /dev/null +++ b/tests/scheme/list/list-queue-append-bang-test.scm @@ -0,0 +1,29 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-append! +;; 以破坏性方式拼接多个队列。 +;; +;; 语法 +;; ---- +;; (list-queue-append! queue ...) -> list-queue? + +(let ((queue (list-queue-append!))) + (check-true (list-queue-empty? queue)) +) ;let + +(let* ((queue-1 (list-queue 1 2)) + (queue-2 (list-queue 3 4)) + (queue-3 (list-queue-append! queue-1 queue-2)) +) ;let* + (check-true (eq? queue-3 queue-1)) + (check (list-queue-list queue-3) => '(1 2 3 4)) + (check (list-queue-list queue-2) => '()) +) ;let* + +(check-catch 'wrong-type-arg (list-queue-append! 1)) + +(check-report) diff --git a/tests/scheme/list/list-queue-append-test.scm b/tests/scheme/list/list-queue-append-test.scm new file mode 100644 index 00000000..c08c7bf2 --- /dev/null +++ b/tests/scheme/list/list-queue-append-test.scm @@ -0,0 +1,26 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-append +;; 以非破坏性方式拼接多个队列。 +;; +;; 语法 +;; ---- +;; (list-queue-append queue ...) -> list-queue? + +(let* ((queue-1 (list-queue 1 2)) + (queue-2 (list-queue 3 4)) + (queue-3 (list-queue-append queue-1 queue-2)) +) ;let* + (check (list-queue-list queue-3) => '(1 2 3 4)) + (check (list-queue-list queue-1) => '(1 2)) + (check (list-queue-list queue-2) => '(3 4)) +) ;let* + +;; 错误处理测试 +(check-catch 'wrong-type-arg (list-queue-append (list-queue 1) 2)) + +(check-report) diff --git a/tests/scheme/list/list-queue-back-test.scm b/tests/scheme/list/list-queue-back-test.scm new file mode 100644 index 00000000..fd24e055 --- /dev/null +++ b/tests/scheme/list/list-queue-back-test.scm @@ -0,0 +1,20 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-back +;; 返回队尾元素。 +;; +;; 语法 +;; ---- +;; (list-queue-back queue) -> any + +(check (list-queue-back (list-queue 1 2 3)) => 3) + +;; 错误处理测试 +(check-catch 'out-of-range (list-queue-back (list-queue))) +(check-catch 'wrong-type-arg (list-queue-back 1)) + +(check-report) diff --git a/tests/scheme/list/list-queue-concatenate-test.scm b/tests/scheme/list/list-queue-concatenate-test.scm new file mode 100644 index 00000000..2d852661 --- /dev/null +++ b/tests/scheme/list/list-queue-concatenate-test.scm @@ -0,0 +1,29 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-concatenate +;; 将队列列表拼接为一个新队列。 +;; +;; 语法 +;; ---- +;; (list-queue-concatenate queues) -> list-queue? + +(let* ((queue-1 (list-queue 1)) + (queue-2 (list-queue)) + (queue-3 (list-queue 2 3)) + (queue (list-queue-concatenate (list queue-1 queue-2 queue-3))) +) ;let* + (check (list-queue-list queue) => '(1 2 3)) + (check (list-queue-list queue-1) => '(1)) + (check (list-queue-list queue-2) => '()) + (check (list-queue-list queue-3) => '(2 3)) +) ;let* + +;; 错误处理测试 +(check-catch 'wrong-type-arg + (list-queue-concatenate (list (list-queue 1) 2))) + +(check-report) diff --git a/tests/scheme/list/list-queue-copy-test.scm b/tests/scheme/list/list-queue-copy-test.scm new file mode 100644 index 00000000..8139416c --- /dev/null +++ b/tests/scheme/list/list-queue-copy-test.scm @@ -0,0 +1,24 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-copy +;; 复制队列,返回一个内容相同但可独立修改的新队列。 +;; +;; 语法 +;; ---- +;; (list-queue-copy queue) -> list-queue? + +(let* ((queue (list-queue 1 2 3)) + (copy (list-queue-copy queue)) +) ;let* + (list-queue-add-front! copy 0) + (check (list-queue-list queue) => '(1 2 3)) + (check (list-queue-list copy) => '(0 1 2 3)) +) ;let* + +(check-catch 'wrong-type-arg (list-queue-copy 1)) + +(check-report) diff --git a/tests/scheme/list/list-queue-empty-p-test.scm b/tests/scheme/list/list-queue-empty-p-test.scm new file mode 100644 index 00000000..b2605ee4 --- /dev/null +++ b/tests/scheme/list/list-queue-empty-p-test.scm @@ -0,0 +1,20 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-empty? +;; 判断队列是否为空。 +;; +;; 语法 +;; ---- +;; (list-queue-empty? queue) -> boolean? + +(check-true (list-queue-empty? (list-queue))) +(check-false (list-queue-empty? (list-queue 1 2 3))) + +;; 错误处理测试 +(check-catch 'wrong-type-arg (list-queue-empty? 1)) + +(check-report) diff --git a/tests/scheme/list/list-queue-first-last-test.scm b/tests/scheme/list/list-queue-first-last-test.scm new file mode 100644 index 00000000..2ed8bce8 --- /dev/null +++ b/tests/scheme/list/list-queue-first-last-test.scm @@ -0,0 +1,34 @@ +(import (liii check) + (only (scheme base) let-values) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-first-last +;; 返回队列内部 first/last pair。 +;; +;; 语法 +;; ---- +;; (list-queue-first-last queue) -> values + +(let ((queue (list-queue))) + (let-values (((first last) (list-queue-first-last queue))) + (check first => '()) + (check last => '()) + ) ;let-values +) ;let + +(let* ((pairs (list 'a 'b 'c)) + (queue (make-list-queue pairs (cddr pairs))) +) ;let* + (let-values (((first last) (list-queue-first-last queue))) + (check-true (eq? first pairs)) + (check-true (eq? last (cddr pairs))) + ) ;let-values +) ;let* + +;; 错误处理测试 +(check-catch 'wrong-type-arg (list-queue-first-last 1)) + +(check-report) diff --git a/tests/scheme/list/list-queue-for-each-test.scm b/tests/scheme/list/list-queue-for-each-test.scm new file mode 100644 index 00000000..0814455d --- /dev/null +++ b/tests/scheme/list/list-queue-for-each-test.scm @@ -0,0 +1,22 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-for-each +;; 依次遍历队列中的元素。 +;; +;; 语法 +;; ---- +;; (list-queue-for-each proc queue) + +(let ((sum 0)) + (list-queue-for-each (lambda (x) (set! sum (+ sum x))) + (list-queue 10 20 30)) + (check sum => 60) +) ;let + +(check-catch 'wrong-type-arg (list-queue-for-each (lambda (x) x) 1)) + +(check-report) diff --git a/tests/scheme/list/list-queue-front-test.scm b/tests/scheme/list/list-queue-front-test.scm new file mode 100644 index 00000000..ce9ded63 --- /dev/null +++ b/tests/scheme/list/list-queue-front-test.scm @@ -0,0 +1,21 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-front +;; 返回队首元素。 +;; +;; 语法 +;; ---- +;; (list-queue-front queue) -> any + +(check (list-queue-front (list-queue 1 2 3)) => 1) + +;; 错误处理测试 +(check-catch 'out-of-range (list-queue-front (list-queue))) +(check-catch 'wrong-type-arg (list-queue-front 1)) +(check-catch 'wrong-number-of-args (list-queue-front)) + +(check-report) diff --git a/tests/scheme/list/list-queue-list-test.scm b/tests/scheme/list/list-queue-list-test.scm new file mode 100644 index 00000000..7e356f53 --- /dev/null +++ b/tests/scheme/list/list-queue-list-test.scm @@ -0,0 +1,20 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-list +;; 返回队列当前底层列表。 +;; +;; 语法 +;; ---- +;; (list-queue-list queue) -> list? + +(check (list-queue-list (list-queue)) => '()) +(check (list-queue-list (list-queue 1 2 3)) => '(1 2 3)) + +;; 错误处理测试 +(check-catch 'wrong-type-arg (list-queue-list 1)) + +(check-report) diff --git a/tests/scheme/list/list-queue-map-bang-test.scm b/tests/scheme/list/list-queue-map-bang-test.scm new file mode 100644 index 00000000..330d9322 --- /dev/null +++ b/tests/scheme/list/list-queue-map-bang-test.scm @@ -0,0 +1,21 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-map! +;; 原地修改队列中的每个元素。 +;; +;; 语法 +;; ---- +;; (list-queue-map! proc queue) + +(let ((queue (list-queue 1 2 3))) + (list-queue-map! (lambda (x) (+ x 1)) queue) + (check (list-queue-list queue) => '(2 3 4)) +) ;let + +(check-catch 'wrong-type-arg (list-queue-map! (lambda (x) x) 1)) + +(check-report) diff --git a/tests/scheme/list/list-queue-map-test.scm b/tests/scheme/list/list-queue-map-test.scm new file mode 100644 index 00000000..f2de805e --- /dev/null +++ b/tests/scheme/list/list-queue-map-test.scm @@ -0,0 +1,23 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-map +;; 返回应用映射后的新队列。 +;; +;; 语法 +;; ---- +;; (list-queue-map proc queue) -> list-queue? + +(let* ((queue (list-queue 1 2 3)) + (mapped (list-queue-map (lambda (x) (* x 10)) queue)) +) ;let* + (check (list-queue-list mapped) => '(10 20 30)) + (check (list-queue-list queue) => '(1 2 3)) +) ;let* + +(check-catch 'wrong-type-arg (list-queue-map (lambda (x) x) 1)) + +(check-report) diff --git a/tests/scheme/list/list-queue-p-test.scm b/tests/scheme/list/list-queue-p-test.scm new file mode 100644 index 00000000..b47b25d9 --- /dev/null +++ b/tests/scheme/list/list-queue-p-test.scm @@ -0,0 +1,20 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue? +;; 判断对象是否为 list-queue。 +;; +;; 语法 +;; ---- +;; (list-queue? obj) -> boolean? + +(check-true (list-queue? (list-queue))) +(check-true (list-queue? (make-list-queue '(1 2 3)))) +(check-false (list-queue? '(1 2 3))) +(check-false (list-queue? 1)) +(check-false (list-queue? #f)) + +(check-report) diff --git a/tests/scheme/list/list-queue-remove-all-bang-test.scm b/tests/scheme/list/list-queue-remove-all-bang-test.scm new file mode 100644 index 00000000..4959834e --- /dev/null +++ b/tests/scheme/list/list-queue-remove-all-bang-test.scm @@ -0,0 +1,26 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-remove-all! +;; 删除全部元素并返回原列表。 +;; +;; 语法 +;; ---- +;; (list-queue-remove-all! queue) -> list? + +(let ((queue (list-queue 1 2 3))) + (check (list-queue-remove-all! queue) => '(1 2 3)) + (check-true (list-queue-empty? queue)) +) ;let + +(let ((queue (list-queue))) + (check (list-queue-remove-all! queue) => '()) + (check-true (list-queue-empty? queue)) +) ;let + +(check-catch 'wrong-type-arg (list-queue-remove-all! 1)) + +(check-report) diff --git a/tests/scheme/list/list-queue-remove-back-bang-test.scm b/tests/scheme/list/list-queue-remove-back-bang-test.scm new file mode 100644 index 00000000..4d379e63 --- /dev/null +++ b/tests/scheme/list/list-queue-remove-back-bang-test.scm @@ -0,0 +1,27 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-remove-back! +;; 删除并返回队尾元素。 +;; +;; 语法 +;; ---- +;; (list-queue-remove-back! queue) -> any + +(let ((queue (list-queue 1 2 3))) + (check (list-queue-remove-back! queue) => 3) + (check (list-queue-list queue) => '(1 2)) +) ;let + +(let ((queue (list-queue 42))) + (check (list-queue-remove-back! queue) => 42) + (check-true (list-queue-empty? queue)) +) ;let + +;; 错误处理测试 +(check-catch 'out-of-range (list-queue-remove-back! (list-queue))) + +(check-report) diff --git a/tests/scheme/list/list-queue-remove-front-bang-test.scm b/tests/scheme/list/list-queue-remove-front-bang-test.scm new file mode 100644 index 00000000..2713b264 --- /dev/null +++ b/tests/scheme/list/list-queue-remove-front-bang-test.scm @@ -0,0 +1,27 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-remove-front! +;; 删除并返回队首元素。 +;; +;; 语法 +;; ---- +;; (list-queue-remove-front! queue) -> any + +(let ((queue (list-queue 1 2 3))) + (check (list-queue-remove-front! queue) => 1) + (check (list-queue-list queue) => '(2 3)) +) ;let + +(let ((queue (list-queue 42))) + (check (list-queue-remove-front! queue) => 42) + (check-true (list-queue-empty? queue)) +) ;let + +;; 错误处理测试 +(check-catch 'out-of-range (list-queue-remove-front! (list-queue))) + +(check-report) diff --git a/tests/scheme/list/list-queue-set-list-bang-test.scm b/tests/scheme/list/list-queue-set-list-bang-test.scm new file mode 100644 index 00000000..cf039f83 --- /dev/null +++ b/tests/scheme/list/list-queue-set-list-bang-test.scm @@ -0,0 +1,39 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-set-list! +;; 直接替换队列内部列表。 +;; +;; 语法 +;; ---- +;; (list-queue-set-list! queue first) +;; (list-queue-set-list! queue first last) + +(let* ((pairs (list 5 6 7)) + (last (cddr pairs)) + (queue (list-queue 1 2)) +) ;let* + (list-queue-set-list! queue pairs last) + (check (list-queue-list queue) => '(5 6 7)) + (list-queue-add-back! queue 8) + (check pairs => '(5 6 7 8)) +) ;let* + +(let ((queue (list-queue 9 10))) + (list-queue-set-list! queue '(4 5)) + (check (list-queue-list queue) => '(4 5)) +) ;let + +(let ((queue (list-queue 9 10))) + (list-queue-set-list! queue '()) + (check-true (list-queue-empty? queue)) + (check (list-queue-list queue) => '()) +) ;let + +;; 错误处理测试 +(check-catch 'wrong-type-arg (list-queue-set-list! (list-queue) 1)) + +(check-report) diff --git a/tests/scheme/list/list-queue-test.scm b/tests/scheme/list/list-queue-test.scm new file mode 100644 index 00000000..2927782c --- /dev/null +++ b/tests/scheme/list/list-queue-test.scm @@ -0,0 +1,26 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue +;; 从元素序列直接构造队列。 +;; +;; 语法 +;; ---- +;; (list-queue element ...) -> list-queue? + +(let ((queue (list-queue))) + (check-true (list-queue? queue)) + (check-true (list-queue-empty? queue)) + (check (list-queue-list queue) => '()) +) ;let + +(let ((queue (list-queue 1 2 3))) + (check (list-queue-list queue) => '(1 2 3)) + (check (list-queue-front queue) => 1) + (check (list-queue-back queue) => 3) +) ;let + +(check-report) diff --git a/tests/scheme/list/list-queue-unfold-right-test.scm b/tests/scheme/list/list-queue-unfold-right-test.scm new file mode 100644 index 00000000..78fff84e --- /dev/null +++ b/tests/scheme/list/list-queue-unfold-right-test.scm @@ -0,0 +1,33 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-unfold-right +;; 以后向构造的方式展开生成队列。 +;; +;; 语法 +;; ---- +;; (list-queue-unfold-right stop? mapper successor seed) +;; (list-queue-unfold-right stop? mapper successor seed queue) + +(let ((queue (list-queue-unfold-right (lambda (x) (> x 3)) + (lambda (x) (* x 2)) + (lambda (x) (+ x 1)) + 0))) + (check (list-queue-list queue) => '(6 4 2 0)) +) ;let + +(let ((tail (list-queue 8))) + (let ((queue (list-queue-unfold-right (lambda (x) (> x 3)) + (lambda (x) (* x 2)) + (lambda (x) (+ x 1)) + 0 + tail))) + (check-true (eq? queue tail)) + (check (list-queue-list queue) => '(8 6 4 2 0)) + ) ;let +) ;let + +(check-report) diff --git a/tests/scheme/list/list-queue-unfold-test.scm b/tests/scheme/list/list-queue-unfold-test.scm new file mode 100644 index 00000000..6b90af78 --- /dev/null +++ b/tests/scheme/list/list-queue-unfold-test.scm @@ -0,0 +1,41 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; list-queue-unfold +;; 以前向构造的方式展开生成队列。 +;; +;; 语法 +;; ---- +;; (list-queue-unfold stop? mapper successor seed) +;; (list-queue-unfold stop? mapper successor seed queue) + +(let ((queue (list-queue-unfold (lambda (x) (> x 3)) + (lambda (x) (* x 2)) + (lambda (x) (+ x 1)) + 0))) + (check (list-queue-list queue) => '(0 2 4 6)) +) ;let + +(let ((tail (list-queue 8))) + (let ((queue (list-queue-unfold (lambda (x) (> x 3)) + (lambda (x) (* x 2)) + (lambda (x) (+ x 1)) + 0 + tail))) + (check-true (eq? queue tail)) + (check (list-queue-list queue) => '(0 2 4 6 8)) + ) ;let +) ;let + +;; 错误处理测试 +(check-catch 'wrong-type-arg + (list-queue-unfold (lambda (x) #t) + (lambda (x) x) + (lambda (x) x) + 0 + 1)) + +(check-report) diff --git a/tests/scheme/list/make-list-queue-test.scm b/tests/scheme/list/make-list-queue-test.scm new file mode 100644 index 00000000..84e028ba --- /dev/null +++ b/tests/scheme/list/make-list-queue-test.scm @@ -0,0 +1,40 @@ +(import (liii check) + (srfi srfi-117) +) ;import + +(check-set-mode! 'report-failed) + +;; make-list-queue +;; 从列表或 first/last pair 构造队列。 +;; +;; 语法 +;; ---- +;; (make-list-queue first) +;; (make-list-queue first last) + +(let ((queue (make-list-queue '()))) + (check-true (list-queue? queue)) + (check-true (list-queue-empty? queue)) + (check (list-queue-list queue) => '()) +) ;let + +(let ((queue (make-list-queue '(1 2 3)))) + (check (list-queue-empty? queue) => #f) + (check (list-queue-list queue) => '(1 2 3)) + (check (list-queue-front queue) => 1) + (check (list-queue-back queue) => 3) +) ;let + +(let* ((pairs (list 'a 'b 'c)) + (queue (make-list-queue pairs (cddr pairs))) +) ;let* + (list-queue-add-back! queue 'd) + (check pairs => '(a b c d)) + (check (list-queue-list queue) => '(a b c d)) +) ;let* + +;; 错误处理测试 +(check-catch 'wrong-type-arg (make-list-queue 1)) +(check-catch 'wrong-type-arg (make-list-queue '() '(1))) + +(check-report)