| I'm wondering why copylist in Arc 3.1 isn't tail-recursive. sort copies lists, so sort requires a lot of stack space
also.  (def copylist (xs)
    (if (no xs) 
        nil 
        (cons (car xs) (copylist (cdr xs)))))
 MzScheme seems to deal with this really well, I suspect
it calls malloc() to make the stack bigger when needed. Unfortunately, Jarc falls over with a StackOverflowError. So I'm replacing copylist in Jarc with something like I tried the tail-recursive copylist2 in Arc 3.1 and it
runs 9 times slower than the original.  (def copylist2 (xs (o acch) (o acct))
    (if (no xs)
        acch
        (no acch)
        (do
          (assign acch (cons (car xs) nil))
          (copylist2 (cdr xs) acch acch))
        (copylist2 (cdr xs) acch (scdr acct (cons (car xs) nil)))))
 The scdr solution is so slow that it's faster to 
iterate the list twice and copy it twice!  arc> (let td (n-of 10000 t) (time (copylist td)) 1)
  time: 3 msec.
  1
  arc> (let td (n-of 10000 t) (time (copylist2 td)) 1)
  time: 27 msec.
  1
 The rev solution takes about twice as long
as the original.  That makes sense since it does twice
as many cons calls.  (def copylist4 (xs (o acc))
    (if (no xs)
        (rev acc)
        (copylist4 (cdr xs) (cons (car xs) acc))))
  arc> (let td (n-of 10000 t) (time (copylist4 td)) 1)
  time: 7 msec.
 So copylist appears to be optimal as it is. Fortunately in Jarc, copylist2 is only twice as slow
as copylist. That seems reasonable since it does N scdr
calls in addition to the N cons calls, assuming the car
and cdr calls are much faster than cons and scdr.  I can
live with that to avoid the StackOverflowError. |