Given that you already iterate through the list, it can be made cheap to get the last item:
(def prl args ;returns last arg
(let u args
(while cdr.u
(pr car.u)
(zap cdr u))
(pr car.u)))
arc> (prl 1 2 3)
1233
Even though 'u points to the list 'args, I can modify 'u to point to another part of the list, and the list itself is not modified. I thus traverse the list only once here.
Also, note that the REPL prints the return value on the same line as whatever other output. I think this is annoying. Common Lisp has a 'fresh-line procedure that prints a newline to an output-stream if and only if at least one character has been printed to that stream and the last character printed was not a newline. It would be nice to use that in the toplevel procedure.
Having written that, I looked at the PLT docs and figured out how to at least tell whether nothing has been written to an output-port since the last time you checked, and I hacked the toplevel function in ac.scm to print a newline when the expression printed something, whether or not that something ended with a newline. I'm not sure whether I like this better:
arc> "ach"
"ach"
arc> (pr "ach")
ach
"ach"
arc> (prn "ach")
ach
"ach"
Changes in ac.scm (I haven't learned to use diff, so I'll record them like this):
;Relevant part of resulting definition of tl2 in ac.scm:
(if (eqv? expr ':a)
'done
(let ((n (next-char-place))
(val (arc-eval expr)))
(if (< n (next-char-place))
(newline))
(write (ac-denil val))
;Then add this:
(define (next-char-place)
(let-values (((a b n) (port-next-location (current-output-port))))
n))