Arc Forumnew | comments | leaders | submitlogin
2 points by aw 5103 days ago | link | parent

Having an open implementation has many advantages:

- if you wanted to serialize closures, you could easily implement a serialization strategy simply by inspecting the closure's environment yourself.

- writing a debugging or tracing facility becomes so simple that you could just throw together an ad-hoc solution to a particular need whenever you wanted, instead of having to rely on the debugging facilities offered (or not) by the runtime.

- for a programmer who is new to closures, having everything be completely transparent makes it easy to see what's going on.

One thought I've had is that it could be useful to write an Arc interpreter in Arc. It would be slow of course... but the highest level functions in a program (like the ones that we typically want to serialize to persist closures) often don't need to be fast... as long as the operations that they call (such as in particular anything being done in a loop) are themselves fast.

This would give us four levels of implementation:

- Arc interpreter

- Arc compiler

- Racket

- C

Each higher level is more expressive but slower than the level below it. Thus you can write something at a higher level first because that will be the fastest for you (it will take you less time to write the program), but then if it turns out to be too slow, you can rewrite it at a lower level at the cost of doing more work.

Your note [3] deserves an entire comment by itself, but I'm out of time now so I'll reply later :)



1 point by Pauan 5103 days ago | link

Excellent notes. Those are definitely great reasons to make functions open, rather than opaque blobs. In fact, I see only two downsides to it:

1) Slowness. Then again, Arc's goal isn't speed either. As you mentioned, it should be possible to rewrite the slow bits in a lower layer if needed.

2) Lack of information hiding. This is more serious than point 1, but, I can provide a different mechanism for information hiding. The downside of having a different mechanism is that it requires learning a new mechanism... and I love that closures can be used for information hiding. It's just so simple and axiomatic, you know?

---

"One thought I've had is that it could be useful to write an Arc interpreter in Arc."

I've been mulling that over too, ever since your earlier comment[1], but... I don't really like the Racket runtime (the implementation, not the language). For instance, trying to make Unix shell scripting work with Racket is a big pain, but it's incredibly easy in Python.

Of course, I don't really like Racket the language either. :P Too big and bloated for my tastes. Why do you think I like Arc to begin with? On the other hand, programming in Racket would probably be preferable to programming in Python, if I had to choose between the two.

Oh yeah, and Python seems to be a lot more popular than Racket... so chances are, your users will have Python installed, but not Racket. Proooobably not a big deal, since we're a pretty small group, but still an advantage for Python.

---

"Each higher level is more expressive but slower than the level below it. Thus you can write something at a higher level first because that will be the fastest for you (it will take you less time to write the program), but then if it turns out to be too slow, you can rewrite it at a lower level at the cost of doing more work."

Yes! And don't forget: profile, profile, profile first. I think that's the best way to make good clean code that is also fast. Honestly, though, I rarely need to actually optimize my JavaScript code, because it's usually plenty fast as-is. Chrome's V8 engine is amazingly fast, especially given how dynamic JavaScript is.

---

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

-----

1 point by aw 5103 days ago | link

trying to make Unix shell scripting work with Racket is a big pain

In what way? Running a Racket program as a shell script, or calling shell scripts from Racket? (I haven't found either particularly difficult... though I can easily imagine that the process might be smoother and better documented in Python).

with respect to Racket vs. Python, an advantage of Arc's axiomatic approach is that it makes it really easy to implement Arc on top of different platforms. So I can use a Python runtime for things that it is it good at, and a Racket runtime for things that it is good for.

-----

1 point by Pauan 5103 days ago | link

Writing an Arc program that works as a shell script. In other words, I want to slap a #!/path/to/arc shebang into a text file, and then call it with ./foo.arc and have it work like an executable.

This works in Anarki (at least, I think so, I haven't tried it), because they made an arc.sh file, and used some kludgy stuff to make it work[1], but in Python it Just Works(tm), no fiddling needed. That's actually true for Arubic[2] as well, because it's written in Python and I designed it that way. You can just use #!/path/to/arubic and it'll Just Work(tm).

I'm probably overly-criticizing Racket for that because I ended up partially implementing arc.sh by myself, then found a forum post that gave a better implementation, swiped that, then modified it. I doubt I'd have cared as much if arc.sh had been included with Arc 3.1 (and worked good).

It's not as big of a deal now that Anarki has arc.sh, but it's just one of those rough-around-the-edges areas. Python also makes it easy to parse command line switches, with the optparse module, though that could be implemented as a library in Arc, so it's not really fair to criticize Racket for that. :P

I'm curious, though, how would you write a Racket program that worked as a shell script?

---

"with respect to Racket vs. Python, an advantage of Arc's axiomatic approach is that it makes it really easy to implement Arc on top of different platforms."

Not in my experience. Arc actually has a lot of primitives[3], not to mention the whole thread/continuations/TCO thing. Implementing a simple toy Arc interpreter? Piece of cake. Making it actually good? A lot harder. That's another reason I'm trying to shove as much into Arc as I can... the more stuff in Arc, the less stuff you need to write in the interpreter layer.

Actually, a lot of my time has been spent debugging small bugs... I've had to wade through a lot of tiny bugs to get Arubic working properly in all sorts of weird edge-cases. Unit tests help a lot with that.

---

* [1]: Actually, I just took a look at Anarki's arc.sh and it looks pretty clean. I'm not sure if it behaves correctly, but I don't feel like testing it to see.

* [2]: I'm renaming py-arc to Arubic, because I like that name a lot. This also gives me some more flexibility... I'm no longer tied to Python. I could implement Arubic in Arc, or Ruby, or another language.

* [3]: Compared to most other popular languages, Arc has very few primitives, but it still has a lot more than I'd like. One thing I did like, though, is that it was incredibly easy to write a tokenizer/parser for Arc, because it has such a regular syntax, due to being a Lisp.

When I implemented a top-down operator precedence parser (in JavaScript) to parse a custom language, it ended up being a lot harder, because the custom language uses syntax, and not particularly regular syntax either.

-----

2 points by aw 5103 days ago | link

Writing an Arc program that works as a shell script.

Ah, I don't think this is a Racket problem. Racket has good information on how to run a Racket program as a shell script: http://docs.racket-lang.org/guide/scripts.html

By the way, Racket also has a decent command line argument parser: http://docs.racket-lang.org/reference/Command-Line_Parsing.h...

Of course, to say that Arc doesn't make this easy enough is certainly a valid criticism. (But I don't think we can blame Racket for that).

not to mention the whole thread/continuations/TCO thing

Your point is well taken. The advantage of an axiomatic approach is once you have them implemented, the rest of the system will run on top of them... but the powerful axioms may be hard to implement.

-----

1 point by Pauan 5102 days ago | link

"Ah, I don't think this is a Racket problem."

Fair enough. I had somewhat assumed that the problem was Racket, because Arubic handles it just fine. My mistake.

That actually looks like a pretty good command line parser. Thanks for the links!

P.S. Once ar gets into a somewhat more complete state, you may want to consider making shell scripts work good with it. For instance, if I'm in the directory /foo and I run a script that's in /usr/bin and the script uses (load "lib/bar.arc"), I would expect it to load /usr/bin/lib/bar.arc, not /foo/lib/bar.arc.

I made this work in my copy of pgArc, but it'd be nice to have it be more standardized. Obviously it should be possible to load relative to the current directory as well, if your script wants to.

Mind if I go in and start hacking on ar? :P If I decide to make an Arc compiler in Arc, I'd probably base it on ar.

---

"The advantage of an axiomatic approach is once you have them implemented, the rest of the system will run on top of them... but the powerful axioms may be hard to implement."

That is true. I do like the axiomatic approach, but I think Arc can improve and become even more axiomatic, which is one of my goals with Arubic.

-----

1 point by aw 5102 days ago | link

Mind if I go in and start hacking on ar

Please do! (that's why I put it on github :)

By the way, the hackinator (https://github.com/awwx/hack) does generate an Arc program that can be run from the shell from any directory (for example https://github.com/awwx/hackbin/blob/master/hack works this way). I just haven't gotten around to getting it into ar yet.

Oh, and just so you know the above example produced by the hackinator incorrectly uses aload to load Arc files after arc.arc has been loaded instead of using Arc's load; this a known issue I've listed in the to-do list in the README.

-----