Maybe we can get the best of both worlds. Let's do the following.
We can implement this in Scheme via a macro:
(extend-syntax (proc-by-value-result)
[(proc-by-value-result (id ...) body ...)
(with ([(newvar ...) (map (lambda (x) (gensym)) '(id ...))])
(lambda (newvar ...)
(let ([id (box (^ newvar))] ...)
(let ([result (begin body ...)])
(:= newvar (^ id)) ...
result))))])
This differs from the macro for proc-by-value only in the assignments to the input parameters at the end. Try a few calls to expand to be sure you understand what is going on. Here's an example.
Try some similar calls of your own.(expand '(proc-by-value-result (x y) (+ (^ foo) (* (^ x) (^ y)))))
Here is the factorial program done by value-result.
(define fac-by-val-result
(proc-by-value-result (x acc)
(while (> (^ x) 0)
(:= acc (* (^ x) (^ acc)))
(:= x (1- (^ x))))))
Run some experiments to see if aliasing is a problem here. How does
this fac-by-val-result return its computed value to the caller?