I don't think it would resemble the former, if only because you'd want to use uniq calls for functions and macros in the expansion, lest they be redefined between here and the use site.
Destructuring is also built in. It's not clear to me if there's a destructuring use case for (bar 12) in Arc, but I could easily see using it the way Erlang uses its pattern matching, so that (def myfn (foo (bar 12 _)) (do things)) would mean that myfn was only called if the cadr of the second argument was 12. Since '_' in this case means "don't care", I'm not sure there'd be any conflict with '_' as already used in Arc.
I like this idea (and the character you chose: @), but as zunz points out in http://arclanguage.org/item?id=105 , it would be convenient in some cases to have all symbols resolve at the macro definition site, rather than at the use site, except for those specified otherwise (for instance 'it' in the aif definition). If I understand correctly, this is all that hygienic macros require.
Hygiene does have the drawback that you can't bugfix a function used in a macro definition and have it just work, and that might well be more important in a language which is so young. I only mention this because I just did this, and if it hadn't worked I'd have been surprised. But that could be because most of my lisp experience is CL, rather than Scheme.
If there was an "intable" function, you could do it in 11 forms (20 symbols), but your solution requires 13 forms, or 22 symbols. The shorter solution would be less gross, by definition!
If intable could be made to return the actual value in the table, I'd have no reservations, since you could
(aif (intable cache args)
(thevalue it) ; where the fn thevalue does cadr
; or whatever it needs to do
(= (table args) (apply f args)))
Scanning over the entire table twice, once to see if the key is there, and once to actually get the value, is what seemed gross to me about checking for the key first. No doubt that could be optimized by having tables keep a list of keys separately, but that seemed like a heavyweight fix.
I agree that your version is prettier on the surface, though.
Seems like it wouldn't be hard to add defaults to the hash referencing (and string referencing), to allow (++ (table k 0)) which seems much nicer than the CL version, in my opinion.
Edit: Actually, not string and array referencing, since defaults don't matter for that, and there's a much more useful meaning for that: slices.
speaking of hash tables, I remember in ACL you explained why CL has two return values for gethash, to differentiate between the nil meaning "X is stored as nil in my table" and the nil meaning "X is not stored in my table". So why not in Arc?
Because it turns out that in practice it's rarely to never an issue. If you have nil as a val in a hash table, you usually don't care whether that's because it was never set, or explicitly set to nil.
Dear Paul, I can not believe you would make such a statement. Either you're living in a vastly different programming universe than the one I am living in, or you really haven't done that much programming at all. In any case, there are many situations where one stores types of values that may include nil in a hash table, and in most of these there is a very significant difference between 'value is nil' and 'value is not stored'. I understand that Arc isn't trying to all 'enterprisey', but these are fundamental concepts that, I thought, only complete amateurs did not understand. Sincerely, Dr. Drake
You know, I do actually understand the difference between the two cases. What I'm saying is that in my experience hash tables that actually need to contain nil as a value are many times less common than those that don't.
In situations where the values you're storing might be nil, you just enclose all the values in lists.
My goal in Arc is to have elegant solutions for the cases that actually happen, at the expense of elegance in solutions for rare edge cases.