Good analysis, Danny.<br>It&#39;s mainly due to the linear time required by string-append and maybe string-length. If there had been a constant-time string-cons, we would have had linear time.<br>This can still be done by converting to lists:<br>

(define (string-&gt;mformat-3 str n filler)<br>  (let loop ([l (string-&gt;list str)] [len (string-length str)])<br>    (if (&gt;= len n)<br>        (list-&gt;string l)<br>        (loop (cons filler l) (add1 len)))))<br>
<br>
There is still an overhead though, probably from the conversion from a big list to a big string:<br>trial 10000000<br>2:<br>cpu time: 348 real time: 347 gc time: 36<br>3:<br>cpu time: 4957 real time: 4959 gc time: 3740<br>

<br>Actually, version 3 is in fact  in O(n log n)  because of the add1 (maybe also because of len, depending on how it  is treated on the loop call).<br>Version 2 is also probably in O(n log n), but maybe there can be some nice compilation trick to prevent that.<br>

Although we are of course bounded by the addressable memory space (but Racket programs are supposed to be independent of that, I think).<br><br>Laurent<br><br><div class="gmail_quote">On Fri, Sep 28, 2012 at 10:38 PM, Danny Yoo <span dir="ltr">&lt;<a href="mailto:dyoo@hashcollision.org" target="_blank">dyoo@hashcollision.org</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">&gt; It is also possible to use build-string, without using explicit recursion:<br>
&gt; (define (string-&gt;mformat str n filler)<br>
&gt;   (string-append<br>
&gt;    (build-string (max 0 (- n (string-length str)))<br>
&gt;                  (lambda (x) filler))<br>
&gt;    str))<br>
<br>
<br>
</div>Hi Laurent,<br>
<br>
I like this one much more because it won&#39;t have the quadratic behavior<br>
that the first solution will exhibit on sufficiently large n.<br>
<br>
<br>
It&#39;s neat to see how the two compare in terms of time.  Here&#39;s a small<br>
test program:<br>
<br>
###########################<br>
#lang racket<br>
<br>
;; string-&gt;mformat-1: string number char -&gt; string<br>
(define (string-&gt;mformat-1 str n filler)<br>
<div class="im">  (if (equal? (string-length str) n)<br>
      str<br>
</div>      (string-&gt;mformat-1 (string-append (string filler) str)<br>
                         n<br>
                         filler)))<br>
<br>
;; string-&gt;mformat-2: string number char -&gt; string<br>
(define (string-&gt;mformat-2 str n filler)<br>
<div class="im">  (string-append<br>
   (build-string (max 0 (- n (string-length str)))<br>
                 (lambda (x) filler))<br>
   str))<br>
<br>
<br>
</div>;; test: number -&gt; void<br>
;; Just show how the two functions compare.<br>
(define (test n)<br>
  (printf &quot;trial ~a\n&quot; n)<br>
  (displayln &quot;1:&quot;)<br>
  (time (void (string-&gt;mformat-1 &quot;foo&quot; n #\0)))<br>
  (displayln &quot;2:&quot;)<br>
  (time (void (string-&gt;mformat-2 &quot;foo&quot; n #\0)))<br>
  (newline))<br>
<br>
<br>
(for ([n &#39;(10 100 1000 10000 100000)])<br>
  (test n))<br>
###########################<br>
<br>
<br>
<br>
We&#39;ll compare the two versions to see how they perform.  Here&#39;s what I<br>
see on my machine:<br>
<br>
<br>
###########################<br>
trial 10<br>
1:<br>
cpu time: 0 real time: 0 gc time: 0<br>
2:<br>
cpu time: 0 real time: 0 gc time: 0<br>
<br>
trial 100<br>
1:<br>
cpu time: 0 real time: 0 gc time: 0<br>
2:<br>
cpu time: 0 real time: 0 gc time: 0<br>
<br>
trial 1000<br>
1:<br>
cpu time: 0 real time: 0 gc time: 0<br>
2:<br>
cpu time: 0 real time: 0 gc time: 0<br>
<br>
trial 10000<br>
1:<br>
cpu time: 141 real time: 152 gc time: 78<br>
2:<br>
cpu time: 1 real time: 0 gc time: 0<br>
<br>
trial 100000<br>
1:<br>
cpu time: 20866 real time: 22001 gc time: 8670<br>
2:<br>
cpu time: 2 real time: 2 gc time: 0<br>
###########################<br>
<br>
<br>
We can see that the performance of string-&gt;mformat-1 starts to falter<br>
as n grows.  The string-&gt;mformat-2 function is better because it does<br>
not repeatedly use string-append on the accumulated result.<br>
</blockquote></div><br>