Arc Forumnew | comments | leaders | submitlogin
ASK: What are the advantages of arc over racket?
3 points by kinnard 2971 days ago | 11 comments
http://stackoverflow.com/questions/8555440/the-advantage-of-arc-over-racket


3 points by akkartik 2971 days ago | link

For me the big reason is differences in the way macros are ordered. Racket is a scheme so its macros are hygienic and require a little bit greater ceremony in creating. More seriously, they have phase ordering, which creates constraints about what code you can call from within macros: https://docs.racket-lang.org/guide/phases.html

Arc is more like Common Lisp in that you can call whatever you want while expanding a macro, and if you make a mistake you might end up with an infinite regress of macroexpansion or something like that. Its macros are not hygienic which again creates room for certain kinds of bugs, but some of us here tend to think of those as learning experiences ^_^ whose benefits outweigh their pain.

Another minor difference is that Arc is a lisp-1 like Scheme and unlike Common Lisp.

-----

2 points by kinnard 2970 days ago | link

I think I'm just beginning to understand some of the benefits/risks of hygienic macros, but I'm not quite there.

-----

2 points by kinnard 2970 days ago | link

Can non-hygienic macros be easily made hygienic in arc?

-----

3 points by rocketnia 2968 days ago | link

I think there is one way to consider Arc to be a language with good hygiene: We can program so that if we ever use a name as a global variable, we never use it as a local variable, and vice versa. As long as an Arc problem follows this rule and the usual (w/uniq ...) idiom, it won't encounter hygiene issues.

Paul Graham has this to say about hygiene in the tutorial:

  Some people worry unduly about this kind of bug.  It caused the
  Scheme committee to adopt a plan for "hygienic" macros that was
  probably a mistake.  It seems to me that the solution is not to
  encourage the noob illusion that macro calls are function calls.
  People writing macros need to remember that macros live in the land
  of names.  Naturally in the land of names you have to worry about
  using the wrong names, just as in the land of values you have to
  remember not to use the wrong values-- for example, not to use zero
  as a divisor.
However, he's only careful about one direction of variable capture. Here's one example from the tutorial where he doesn't mind capturing the names let, repeat, push, and rev:

  (mac n-of (n expr)
    (w/uniq ga
      `(let ,ga nil
         (repeat ,n (push ,expr ,ga))
         (rev ,ga))))
I think he gets away with this because he's following that rule I mentioned, keeping a careful separation between the names of locals and globals.

It seems we don't particularly follow that rule here on the Arc Forum. For instance, a few of us have agreed that a certain behavior in Arc 3.1 is a bug: When we make a function call to a local variable, we don't want a global macro of the same name to take effect, which is what happens in Arc 3.1. If we were keeping locals and globals separate, we wouldn't even encounter this problem.

Which means that if we want to write macros that are hygienic, we can't write them in quite the way we see in arc.arc or the tutorial. If we're dedicated to hygiene, we might even want to rewrite arc.arc to fix its hygiene issues... but that's practically the whole language, so it effectively starts to be a new language project. The Anarki arc2.hygiene branch, Penknife, ar, Semi-Arc, and Nulan are several examples of Arc-based or Arc-inspired projects that pursued some kind of hygiene.

If we don't mind the lack of hygiene in arc.arc but only care about proper hygiene for our own new macros, it is possible to be diligent about hygiene in plain Arc 3.1 or Anarki:

  (mac n-of (n expr)
    (w/uniq ga
      (rep.let ga nil
         (rep.repeat n (rep.push expr ga))
         `(',rev ,ga))))
Coding this way looks a little arcane and loses some of Arc's brevity, but one of the techniques here is to embed a the rev function into the syntax as a first-class value. By putting most of the macro implementation into an embedded function, it can become rather familiar-looking again:

  (mac n-of (n expr)
    `( ',(fn (n expr)
             (let a nil
               (repeat n (push (expr) a))
               rev.a))
       ,n
       (fn () ,expr)))
Here's a macro that makes this even more convenient:

  (mac qq-with args
    (let (body . rev-bindings) rev.args
      (let (vars vals) (apply map list (pair rev.rev-bindings))
        `(',list `',(fn ,vars ,body) ,@vals))))
  
  (mac n-of (n expr)
    (qq-with n n expr `(fn () ,expr)
      (let a nil
        (repeat n (push (expr) a))
        rev.a)))
I think if I programmed much in Arc again, I'd start by defining that macro or something like it. :)

As it is, right now I'm just settling into a macro system I designed. I don't have convenient gensym side effects like Arc does, and I want the generated code to be serializable (not containing opaque first-class functions), so my options are limited. I still can and do implement macros, but the implementation of each macro is pretty verbose.

-----

1 point by kinnard 2958 days ago | link

I'm still learning lisp and haven't fully wrapped my head around macros. So the hygienic vs unhygienic debate is still more or less opaque to me :D

-----

5 points by Pauan 2964 days ago | link

With the current implementation of Arc, it is possible but rather tricky to write hygienic macros.

However, there is a very simple change that can be made to the Arc compiler which would make hygienic macros easy to write.

The Arc compiler would have a big hash table which maps from global symbols to gensyms.

Whenever you define a global variable, it will create a new gensym and store it in the hash table.

When using the quasiquote syntax, it will lookup the variable in the hash table and will use the gensym rather than the symbol.

As an example, if you have this Arc program:

  (= foo 1)

  (mac bar ()
    `(+ foo 2))
The Arc compiler would expand it to this code instead:

  (= #<foo:1> 1)

  (mac #<bar:1> ()
    `(#<+:1> #<foo:1> 2))
In this case, #<foo:1>, #<+:1>, and #<bar:1> are gensyms, rather than ordinary symbols.

Now the macro bar will always expand to the correct global variable foo, and therefore it is 100% hygienic.

If you want to intentionally break hygiene, you can simply do this:

  (mac bar ()
    `(+ ,'foo 2))
The above code uses "," to insert the symbol "foo", rather than the gensym for foo.

This change is very easy to make in the Arc compiler, and it only requires a few minor changes to the language.

-----

1 point by akkartik 2969 days ago | link

No, they're conflicting philosophies.

-----

2 points by highCs 2970 days ago | link

Arc is designed for good programmers. It gives you raw power. Like you could kill yourself with it. Arc is to programming language what unix is to OSes. It doesn't try to protect yourself from doing bad things but gives you the maximum power instead.

The advantages of the language are numerous: raw macro, short names, incredible library, awesome operators, right choice of data structures, etc.

In short, it's more beautiful and agile than racket.

-----

3 points by akkartik 2969 days ago | link

Hi highCs, this is off-topic but I was thinking about you just yesterday. I updated your bugfix at http://arclanguage.com/item?id=19310. Could you pull anarki and let me know if it's still working for you on Windows? Many thanks.

We were also wondering what your setup looks like. Are you using cygwin when you run Arc on Windows?

-----

2 points by highCs 2968 days ago | link

Hi akkartik, thanks for the update. I'm not using cygwin, but raw racket for windows, sublime and terminals. But I've not run Arc since a while - december or so. Actually, I growing more and more interested by poker. It's kind of the perfect answer to the frustration I got in software - mostly due to my struggle to find a job with great programmers and also my struggle to find great co-hackers. In poker, I win money when the others are wrong; guess how I like that this days...

Programming is my life. I like to think I'm a master of it. But I'm completely alone. Also I hate my jobs, I hate big companies, I hate bullshit, I hate TDD, I hate code reviews, I hate estimations; it's a pain man.

Poker, while definitely not as deep as software, is the exact opposite. They do TDD? I take money. They do code reviews? I take money. bullshit? a fountain of money...

But there is Arc. The most beautiful language I've ever used. I could build so much with it. Wow it could be so awesome. But, let's be honest, it's now or never. Btw, I think I have an idea to fix email. What's missing is a delivery date (of the task / answer / content) set by the sender or the receiver, which would allow to sort emails. Anyway, I'm throwing a bottle in the ocean. If you have a project you want to do using arc (or another language that would fit the task better), let me know.

-----

3 points by akkartik 2968 days ago | link

I was quite addicted to poker (no-limit hold 'em) for a couple of years (2005-2008) until it became hard to play online in the US. Now I just play with play money on some mobile app every few months :) It's not true that when people play badly they always lose money. It took me a while to realize that my compass of how well I was playing had to come from within. Otherwise the worst thing that could happen to me was to play badly and win a hand. I'd then be giving away money for a long time, going on tilt, etc. But yeah you're right that in the long run the better player wins, particularly in cash games. Tournaments seem like more of a lottery (maybe I'm just not very good).

I'm constantly looking for people to hack with as well. Some ideas:

a) We could work on anarki. For example, try out the latest version sometime when you have time and let me know if mktemp broke again on Windows. Help kinnard and me expand the install instructions for Anarki to Windows. Neither of us knows how to run Arc there, so this would be very valuable. These small-ish ideas might be the start of a larger project.

b) Other than that I spend a lot of time these days working on an Arc-inspired project that looks nothing like lisp: http://github.com/akkartik/mu. My background: http://arclanguage.org/item?id=17597. Problem statement: http://akkartik.name/about. Writeup on the current state of the solution: http://akkartik.name/post/mu. Let me know how far down that list you were moved to read :)

-----