Proposed amendments to SRFI-13 Donald Welsh 23 Oct 1999 12:15 UTC
Hello everyone. A few comments and suggestions on SRFI-13. string-take string-drop string-take-right string-drop-right substring-move-left substring-move-right These (if needed) can all be defined as special cases of a more general function, string-replace. string-replace s1 start end s2 -> string replace the substring of s1 from start to end with s2 A variant, string-replace! could also be defined, which is allowed to reuse the original storage of s1. With a regexp package, regexp matching could used to find start and end points, then string-replace could perform the replacement. My sample code defines two equivalent versions of string-replace. String-replace-simple does string replacement using substrings and append; string-replace allocates a new string and copies characters into it. ------------ reverse-string-concatenate string-list [end] -> string reverse-string-concatenate/shared string-list [end] -> string Why are these included? Without the optional parameter, the stated equivalents are clearer. With END these functions are odd -- why are they needed? ------------ string-filter s char/char-set/pred [start end] -> string string-delete s char/char-set/pred [start end] -> string The char/char-set/pred isn't intuitive. If char-sets are needed, perhaps there should be a set package SRFI (is there one already?), or the functionality could be provided by a regexp package. Suggest dropping string-delete and using an alternative version of string-filter which uses a string -> string function f instead of char/char-set/pred. (String deletion can be done by f returning "".) The function f should go first, as with map and string-map. string-filter f s [start end] -> string construct a string by applying f to each character of s function f should take a string of length one as input, and output a string (of any length) ------------ Example code (written in MzScheme) is below. Enjoy. ;;; dw-string.scm -- a few string manipulation functions ;;; these functions are for illustration, and lack error checking ; filter a string s using function f (define (string-filter f s . endpoints) (let ((start 0) (end (string-length s))) (if (not (null? endpoints)) (begin (set! start (car endpoints)) (set! end (cadr endpoints)))) (string-append (substring s 0 start) (apply string-append (map f (map string (string->list (substring s start end))))) (substring s end (string-length s))))) ; map a character-transforming function over a string ; does not take substring endpoints (define (string-map f s) (list->string (map f (string->list s)))) ; destructive version of string-map ; modifies the original string ; does not take substring endpoints (define (string-map! f s) (do ((i (- (string-length s) 1) (- i 1))) ((< i 0) 'ok) (string-set! s i (f (string-ref s i))))) ; replace substring of s1 with s2 (define (string-replace-simple s1 start end s2) (string-append (substring s1 0 start) s2 (substring s1 end (string-length s1)))) ; string-copy!, needed for efficient version of replacement ; substring endpoints should be optional (define (string-copy! target tstart s start end) (do ((i tstart (+ i 1)) (j start (+ j 1))) ((= j end) 'ok) (string-set! target i (string-ref s j)))) ; replacement, efficient version ; equivalent to string-replace-simple (define (string-replace s1 start end s2) (let ((result (make-string (+ (string-length s1) (- start end) ; this should be nonpositive (string-length s2))))) ; copy first part of s1 into result (string-copy! result 0 s1 0 start) ; copy s2 into result (string-copy! result start s2 0 (string-length s2)) ; copy second part of s1 into result (string-copy! result (+ start (string-length s2)) s1 end (string-length s1)) ; return result result)) ;; the first two functions below demonstrate uses of string-filter ;; which could not be done by string-map ; test string-filter: remove the vowels from a string (define (remove-vowels s) (string-filter (lambda (s1) (if (member (string-ref s1 0) (string->list "AEIOUaeiou")) "" (substring s1 0 1))) s)) ; another example of string-filter (define (local-echo s) (string-filter (lambda (s1) (string-append s1 s1)) s)) ;; example of using string-map ; rot13 of a character (define (rot13 c) (cond ((char-upper-case? c) (integer->char (if (char<? c #\N) (+ (char->integer c) 13) (- (char->integer c) 13)))) ((char-lower-case? c) (integer->char (if (char<? c #\n) (+ (char->integer c) 13) (- (char->integer c) 13)))) (else c))) ; rot13 of a string (define (string-rot13 s) (string-map rot13 s))