What if that value is nil? That makes for a nasty corner case.
oops, yes, you're right, good point
Why use microbenchmarks
using parser.arc to index tokens from arc.arc is the benchmark I use most often for tuning rainbow performance. I wanted to present the issue with as few extraneous details as possible.
Micro benchmarks can be misleading sometimes. Most of the time I get different timings for the same microbenchmark when I eval it a few times so it's really difficult to see if they really do their job when the timings are too close unless some full blown benchmark is performed on some real data.
I understand Rainbow can do graphics stuff pretty well.
rainbow comes with tetris, minesweeper and and an arc editor that use the swing library from java so there is lots of sample code to work from. If you've used swing before, you should find it pretty easy from rainbow, and I've tried to design the arc interface so it looks as arc-ish and un-java-ish as possible.
But please bear in mind rntz's observation about the long-term goals of the 100-year language; I'm pretty sure java integration is way off the bottom of the list :)
If you need help to get swing up and running from rainbow, let me know.
On top of that, while we're on the topic, I don't know what happens if you jump into another continuation in the following circumstances:
1. you're inside atomic-invoke, call-w/stdout, call-w/stdin, or anything that creates context that needs to be undone on the way out. The problem is that a continuation from in here can be exited multiple times although it was entered only once.
2. similarly, you're inside protect, (equivalent to "finally" in java) - is the "after"-fn called, and if so, only once or for each re-entered continuation?
3. the continuation you jump into was originally running on another thread.
I should write tests to figure out what happens in all these cases, but if anybody knows the answers I can live with being lazy :)
Take a look at anarki, a community-maintained fork of arc with a bunch of enhancements (I don't know if there's a simple list of changes anywhere) ... and rainbow (an arc interpreter in java; mostly the same as arc except for access to java libs; dunno if that counts as "enhancing usability" :))
I just add all my code in subdirectories of my arc installation. For now, arc assumes that the current working directory is the directory containing arc.arc. It's not difficult to put together something that uses a path-like environment variable (eg "ARC_PATH") for searching for arc files (I believe anarki includes something like this) - but you still need to start in the arc directory, even though you can reference arc files stored at a different location.
Official Arc exists to support one app: news.arc (it's running this forum and hacker news). If you were to write a language to support a single app, you wouldn't need fluff like being able to run from a different working directory. [or, as palsecam put it more eloquently, Lisps in general just consider the OS is crap, and they are too "pure" to talk with it.]
If arc becomes widespread, either this will change, or popular ideas about what a language should do will. History isn't in arc's favour here :)
> Official Arc exists to support one app: news.arc
To erikb: yes, don't forget this important point. Sometimes Arc failed on basic stuff, because news.arc/pg's stuff doesn't need it (yet). If you're not going to accept this fact, you'd better not use Arc (or you can do even better: actually improve it to suit your needs :-)).
There is a danger in designing a language based on one's own experience of programming. But it seems more dangerous to put stuff in that you've never needed because it's thought to be a good idea.
which is wise.
> If you were to write a language to support a single app, you wouldn't need fluff like being able to run from a different working directory. [or, as palsecam put it more eloquently, Lisps in general just consider the OS is crap, and they are too "pure" to talk with it.]
I don't think this is the same idea here.
"Mine" is: you are crazy to create a general-purpose language and completely ignore the rest and the world, i.e the OS and the other programs (not written in your language). (In Common Lisp defense, it was designed at a time the OSes were more diverse & their future uncertain, etc.).
And Arc, as we said, is not so designed to be of general purpose.
And I don't think "if you were to write a language to support a single app, you wouldn't need fluff like being able to run from a different working directory" is totally correct.
You can design a language for a single purpose that would include deep cooperation with the OS. E.g: purpose is to write a language to manage firewalling rules.
*Arc is still a work in progress. [...] it's
still in the semi-finished state most software
is, full of hacks and note-to-self comments about
fixing them.*
It's good to know that the principle of invoking arc as a script-runner isn't excluded.
I confess, this is a seriously contrived example: nested strings need to be escaped -
arc> "database/@(+ user "_file.arc")"
Error: "UNKNOWN::0: read: expected a `)'"
arc> Error: "reference to undefined identifier: __file"
arc> ")"
arc> "database/@(+ user \"_file.arc\")"
"database/conanite_file.arc"
arc>
This is because arc relies on the scheme reader, which doesn't know anything about atstrings; the arc compiler later compiles "a @b c" into (string "a " b " c"). "\@" isn't a valid string escape sequence in scheme, so arc has to use "@@" instead.
I know this is more than you asked, but I just had to vent :)
[forum hint] Indent code samples with two spaces and delimit with blank lines to get it to format properly
whoops, I forgot about the formatting and now it's too late to edit.
Maybe my original problem wasn't important then. Also it seems like your first problem means there should be more parens for disambiguation. "x/@(y)/z" or "x/@((funcall))/z" etc. "add more parens" always seems too easy to be right, though :)
Macros are like compiler hooks, they are executed at compile time, not run-time. When you run code at the REPL, run-time is immediately after compile-time, so the difference is not obvious. Try this:
arc> (mac amac () (prn "amac is reached"))
#3(tagged mac #<procedure: amac>)
arc> (def maybe-amac () (if t 1 (amac)))
amac is reached
#<procedure: maybe-amac>
arc> (maybe-amac)
1
No "amac is reached" when you execute maybe-amac ...
I don't know how CL works internally, maybe it suppresses std-out from macros?
For CL, I don't know exactly how it works, but I suppose 'if is treated as a special form (or expand to a call to 'cond which is a special form, or something) which is in some way "higher in priority" than macro expanding.
I am really really not sure of that, but if I remember well my teachings, this is a part of the reasons why 'if or 'cond is a special form and not just a normal macro.
> maybe it suppresses std-out from macros?
Now that would be crappy :-D! It is not just a problem of output, try the sleep macro example:
arc> (mac expect-arg-m (arg) arg)
#3(tagged mac #<procedure: expect-arg-m>)
arc> (expect-arg-m)
Error: "procedure expect-arg-m: expects 1 argument, given 0" <-- OK, this is normal
arc> (if t 1 (expect-arg-m))
Error: "procedure expect-arg-mac: expects 1 argument, given 0" <-- hmm, parse the false clause...
cl> (defmacro expect-arg-m (arg) arg)
cl> (expect-arg-m)
error while parsing arguments to DEFMACRO EXPECT-ARG-MAC:
invalid number of element <-- OK, normal
cl> (if t 1 (expect-arg-m))
1 <-- didn't bother to parse the false clause