I definitely think that shunting stderr to stdout, or any other method of displaying errors would make a huge difference.
I agree with you and am working on it. The only reason I've hesitated with that feature is that certain errors reveal information about the sandboxing mechanism I'm not sure I want people to have.
arc> (system "ls")
subprocess: `execute' access denied for /bin/sh
Maybe it's not really an issue at all, but it is something I've worried about. I could probably hedge my bets by displaying more generic error messages than the ones the sandbox provides.
Other than that, it's really rather cool. Great job!
The ambiguities of certain names in Arc really used to confuse me. acons is the cons predicate and alist the list predicate, but afn isn't the function predicate. Moreover, alist has nothing to do with alists (association lists).
Now that I have better command over the language, these things don't bother me so much. They have their own sense, and I increasingly appreciate how "externally exposed names [are] approximately hamming encoded." [1]
I don't mind short names. Indeed, one of my hopes in learning Arc is to get out from under the sheer bulk of the code I usually have to write to implement my ideas.
Let's go ahead and define afor because it will be less awkward to demo with:
; s/loop/aloop/ was the only change from for's definition
(mac afor (v init max . body)
(w/uniq (gi gm)
`(with (,v nil ,gi ,init ,gm (+ ,max 1))
(aloop (assign ,v ,gi) (< ,v ,gm) (assign ,v (+ ,v 1))
,@body))))
And now check it out!
; prints i from zero to ten, skipping odd values of i
arc> (afor i 0 10
(if (odd i)
(continue)
(pr i)))
*** redefining continue
0246810nil
(Note that since the continue macro gets generated anew on each call to aloop, you'll get the "redefining continue" message every time you call aloop or afor.) You could use the above definitions to spin off labeled versions of down, forlen, each and on, and a similar technique could be applied to redefine the while-family of macros.
I'm pretty sure the second (continue) form is expanded after the inner (afor ...) form is expanded, so that it tries to continue the wrong loop, but ends up referring to an unbound variable instead.
I recommend sticking to an anaphoric variable that has no macro wrapping it, sort of like this:
I'm pretty sure the second (continue) form is expanded after the inner (afor ...) form is expanded, so that it tries to continue the wrong loop, but ends up referring to an unbound variable instead.
Very good point, I hadn't tried to nest them before.
I will try your aloop definition when I get the chance.
Why make another web-based repl for arc when there is already palsecam's evsrv [1], nostrademons' ArcLite [2], thaddeus' wterm project [3] and pg's prompt.arc? (Are there others?)
These projects don't serve identical purposes. Try Arc is meant to be a tool for introducing people to Arc in a hands-on way. Sandboxed eval makes this safe and Chris Done's jquery-console makes it convenient (that is, once I've worked some of the kinks out). It is probably suboptimal for real development though (beyond as some sort of scratchpad) since it doesn't offer persistence: accidentally refresh the page and you lose your work.
prompt.arc, on the other hand, is nice for real development. Not only can you try things out at the repl, but you can plug them in as real applications at the prompt. However, it wouldn't be as good in the Try Arc context since it calls raw eval, granting access to the underlying system (it's a double-edged sword).
evsrv is great. Sandboxed eval plus persistence for multiple users, and you can even start an anonymous session, all at an ajaxified terminal? palsecam mentioned in [4] that he used mzscheme for sandboxing as well; there may be some useful ideas in what he's done for this project.
I haven't actually tried what thaddeus did, has anybody else? I also have less to say about ArcLite, except that it's awesome he got a working implementation of Arc in JavaScript.
I wrote this inspired by sites like Try Ruby and Try Haskell. My hope is that it can become a way for people to experiment with Arc and go through the tutorial without having to install mzscheme.
The REPL points out that it's "lacking certain refinements". These correspond roughly to the TODO list at http://evanrmurphy.posterous.com/try-arc-todo. Bug reports and other feedback are very welcome.
Site is powered by Chris Done's jquery-console, Racket's sandbox library and srv.arc + html.arc. Color scheme and logo borrowed from arclanguage.org.
The sandbox library seems to work fairly well. Using the awesome quasiquote bug/feature that lets you drop to Scheme[0], I was able to evaluate (current-directory) --> "/root/arc/arc3.1/" and (version) --> "4.1.5", but the functions 'directory-list (like "ls"), 'open-output-file, and 'system don't do anything. Also, (current-directory <something>), which would change the current directory, doesn't do anything. That's probably somewhat reassuring to know, security-wise. (Someone has to try these things out, and it may as well be me, who intends to do no harm, before it's someone else, who might feel mischievous.)
By the way, an end-user can emulate stdout by doing something like this:
@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.
Using the awesome quasiquote bug/feature that lets you drop to Scheme...
That is an awesome bug/feature.
To be sure, what you get at that repl isn't pure arc3.1 (at least for now it's not). It's arc3.1 plus anarki's $ minus libs.arc. So since it has $, you can drop to scheme without even exploiting rocketnia's discovery. You just can't do much harm there (at least, you're not supposed to be able to do much harm there, and you just helped me gain a bit of confidence about that).
It does concern me that you're able to see the current directory and version, but I guess as long as you're not able to change anything on the system it might be ok.
(Someone has to try these things out, and it may as well be me, who intends to do no harm, before it's someone else, who might feel mischievous.)
I completely agree. Thank you for trying to break it and reporting your results.
I'm guessing they defined afn because it was frequently useful, then defined rfn because they needed it "for use in macro expansions", and didn't find the refactoring worth their trouble.
Note, by the way, that rfn = "recursive fn" (that's the only reason you would use it instead of fn). But rif is certainly not "recursive if". If you still find it helps you remember it or that it makes more sense, sure, use it, but I would personally use iflet. (Or you could have it defined both ways and use whichever one your brain remembers first.)