Hi, For wisp I created an efficient implementation of substring replacement and thought it might be useful for guile in general.
I optimized it a bit to get rid of (likely) quadratic behaviour: ; ,time (string-replace-substring (xsubstring "abcdefghijkl" 0 99999) "def" "abc") ; 1.140127s real time, 1.139714s run time. 0.958733s spent in GC. ; 0.885618s real time, 0.885350s run time. 0.742805s spent in GC. ; second number after multiple runs (define (string-replace-substring s substring replacement) "Replace every instance of substring in s by replacement." (let ((sublen (string-length substring))) (let replacer ((newstring s) (index (string-contains s substring))) (if (not (equal? index #f)) (let ((replaced (string-replace newstring replacement index (+ index sublen)))) (replacer replaced (string-contains replaced substring index))) newstring)))) This fast and elegant approach is thanks to ijp. I tested a two alternative approaches. The following uses explicit readonly substrings and is fast, the one afterwards always searches from the beginning and shows drastic slowdown on long strings. ; efficient version from rev 12266d455bb0 of the wisp hg repo ; ,time (string-replace-substring-fast-but-long (xsubstring "abcdefghijkl" 0 99999) "def" "abc") ; 1.316090s real time, 1.315626s run time. 1.129857s spent in GC. ; 0.668212s real time, 0.667948s run time. 0.482193s spent in GC. ; 0.868419s real time, 0.868131s run time. 0.685472s spent in GC ; Second and third are after multiple runs (define (string-replace-substring-fast-but-long s substring replacement) "Replace every instance of substring in s by replacement." (let ((sublen (string-length substring))) (let replacer ((newstring s) (startindex 0) (addindex (string-contains s substring))) (if (not (equal? addindex #f)) (let* ((index (+ startindex addindex)) (replaced (string-replace newstring replacement index (+ index sublen))) (newaddindex (string-contains (substring/read-only replaced index) substring))) (replacer replaced index newaddindex)) newstring)))) ; less efficient version from rev a887aeb0dfe2 ; ,time (string-replace-substring-slow (xsubstring "abcdefghijkl" 0 99999) "def" "abc") ; 5.242456s real time, 5.240834s run time. 0.358750s spent in GC. ; 5.727069s real time, 5.724973s run time. 0.835445s spent in GC. ; switches between fast and slow version (define (string-replace-substring-slow s substring replacement) "Replace every instance of substring in s by replacement." (let ((sublen (string-length substring))) (let replacer ((newstring s) (index (string-contains s substring))) (if (not (equal? index #f)) (let ((replaced (string-replace newstring replacement index (+ index sublen)))) (replacer replaced (string-contains replaced substring))) newstring)))) ijp suggested renaming to (string-replace-all, but I do not know enough about conventions in guile to judge that). Best wishes, Arne