diff --git a/devel/201_20.md b/devel/201_20.md index dcdf291a827655659a760a39bd101aca3549be3e..d1daabd62633ef02f7c3f94622a5a026aea0ad72 100644 --- a/devel/201_20.md +++ b/devel/201_20.md @@ -25,54 +25,51 @@ + [x] rich-string%empty? + [x] rich-string%starts-with + [x] rich-string%ends-with -+ [ ] rich-string%forall -+ [ ] rich-string%exists -+ [ ] rich-string%contains -+ [ ] rich-string%index-of -+ [ ] rich-string%map -+ [ ] rich-string%filter -+ [ ] rich-string%reverse -+ [ ] rich-string%for-each -+ [ ] rich-string%count -+ [ ] rich-string%index-where -+ [ ] rich-string%take-while -+ [ ] rich-string%drop-while -+ [ ] rich-string%to-string -+ [ ] rich-string%to-vector -+ [ ] rich-string%to-rich-vector -+ [ ] rich-string%+ -+ [ ] rich-string%strip-left -+ [ ] rich-string%strip-right -+ [ ] rich-string%strip-both -+ [ ] rich-string%strip-prefix -+ [ ] rich-string%strip-suffix -+ [ ] rich-string%replace-first -+ [ ] rich-string%replace -+ [ ] rich-string%pad-left -+ [ ] rich-string%pad-right -+ [ ] rich-string%split -+ [ ] rich-string%equals -+ [ ] rich-string%flat-map -+ [ ] rich-string%fold -+ [ ] rich-string%fold-right -+ [ ] rich-string%sort-with -+ [ ] rich-string%sort-by -+ [ ] rich-string%group-by -+ [ ] rich-string%sliding -+ [ ] rich-string%zip -+ [ ] rich-string%zip-with-index -+ [ ] rich-string%distinct -+ [ ] rich-string%reduce -+ [ ] rich-string%reduce-option -+ [ ] rich-string%max-by -+ [ ] rich-string%min-by -+ [ ] rich-string%append -+ [ ] rich-string%max-by-option -+ [ ] rich-string%min-by-option -+ [ ] rich-string%to-string -+ [ ] rich-string%make-string -+ [ ] rich-string%to-vector -+ [ ] rich-string%to-rich-vector ++ [x] rich-string%forall ++ [x] rich-string%exists ++ [x] rich-string%contains ++ [x] rich-string%index-of ++ [x] rich-string%map ++ [x] rich-string%filter ++ [x] rich-string%reverse ++ [x] rich-string%for-each ++ [x] rich-string%count ++ [x] rich-string%index-where ++ [x] rich-string%take-while ++ [x] rich-string%drop-while ++ [x] rich-string%to-string ++ [x] rich-string%to-vector ++ [x] rich-string%to-rich-vector ++ [x] rich-string%+ ++ [x] rich-string%strip-left ++ [x] rich-string%strip-right ++ [x] rich-string%strip-both ++ [x] rich-string%strip-prefix ++ [x] rich-string%strip-suffix ++ [x] rich-string%replace-first ++ [x] rich-string%replace ++ [x] rich-string%pad-left ++ [x] rich-string%pad-right ++ [x] rich-string%split ++ [x] rich-string%equals ++ [x] rich-string%flat-map ++ [x] rich-string%fold ++ [x] rich-string%fold-right ++ [x] rich-string%sort-with ++ [x] rich-string%sort-by ++ [x] rich-string%group-by ++ [x] rich-string%sliding ++ [x] rich-string%zip ++ [x] rich-string%zip-with-index ++ [x] rich-string%distinct ++ [x] rich-string%reduce ++ [x] rich-string%reduce-option ++ [x] rich-string%max-by ++ [x] rich-string%min-by ++ [x] rich-string%append ++ [x] rich-string%max-by-option ++ [x] rich-string%min-by-option ++ [x] rich-string%make-string ## 任务相关的代码文件 参考代码(一般情况下不修改,除非有缺陷): @@ -80,8 +77,9 @@ - tests/goldfish/liii/lang-test.scm 测试用例: -- tests/goldfish/liii/rich-string-test.scm (已创建并包含20个方法的测试) +- tests/goldfish/liii/rich-string-test.scm - tests/goldfish/liii/rich-string2-test.scm +- tests/goldfish/liii/rich-string3-test.scm ## 如何测试 ``` @@ -90,6 +88,8 @@ xmake b goldfish bin/lint goldfish/liii/rich-string.scm bin/lint tests/goldfish/liii/rich-string-test.scm bin/goldfish -m r7rs tests/goldfish/liii/rich-string-test.scm +bin/goldfish -m r7rs tests/goldfish/liii/rich-string2-test.scm +bin/goldfish -m r7rs tests/goldfish/liii/rich-string3-test.scm ``` ## 测试用例标准:精简 diff --git a/goldfish/liii/rich-string.scm b/goldfish/liii/rich-string.scm index db3278b82186f7625e148fa5347bc0cdd8492632..70813980274f25776c131657d445a5d8fa64da4f 100644 --- a/goldfish/liii/rich-string.scm +++ b/goldfish/liii/rich-string.scm @@ -20,7 +20,8 @@ (liii base) (liii rich-char) (liii rich-vector) - (liii vector)) + (liii vector) + (liii error)) (export rich-string) (begin @@ -197,6 +198,14 @@ :map (lambda (x) (x :make-string)) :make-string)))) + (define (%flat-map func . args) + (chain-apply args + (let ((result-string "")) + (do ((index 0 (+ index 1))) + ((>= index N) (rich-string result-string)) + (let ((mapped-result (func (%char-at index)))) + (set! result-string (string-append result-string (mapped-result :get)))))))) + (define (%filter pred . args) (chain-apply args (rich-string ((%to-rich-vector) @@ -277,6 +286,18 @@ (else (type-error (string-append (object->string s) "is not string or rich-string or number")))))) + (define (%append s . args) + (chain-apply args + (cond + ((string? s) + (rich-string (string-append data s))) + ((rich-string :is-type-of s) + (rich-string (string-append data (s :get)))) + ((number? s) + (rich-string (string-append data (number->string s)))) + (else + (type-error (string-append (object->string s) "is not string or rich-string or number")))))) + (define (%strip-left . args) (chain-apply args (rich-string (string-trim data)))) @@ -331,17 +352,172 @@ (define (%split sep) (let ((str-len N) (sep-len (utf8-string-length sep))) - + (define (split-helper start acc) (let ((next-pos (%index-of sep start))) (if (= next-pos -1) (cons (%drop start :get) acc) (split-helper (+ next-pos sep-len) (cons (%slice start next-pos :get) acc))))) - + (if (zero? sep-len) ((%to-rich-vector) :map (lambda (c) (c :make-string))) (rich-vector (reverse-list->vector (split-helper 0 '())))))) + (define (%equals that) + (cond + ((not (rich-string :is-type-of that)) + #f) + (else + (string=? data (that :get))))) + + (define (%fold f init . args) + (chain-apply args + (let loop ((i 0) (acc init)) + (if (>= i N) + acc + (loop (+ i 1) (f acc (%char-at i))))))) + + (define (%fold-right f init . args) + (chain-apply args + (let loop ((i (- N 1)) (acc init)) + (if (< i 0) + acc + (loop (- i 1) (f acc (%char-at i))))))) + + (define (%sort-with comparator . args) + (chain-apply args + (rich-string ((%to-rich-vector) + :sort-with comparator + :map (lambda (x) (x :make-string)) + :make-string)))) + + (define (%sort-by f . args) + (chain-apply args + (rich-string ((%to-rich-vector) + :sort-by f + :map (lambda (x) (x :make-string)) + :make-string)))) + + (define (%group-by f . args) + (chain-apply args + ((%to-rich-vector) :group-by f))) + + (define (%sliding size . step-arg) + (unless (integer? size) (type-error "rich-string%sliding: size must be an integer " size)) + (unless (> size 0) (value-error "rich-string%sliding: size must be a positive integer " size)) + + (if (zero? N) + (rich-vector #()) + (let* ((is-single-arg-case (null? step-arg)) + (step (if is-single-arg-case 1 (car step-arg)))) + + ;; Validate step if provided + (when (and (not is-single-arg-case) + (or (not (integer? step)) (<= step 0))) + (if (not (integer? step)) + (type-error "rich-string%sliding: step must be an integer " step) + (value-error "rich-string%sliding: step must be a positive integer " step))) + + ;; single-argument version when N < size + (if (and is-single-arg-case (< N size)) + (rich-vector (vector (%this))) + (let collect-windows ((current-idx 0) (result-windows '())) + (cond + ;; Stop if current_idx is out of bounds + ((>= current-idx N) (rich-vector (list->vector (reverse result-windows)))) + ;; For single-arg case + ((and is-single-arg-case (> (+ current-idx size) N)) + (rich-vector (list->vector (reverse result-windows)))) + (else + (let* ((window-end (if is-single-arg-case + (+ current-idx size) ;; Single-arg: always takes full 'size' + (min (+ current-idx size) N))) ;; Two-arg: can be partial + (window (%slice current-idx window-end))) + (collect-windows (+ current-idx step) (cons window result-windows)))))))))) + + (define (%zip-with-index . args) + (chain-apply args + ((%to-rich-vector) :zip-with-index))) + + (define (%zip other . args) + (chain-apply args + ((%to-rich-vector) :zip (other :to-rich-vector)))) + + (define (%reduce f . args) + (chain-apply args + (if (zero? N) + (value-error "rich-string%reduce: cannot reduce an empty string") + (let loop ((i 1) (acc (%char-at 0))) + (if (>= i N) + acc + (loop (+ i 1) (f acc (%char-at i)))))))) + + (define (%reduce-option f . args) + (chain-apply args + (if (zero? N) + (none) + (let loop ((i 1) (acc (%char-at 0))) + (if (>= i N) + (option acc) + (loop (+ i 1) (f acc (%char-at i)))))))) + + (define (%max-by f) + (when (not (procedure? f)) + (type-error "rich-string%max-by: f must be a procedure")) + + (if (zero? N) + (value-error "rich-string%max-by: cannot find max in an empty string") + (let loop ((i 1) + (max-elem (%char-at 0)) + (max-val (f (%char-at 0)))) + (if (>= i N) + max-elem + (let* ((current-elem (%char-at i)) + (current-val (f current-elem))) + (unless (number? current-val) + (type-error "f must return a number")) + (if (> current-val max-val) + (loop (+ i 1) current-elem current-val) + (loop (+ i 1) max-elem max-val))))))) + + (define (%max-by-option f) + (when (not (procedure? f)) + (type-error "rich-string%max-by-option: f must be a procedure")) + + (if (zero? N) + (none) + (option (%max-by f)))) + + (define (%min-by f) + (when (not (procedure? f)) + (type-error "rich-string%min-by: f must be a procedure")) + + (if (zero? N) + (value-error "rich-string%min-by: cannot find min in an empty string") + (let loop ((i 1) + (min-elem (%char-at 0)) + (min-val (f (%char-at 0)))) + (if (>= i N) + min-elem + (let* ((current-elem (%char-at i)) + (current-val (f current-elem))) + (unless (number? current-val) + (type-error "f must return a number")) + (if (< current-val min-val) + (loop (+ i 1) current-elem current-val) + (loop (+ i 1) min-elem min-val))))))) + + (define (%min-by-option f) + (when (not (procedure? f)) + (type-error "rich-string%min-by-option: f must be a procedure")) + + (if (zero? N) + (none) + (option (%min-by f)))) + + (define (%make-string) + data) + ) ) diff --git a/goldfish/liii/rich-vector.scm b/goldfish/liii/rich-vector.scm index 6fee342fb02e06b4120bf08151f048c51175800c..721c15692bdb4b0309a9c75b11925df54bbba006 100644 --- a/goldfish/liii/rich-vector.scm +++ b/goldfish/liii/rich-vector.scm @@ -15,7 +15,7 @@ ; (define-library (liii rich-vector) - (import (liii string) (liii hash-table) (liii sort) (liii list) (liii vector) (liii oop) (srfi srfi-8)) + (import (liii string) (liii hash-table) (liii sort) (liii list) (liii vector) (liii oop) (liii rich-hash-table) (srfi srfi-8)) (export rich-vector) (begin diff --git a/tests/goldfish/liii/lang-test.scm b/tests/goldfish/liii/lang-test.scm index bcc1fde76b055c19f40b2f790b021404fb2c714e..d286cf507ce509272e8ca9ad2ec8af46f764bc1a 100644 --- a/tests/goldfish/liii/lang-test.scm +++ b/tests/goldfish/liii/lang-test.scm @@ -581,260 +581,6 @@ (check ((rich-char #x4E2D) :make-string) => "中") (check ((rich-char #x1F600) :make-string) => "😀") -(check-true (rich-string :is-type-of ($ "Hello"))) - -(check-false (rich-string :is-type-of "hello")) -(check-false (rich-string :is-type-of 1)) -(check-false (rich-string :is-type-of (box 1))) - -(check (rich-string :value-of #\a) => "a") -(check (rich-string :value-of 'a) => "a") -(check (rich-string :value-of 123) => "123") -(check (rich-string :value-of 1.0) => "1.0") -(check (rich-string :value-of "abc") => "abc") -(check (rich-string :value-of (rich-char #x4E2D)) => "中") -(check (rich-string :value-of #\ ) => " ") - -(check ($ "abc" :get) => "abc") -(check ($ "" :get) => "") - -(check ((rich-string "abc") :length) => 3) -(check ((rich-string "中文") :length) => 2) -(check (rich-string :empty :length) => 0) - -(let1 str ($ "你好,世界") - (check (str :char-at 0) => (rich-char #x4F60)) ;; "你" 的 Unicode 码点 - (check (str :char-at 1) => (rich-char #x597D)) ;; "好" 的 Unicode 码点 - (check (str :char-at 2) => (rich-char #xFF0C)) ;; "," 的 Unicode 码点 - (check (str :char-at 3) => (rich-char #x4E16)) ;; "世" 的 Unicode 码点 - (check (str :char-at 4) => (rich-char #x754C)) ;; "界" 的 Unicode 码点 - (check-catch 'out-of-range (str :char-at 10))) - -(let1 str ($ "Hello,世界") - (check (str 0) => ($ #\H)) - (check (str 7) => (rich-char :from-string "#\\界"))) - -(let1 s ($ "你好世界HelloWord") - (check ((s :find (@ _ :equals ($ "你" 0))) :get) - => ($ "你" 0)) - (check-true ((s :find (@ _ :equals ($ "师" 0))) :empty?))) - -(let1 s ($ "你好世界HelloWord") - (check ((s :find-last (@ _ :equals ($ "你" 0))) :get) - => ($ "你" 0)) - (check-true ((s :find-last (@ _ :equals ($ "师" 0))) :empty?))) - -(check ($ "你好" :head) => ($ "你" 0)) -(check-catch 'index-error (rich-string :empty :head)) -(check ($ "hello" :head-option) => (option #\h)) -(check (rich-string :empty :head-option) => (none)) - -(check ($ "你好" :last) => ($ "好" 0)) -(check-catch 'index-error (rich-string :empty :last)) - -(check ($ "hello" :last-option) => (option #\o)) -(check (rich-string :empty :last-option) => (none)) - -(let1 str ($ "Hello,世界") - (check (str :slice 0 5) => ($ "Hello")) - (check (str :slice -10 5) => ($ "Hello")) - (check (str :slice 6 100) => ($ "世界")) - (check (str :slice 6 2) => ($ "")) - (check (str :slice -3 -2) => ($ "")) - (check (str :slice 100 101) => ($ "")) - (check (str :slice -1 100) => ($ "Hello,世界")) - (check (str :slice 0 5 :to-string) => "Hello")) - -(let1 str ($ "Hello,世界") - (check (str :take -1) => "") - (check (str :take 0) => "") - (check (str :take 1) => "H") - (check (str :take 8) => "Hello,世界") - (check (str :take 9) => "Hello,世界")) - -(let1 str ($ "Hello,世界") - (check (str :take-right -1) => "") - (check (str :take-right 0) => "") - (check (str :take-right 1) => "界") - (check (str :take-right 8) => "Hello,世界") - (check (str :take-right 9) => "Hello,世界")) - -(let1 str ($ "Hello,世界") - (check (str :drop 1) => "ello,世界") - (check (str :drop 0) => "Hello,世界") - (check (str :drop -1) => "Hello,世界") - (check (str :drop 6) => "世界") - (check (str :drop 7) => "界") - (check (str :drop 8) => "") - (check (str :drop 9) => "")) - -(check (rich-string :empty :drop 1) => "") - -(let1 str ($ "Hello,世界") - (check (str :drop-right -1) => "Hello,世界") - (check (str :drop-right 0) => "Hello,世界") - (check (str :drop-right 1) => "Hello,世") - (check (str :drop-right 8) => "") - (check (str :drop-right 8) => "")) - -(check ($ "42") => ($ "42")) -(check-false ($ "41" :equals ($ "42"))) - -(check-true ((rich-string "") :empty?)) -(check-false ((rich-string "abc") :empty?)) - -(check-false ($ "全部都是中文" :forall (@ _ :digit?))) - -(check-true ($ "全部都是中文" :exists (@ _ :equals (rich-char :from-string "#\\中")))) - -(let1 str (rich-string "Hello, World!") - (check-true (str :contains #\W)) - (check-true (str :contains "Hello")) - (check-true (str :contains "")) - (check-true (str :contains (rich-char #\W))) - (check-true (str :contains ($ ""))) - (check-true (str :contains ($ "Hello")))) - -(let1 str (rich-string "你好世界") - (check-true (str :contains "好世")) - (check-true (str :contains "你")) - (check-true (str :contains ($ "你" 0)))) - -(let1 str (rich-string "你好,世界!") - (check (str :index-of ($ "你")) => 0) - (check (str :index-of ($ "好")) => 1) - (check (str :index-of ($ "世")) => 3) - (check (str :index-of ($ "界")) => 4) - (check (str :index-of ($ "!")) => 5) - (check (str :index-of ($ "中" 0)) => -1) - (check (str :index-of (rich-string "你好")) => 0) - (check (str :index-of (rich-string "世界")) => 3) - (check (str :index-of (rich-string "你好,世界")) => 0) - (check (str :index-of (rich-string "世界!")) => 3) - (check (str :index-of (rich-string "你好,世界!")) => 0) - (check (str :index-of (rich-string "中国")) => -1) - (check (str :index-of ($ "你") 1) => -1) - (check (str :index-of (rich-string "世界") 4) => -1)) - -(let1 str (rich-string "Hello😀World") - (check (str :index-of ($ "😀")) => 5) - (check (str :index-of (rich-string "😀")) => 5) - (check (str :index-of (rich-string "Hello😀")) => 0) - (check (str :index-of (rich-string "😀World")) => 5) - (check (str :index-of ($ "😀") 6) => -1) - (check (str :index-of (rich-string "😀World") 6) => -1)) - -(check ($ "Hello" :index-of #\e) => 1) -(check ($ "Hello" :index-of #\e 5) => -1) -(check ($ "Hello" :index-of #\e -1) => 1) - -(let1 s ($ "abc" :map (lambda (c) (c :to-upper))) - (check s => "ABC") - (check (s :length) => 3)) - -(check ($ "abc中文" :map (lambda (c) (c :to-upper))) => "ABC中文") - -(check ($ "Hello123" :filter (@ _ :ascii?)) => "Hello123") -(check ($ "123abc" :filter (@ _ :digit?)) => "123") -(check ($ "ABCabc" :filter (@ _ :upper?)) => "ABC") -(check ($ "你好世界hello" :filter (@ _ :equals ($ "你" 0))) => ($ "你")) - -(check ($ "Hello123" :filter (@ _ :ascii?) :reverse) => "321olleH") -(check ($ "123abc" :filter (@ _ :digit?) :reverse) => "321") -(check ($ "ABCabc" :filter (@ _ :upper?) :reverse) => "CBA") -(check ($ "你好世界" :drop-while (@ _ :equals ($ "你" 0)) :reverse) => "界世好") - -(check ($ "" :count (@ class=? _ #\A)) => 0) -(check ($ "hello" :count (@ class=? _ #\l)) => 2) -(check ($ "你好,我是韩梅梅" :count (@ class=? _ (rich-char :from-string "#\\梅"))) => 2) - -(check ($ "Hello" :index-where (@ _ :equals (rich-char #\e))) => 1) -(check ($ "" :index-where (@ _ :digit?)) => -1) -(check ($ "abc" :index-where (@ _ :digit?)) => -1) -(check ($ "中文" :index-where (@ _ :equals (rich-char #x4E2D))) => 0) -(check ($ "中文" :index-where (@ _ :equals (rich-char #x6587))) => 1) - -(check ($ "Hello123" :take-while (@ _ :ascii?)) => "Hello123") -(check ($ "123abc" :take-while (@ _ :digit?)) => "123") -(check ($ "你好World" :take-while (@ _ :ascii?)) => "") -(check ($ "" :take-while (@ _ :ascii?)) => "") -(check ($ "ABC" :take-while (@ _ :upper?)) => "ABC") -(check ($ "123abc" :take-while (@ _ :digit?)) => ($ "123")) -(check ($ "你好世界hello" :take-while (@ _ :equals ($ "你" 0))) => ($ "你")) -(check ($ "aaaaa" :take-while (@ _ :equals (rich-char #\a)) :get) => "aaaaa") -(check ($ "" :take-while (@ _ :digit?)) => "") - -(check ($ " hello" :drop-while (@ _ :equals (rich-char #\space))) => "hello") -(check ($ "123abc" :drop-while (@ _ :digit?)) => "abc") -(check ($ "你好世界" :drop-while (@ _ :equals ($ "你" 0))) => "好世界") -(check ($ "" :drop-while (@ _ :equals (rich-char #\a))) => "") -(check ($ "aaaa" :drop-while (@ _ :equals (rich-char #\a))) => "") - -(check ((rich-string "hello") :to-string) => "hello") - -(let1 v ($ "中文" :to-vector) - (check (v 0) => (rich-char :from-string "#\\中")) - (check (v 1) => (rich-char :from-string "#\\文"))) - -(let1 v ($ "hello" :to-vector) - (check (v 0) => (box #\h)) - (check (v 4) => (rich-char #\o))) - -(let1 v ($ "中文的" :to-rich-vector) - (check (v :length) => 3) - (check (v 0) => (rich-char :from-string "#\\中")) - (check (v 1) => (rich-char :from-string "#\\文")) - (check (v 2) => (rich-char :from-string "#\\的"))) - -(check ($ "Hello" :+ " " :+ "World") => "Hello World") -(check ($ "hello " :+ (box "world")) => "hello world") -(check ($ "Hello " :+ 2025) => "Hello 2025") -(check ($ "Price is " :+ 1.2) => "Price is 1.2") - -(check ($ " abc " :strip-left) => "abc ") -(check ($ " abc" :strip-left) => "abc") -(check ($ "\t\n abc" :strip-left) => "abc") -(check ($ " \t \n abc \t \n " :strip-left) => "abc \t \n ") -(check ($ "" :strip-left) => "") -(check ($ " " :strip-left) => "") - -(check ($ " abc " :strip-right) => " abc") -(check ($ "abc " :strip-right) => "abc") -(check ($ "abc \t\n" :strip-right) => "abc") -(check ($ " \t \n abc \t \n " :strip-right) => " \t \n abc") -(check ($ "" :strip-right) => "") -(check ($ " " :strip-right) => "") - -(check ($ " abc " :strip-both) => "abc") -(check ($ " abc " :strip-both) => "abc") -(check ($ "\t\n abc \t\n" :strip-both) => "abc") -(check ($ " \t \n abc \t \n " :strip-both) => "abc") -(check ($ "" :strip-both) => "") -(check ($ " " :strip-both) => "") - -(check ($ "" :strip-prefix "") => ($ "")) -(check ($ "hello" :strip-prefix "") => ($ "hello")) -(check ($ "hello" :strip-prefix "he") => ($ "llo")) -(check ($ "hello" :strip-prefix "hello") => ($ "")) -(check ($ "hello" :strip-prefix "abc") => ($ "hello")) -(check ($ "hello" :strip-prefix "helloo") => ($ "hello")) -(check ($ "hello" :strip-prefix "he" :strip-prefix "ll") => ($ "o")) -(check ($ "世界" :strip-prefix "世") => "界") - -(check-catch 'wrong-number-of-args ("hello":strip-prefix "he")) -(check-catch 'unbound-variable (123:strip-prefix 1)) - -(check ($ "" :strip-suffix "") => ($ "")) -(check ($ "hello" :strip-suffix "") => ($ "hello")) -(check ($ "hello" :strip-suffix "lo") => ($ "hel")) -(check ($ "hello" :strip-suffix "hello") => ($ "")) -(check ($ "hello" :strip-suffix "abc") => ($ "hello")) -(check ($ "hello" :strip-suffix "hhello") => ($ "hello")) -(check ($ "hello" :strip-suffix "lo" :strip-suffix "el") => ($ "h")) -(check ($ "世界" :strip-suffix "界") => "世") - -(check-catch 'wrong-number-of-args ("hello":strip-suffix "llo")) - (check ($ "hahaha" :replace-first "a" "oo") => ($ "hoohaha")) (check ($ "hello" :replace-first "world" "") => ($ "hello")) (check ($ "hello" :replace-first "l" "L" :strip-prefix "he") => ($ "Llo")) diff --git a/tests/goldfish/liii/rich-string3-test.scm b/tests/goldfish/liii/rich-string3-test.scm new file mode 100644 index 0000000000000000000000000000000000000000..dfb91f4e186fd3a1cf85b8a0c895e7c07a501105 --- /dev/null +++ b/tests/goldfish/liii/rich-string3-test.scm @@ -0,0 +1,96 @@ +; +; Copyright (C) 2025 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. +; + +(import (liii check) + (scheme base) + (liii rich-string) + (liii lang) + (liii error) + (liii rich-vector) + (liii option)) + +(check-set-mode! 'report-failed) + +#| +rich-string%make-string +将rich-string对象转换为普通的字符串。 + +语法 +---- +(rich-string-instance :make-string) + +参数 +---- +无参数。 + +返回值 +----- +返回一个字符串,包含rich-string对象的内容。 + +说明 +---- +该方法将rich-string对象转换为普通的字符串。 +返回的字符串包含rich-string对象中的所有字符。 +该方法正确处理Unicode字符,能够准确转换多字节编码的字符。 + +边界条件 +-------- +- 空字符串:返回空字符串 +- 单字符字符串:返回包含该字符的字符串 +- 多字符字符串:返回包含所有字符的字符串 +- Unicode字符:正确处理Unicode字符的转换 + +性能特征 +-------- +- 时间复杂度:O(1),直接返回内部存储的字符串 +- 空间复杂度:O(1),不创建新的字符串对象 + +兼容性 +------ +- 与所有rich-string实例兼容 +- 支持链式操作 +|# + +;; 基本功能测试 +;; 普通字符串转换 +(check ((rich-string :value-of "hello") :make-string) => "hello") + +;; 空字符串转换 +(check ((rich-string :empty) :make-string) => "") + +;; 边界条件测试 +;; 单字符字符串 +(check ((rich-string :value-of "a") :make-string) => "a") + +;; Unicode字符转换测试 +(check ((rich-string :value-of "测试") :make-string) => "测试") + +;; 验证返回类型 +(check (string? ((rich-string :value-of "hello") :make-string)) => #t) + +;; 验证原字符串不变性 +(let ((original (rich-string :value-of "hello"))) + (original :make-string) + (check (original :get) => "hello")) + +;; 链式操作测试 +(check ((rich-string :value-of "abc") :make-string) => "abc") + +;; 与%get方法的对比测试 +(let ((rs (rich-string :value-of "hello"))) + (check (rs :make-string) => (rs :get))) + +(check-report) \ No newline at end of file