Saying that they're "broken" is a bit extreme... The current design has clear benefits (it's trivial to check the value of a gensym, the implementation code is simpler, etc.) I kind of like how they work, actually- The fact that gensyms thrash the main namespace, the main drawback of this design, is pretty typical arc behavior. I hope gensyms continue to work in the current manner.
By that line of thinking, almost everything in arc is broken, from macros to equality checks (what, no EQL support?) , because arc is always willing to accept a risk of rare bugs/inefficiencies in exchange for simplicity.
Ok, so I exaggerated a little in my initial language. Sorry if I mislead you.
Perhaps the current design is slightly simpler (but not by much, because my changes remove about as much code as they add). And personally, I think it is more unintuitive to think that gensyms are converted to globals and interned into the main arc namespace, than just left alone when assigned in a global context.
But either way, the whole point of gensyms in the first place is to protect from unintended variable capture, right? I don't really see how a design which basically fails to do that can be considered acceptable. Especially when every other Lisp I have ever used ensures somehow that gensyms do not interfere with other variables.
Much of what might be called broken in arc is either just broken until someone gets around to fixing it (like first class macros), or intentionally designed that way and not broken at all (like unhygienic macros). The former will presumably be fixed at some point, and the latter, well, isn't as "broken" as people claim it to be (ask kennytilton for figures on how many macros he has written).
Gensyms are the former, as indicated by the comment above the implementation of ar-gensym. On the other hand, one might argue that gensyms are the latter because unintended variable capture doesn't occur very often. I won't directly argue against this, but consider that CL uses unhygenic macros, yet goes to the trouble of ensuring safe gensyms. (In fact, it can party get away with unhygenic macros because it ensures unique gensyms.)
Also, I think there is a matter of elegance involved in an issue's classification as "to be fixed" or "not really broken". I can't conclusively prove that gensyms increase the elegance of code that uses them, it is just a gut feeling I have. And likewise I feel unhygienic macros decrease elegance (but this may be slightly more arbitrary, since I have never actually written a hygienic macro).
There is always an issue of risk vs. gain, but in this case, I consider the gain to be greater than the risk/cost. Your opinion may differ.
P.S. I think it would settle things pretty decisively if pg told us what he intends to do with gensyms.... pg?
I don't know of a nice way to communicate between threads... I also don't know of a way to do thread-specific storage (mzscheme has functions for both of these that are never lifted to arc)
However, you can relatively painlessly communicate between threads by using the atomic command- Just create a fun that can set/read a global variable based on a flag and have it use atomic to prevent simultaneous reading/writing. You can do a similar thing for thread-local storage (in a bit more complicated way)
There may be a better way to do this though- I'd love to hear what others have to say on this question...
What are these mzscheme functions you are referring to? I was just using a table keyed on thread for threadlocal storage. (Do I need to wrap table access in an atomic-invoke, by the way?)
I wish scheme documentation was more googleable. It's the opposite of javascript, in which you can find 100 ways to do anything, but they are all terribly ugly.
Actually, how did you manage to key on thread? I couldn't figure out how to do this myself, since there isn't a "thread id" or anything that would work as a key...
I would assume (but don't know for sure) that arc tables are thread-safe- I would think you didn't need to worry about atomicity, here...
Thanks for the pointer. Looks like tables are indeed threadsafe. From your link -
"The hash-table-put! procedure is not atomic, but the table is protected by a lock."
As far as threadlocal goes... new-thread returns the thread descriptor and you can use that directly as a hash key.
arc> (= a (table))
#hash()
arc> (= (a (new-thread (fn () (sleep 10)))) 5)
5
arc> a
#hash((#<thread> . 5))
This is inconvenient by itself since in arc you can't access the current thread descriptor without some trickery. It seemed easiest to expose mzscheme's current-thread. I imagine that will have to end up in arc eventually.