@waterhouse thank you for your eval-w/stdout function. I tried about twelve variations on the idea but ended up back at exactly the definition you gave. Even one cosmetic change that I was sure would be an improvement turned out to make it harder to read (at least in my opinion):
2. strings.arc, pprint.arc and html.arc are now all included in the sandbox:
arc> (plural 2 "dog")
"2 dogs"
; not indenting properly
arc> (ppr:macex1 '(accum a (each x '(1 2 3) (a x))))
(withs (gs954 nil
a
(fn (_) (push _ gs954)))
(each x (quote (1 2 3)) (a x))
(rev gs954))t
arc> (tag strong (link "Arc Forum" "http://arclanguage.org"))
<strong><a href="http://arclanguage.org">Arc Forum</a></strong>"</strong>"
At least for the moment I'm not including srv.arc, app.arc, code.arc and prompt.arc. Most of their functions couldn't be used in the sandbox anyway, and I can conserve resources (i.e. loading them in for each new user) by leaving them out.
arc> (def average (x y)
> (prn "my arguments were: " (list x y))
> (/ (+ x y) 2))
#<procedure: average>
arc> (average 100 200)
my arguments were: (100 200)
150
It simply checks for balanced parens. I just realized I neglected to check for balanced #\[ and #\] though, so for the moment your square-bracketed functions must be on one line.