Arc Forumnew | comments | leaders | submit | evanrmurphy's commentslogin
1 point by evanrmurphy 5511 days ago | link | parent | on: Try Arc

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!

Thanks for that.

-----

3 points by evanrmurphy 5511 days ago | link | parent | on: Care to share your arc project?

akkartik's http://readwarp.com/ is an impressive webapp written in Arc.

http://tryarc.org/ is what I've been working on lately.

-----

1 point by evanrmurphy 5511 days ago | link | parent | on: More documentation

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]

[1] http://arclanguage.org/item?id=11738

-----

1 point by prestonbriggs 5510 days ago | link

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.

Preston

-----

1 point by evanrmurphy 5511 days ago | link | parent | on: Named loop or continue keyword?

Much more elegant and less buggy than my attempt. Nice work.

-----

2 points by evanrmurphy 5512 days ago | link | parent | on: Named loop or continue keyword?

One way to do it would be with macro-generating macros. Take loop for example. arc.arc defines loop as follows:

  (mac loop (start test update . body)
    (w/uniq (gfn gparm)
      `(do ,start
           ((rfn ,gfn (,gparm) 
              (if ,gparm
                  (do ,@body ,update (,gfn ,test))))
            ,test))))
Here's how you could write aloop, which is just like loop except that it grants access to itself through the generated macro continue:

  (mac aloop (start test update . body)
    (w/uniq (gfn gparm)
      (mac continue ()
        `(do ,update (,gfn ,test)))
      `(do ,start
           ((rfn ,gfn (,gparm) 
              (if ,gparm
                  (do ,@body (continue))))
            ,test))))
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.

-----

2 points by rocketnia 5512 days ago | link

Defining macros during macro-expansion strikes me as being a bit error-prone, and here's one concern:

  (afor i 0 10
    (afor j 0 10
      ...
      (continue)
      ...
      )
    ...
    (continue)
    ...
    )
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:

  (mac aloop (start test update . body)
    (w/uniq (gfn gparm)
      `(do ,start
           ((rfn ,gfn (,gparm) 
              (if ,gparm
                  (let continue (fn () ,update (,gfn ,test))
                    ,@body
                    (do.continue))))
            ,test))))

-----

1 point by evanrmurphy 5511 days ago | link

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.

-----

2 points by garply 5512 days ago | link

Your code works because nothing follows your continue. This does not work as I would want it to:

(afor i 0 3 (when (odd i) (continue)) (prn i)) goes to:

0

2

4

5

nil

-----

1 point by evanrmurphy 5514 days ago | link | parent | on: Try Arc

Here's a question:

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.

[1] http://dabuttonfactory.com:8080/

[2] http://jonathan.tang.name/files/arclite/index.html

[3] http://arclanguage.org/item?id=10604

[4] http://www.arclanguage.org/item?id=10401

-----

2 points by evanrmurphy 5514 days ago | link | parent | on: Try Arc

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.

-----

3 points by waterhouse 5514 days ago | link

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:

  (def eval-w/stdout (expr)
    (tostring:let result nil
      (let output (tostring (= result (eval expr)))
        (unless (empty output)
          (prn "output: " output))
        (write result))))
In action: (for some reason, when I copied this, it had a bunch of extra spaces)

  arc> (eval-w/stdout '(time (reduce + (n-of 1000 rand.100))))
  output: time: 339 msec.
  
  49840
[0]http://arclanguage.org/item?id=11838

-----

2 points by evanrmurphy 5513 days ago | link

Try Arc saw two updates today:

1. stdout now displays properly.

  arc> (pr "hello")
  hello"hello"
@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):

   (def eval-w/stdout (expr)
  -  (tostring:let result nil
  -    (let output (tostring (= result (eval expr)))
  +  (tostring:withs (result nil
  +                   output (tostring (= result (eval expr))))
         (unless (empty output)
           (prn "output: " output))
  -      (write result))))
  +      (write result)))
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.

-----

2 points by evanrmurphy 5512 days ago | link

I added support for multi-line entry:

  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.

-----

2 points by evanrmurphy 5514 days ago | link

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.

-----

1 point by evanrmurphy 5521 days ago | link | parent | on: rif

Good catch.

-----

1 point by evanrmurphy 5523 days ago | link | parent | on: Dot notation and doc in general

Do you know about http://af.searchyc.com/ for searching the forum? Also useful is Ken Shirriff's documentation at http://files.arcfn.com/doc/.

http://www.paulgraham.com/arcll1.html has a nice high-level discussion of syntax in Arc.

do you go directly to the source file to view how the dot is implemented?

This is certainly encouraged too.

-----

1 point by evanrmurphy 5523 days ago | link | parent | on: rif

Relatedly, why not define afn in terms of rfn?

  (mac afn (parms . body)
    `(rfn self ,parms ,@body))
Am I missing something here?

-----

2 points by waterhouse 5522 days ago | link

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.)

-----

1 point by evanrmurphy 5522 days ago | link

Somehow it had escaped me that the r stood for "recursive". I thought maybe it stood for "reference", in which case rif would be a sensible name.

I think you're right this definition could just override iflet. It would be an obscure case where you wouldn't want var binding to the other exprs.

-----

More