As a first cut, I would scan through to find the tempsets, take out the variables, and then expand to a let or with block now that you know their names.
Ah. Right. (And I even worried about similar things when writing make-br-fn...). Well, it would work in simple cases, but let/with are looking like better ideas.
Actually, if we add another primitive (with $ or xdef) which works using mzscheme's namespace-undefine-value!, we could have tempset maintain a global list of tempset variables, and cleartemps go through and undefine them.
It's intentional, although it may violate your expectations. In Arc, the empty list is denoted nil, but can also be written '() and (). (You can check this by typing (is nil '()) and (is nil ()) into the REPL; both will return t for true.) Reversing the empty list should (naturally) result in the empty list, so it seems like you were expecting (rev '()) --> '(). However, even though you input the empty list in the Scheme manner, it was output as nil, in the CL and Arc manner. So if you were expecting the reversal of the empty list to be the empty list, it does what you would expect. If you were expecting '() to be the preferred syntax for the empty list, it doesn't.
My apologies, I was foolish in that I did not consider that '() evals to nil prior to the evaluation of rev. (rev nil) --> nil - this now makes more sense.
A couple more observations on this point:
(list) --> ()
((fn nil 'a)) --> a
(type (list)) --> sym
Is there any valid use of the '() syntax other than zero parameter declarations in functions? It would appear that in arc, one should embrace nil.
Personally, I use '() when I mean "the empty list" and nil when I mean either "the false boolean" or "no value yet". It is just a matter of readability, since they're both as long to type ;)
Simply () works too, and is more than 33% shorter ;)
The following shows four ways to express the empty list, and proves that they mean the same in Arc. What's a little peculiar, however, is that one gets printed differently;
In Arc, they are equivalent, so it doesn't really matter. I think pg would like us all to use nil everywhere, but (obviously) that's not being enforced. Nevertheless, based on arc.arc, I think "embracing nil" is probably the best idea.
Indeed, you are correct. Ruby[1] doesn't have "native" lists, it has native arrays. Observe:
irb(main):001:0> [].class
=> Array
There is no Ruby cons, nor Ruby car, nor Ruby cdr. There is y.unshift x or [x] + y for cons (though these cannot constructed "dotted Arrays"), arr[0] or arr.first for car, and arr[1..-1] for cdr, but they denote no structure-sharing. However, flattening would merely be arr.flatten—of course it doesn't work by cdr-juggling, but that's because there are no cdrs.
I'm not really sure what the grandparent post means: "lists without the car and cdr part"? That sounds to me like a very good definition of an... array![2]
Also, that set of duck puns/references was fantastic. Well done.
[1]: Which is a very nice language.
[2]: Well, without the O(1) access time, but I digress.
I can take no credit -- they just popped out of my keyboard. There must be some poorly understood connection between algorithms, data structures, and waterfowl.
Actually, they (the infamous "they") did a study, and apparently, ducks are the funniest animal. Take that with as large a grain of salt as you think is appropriate :)
One use of dotted lists is the degenerate case of a dotted pair: (cons 'a 'b). Slightly nicer for representing a pair than a complete list (though less so with the lst.n syntax). But it seems to me like they're important to have because of what a list is. A list has a car and a cdr: (car (cons x y)) -> x, and (cdr (cons x y)) -> y. If you remove dotted lists, you break that valuable identity. Would (cons 'x 'y) be an error, or implicitly create the list '(x y)? Either way, there's inconsistency that will come back to bite you.
It's just a convention: "w/" is a standard abbreviation for "with," so it reads nicely. (The * ending is also a convention.) Arc does have some syntax, though (e.g. f1:f2 or x.y); I posted a list of all of the syntax at http://arclanguage.org/item?id=4012 , if you're curious.
I haven't done any I/O yet, but it looks like you want w/infile and w/outfile.
Another way to run a program from a file is to use arc.sh from the Anarki. This pretty much does what you said (mzscheme -m -f as.scm < myprogram.arc), but is packaged up in a script.
As for searching, the best way is probably to do a Google search for "my query site:arclanguage.org".
>As for searching, the best way is probably to do a Google search for "my query site:arclanguage.org".
True, and I'd figured that out, but neglected to mention it because I still couldn't find what I wanted.
Anyways, search is an important feature these days that every site with some dynamic content should have. You can't expect google's indexer to keep up with all your changes, and a forum with any sort of scale should encourage its users to search for duplicate topics before starting their own lest redundancies abound. I'd like to see an arc solution for searching on these posts.
That's what Arc's symbols are for. Generally speaking, you should be keying your tables with symbols for exactly that reason: every 'a is at the same place in memory, but every "a" is not (which allows mutable strings).
You had me worried, but I'm pretty sure there's absolutely no problem with using strings as the keys for tables.
The MzScheme documentation says: make-hash-table ... 'equal -- creates a hash table that compares keys using equal? instead of eq? (needed, for example, when using strings as keys).
Checking ac.scm, sure enough:
(xdef 'table (lambda () (make-hash-table 'equal))
Likewise, the "is" operation in Arc uses MzScheme's string=? . (That's a statement, not a question :-) So string comparison works, although in O(n) time.
Net net: strings are okay for comparison and table keys in Arc.
I wasn't saying that they weren't usable, just that they were, in fact, slower; that's what you observed. Symbol comparison is O(1) time, whereas string comparison is O(n) time. That's all.
I would rather have immutable strings + unification of symbols and strings.
- Any string could have an associated value, like symbols today.
- "foo", 'foo and (quote foo) would be the same object (you would allow Lisp-style prepend-quoting of non-whitespace strings for convenience).
- foo, (unquote "foo") or (unquote 'foo) would then be used to evaluate, so even non-whitespace strings like "bar baz" could act as symbols (but with less convenience, of course, since you would have to use the unquote form to get them evaluated).
- Since such a unified string/symbol would also act as a perfectly good key/value pair, a simple list of such strings will in effect act as a string-keyed hashtable (since duplicate strings in the list would be the same immutable key), and can be used wherever you need symbol tables (e.g. for lexical environments). In fact, string-keyed hash tables would be a subtype of any-sort-of-key hashtables, and probably used much more.
. And by (unquote "foo"), do you mean (eval "foo")? Or do you mean `,"foo"? The latter makes more sense here.
At any rate, I'm not convinced that this is actually a benefit. Strings and symbols are logically distinct things. Strings are used when you want to know what they say, symbols when you want to know what they are. Unifying them doesn't seem to add anything, and you lose mutability (which, though unfunctional, can be quite useful).
> Strings and symbols are logically distinct things. Strings are used when you want to know what they say, symbols when you want to know what they are.
Fine. But this breaks down anyway when you force people to use (immutable) symbols instead of strings for efficient allocation. When using symbols as keys in hashtables, you do not "want to know what they are", you "want to know what they say".
And unification would possibly have good consequences for simplifying macros and code-as-data (especially if characters are also just strings of length 1). Most code fragments would then literally be strings (most notable exceptions would be numeric literals, list literals and the like).
Actually, in a hash table, I usually don't care what the key says, any more than I care about the name of the variable used to store an integer. I care about it for code readability, but I'm usually not concerned about getting a rogue key (where I do care what it says). In that case, I would either use string keys or (coerce input 'sym).
I'm not convinced that characters being strings of length one is a good idea... it seems like the "character" is actually a useful concept. But I don't have a huge opinion about this.
Code fragments would still be lists, actually: most code involves at least one function application, and that's a list structure. Only the degenerate case of 'var would be a string.
> Actually, in a hash table, I usually don't care what the key says, any more than I care about the name of the variable used to store an integer.
That's fine again, but my point is just that by using symbols as keys in hashtables, you never care about the value part of that symbol (you just need an immutable key); you're not using the symbol "as intended", for value storage.
> most code involves at least one function application, and that's a list structure.
Yep. But in the case where that function application does not contain another function application (or list literal) in any of its argument positions, we would, with my proposal, be talking about a list of strings, which could then again be seen as a string-keyed hash table...
Symbols are not "intended" for value storage, symbols happen to be used for value storage. Symbols have exactly the same properties as, say, named constants in C, and thus fit in the same niche. They also have the properties of variable names, and so fit in that niche too. Symbols are a generally useful datatype, and they are no more intended for just "value storage" than cons cells are intended for just list construction.
A list of strings is still a list, which is not what you said; right now, it's a list of symbols, and I don't see the benefit of a list of strings over a list of symbols.
Really, I think most people are confused by the boundary between interface and implementation.
It's possible to have a mutable string interface built on an immutable string implementation. Just add indirection! We can get the best of both worlds: immutability of actual strings optimizes comparison of strings, while the pseudo-mutable strings allow you to pass data across functions by a method other than returning a value (i.e. mutating the string).
That's a good point. However, it leaves open the question of what "a new string" creates. One can build either one on top of something else (e.g. immutable strings on top of symbols [though one could argue that that's what symbols are, I suppose]), so the real question (it seems to me) is what the default should be.
This is where "code is spec" breaks down, again ^^; \/
I suppose if the user uses symbol syntax, it's an immutable string, while if the user uses "string syntax", it's a mutable string. Interface, anyone? ^^
edit: typical lisps implement symbols as references to mutable strings; some newer ones implement mutable strings as references to immutable strings, with symbols referring also to immutable strings.
This isn't so much code is spec, though: Arc only has mutable strings and symbols. You could consider symbols immutable strings, but they exist to fill a different niche.[1] If mutable and immutable strings were created, then the code-spec would have to deal with this; I think it would be capable of doing so.
I'm not so concerned with how Lisps represent symbols and (mutable) strings as long as (1) my strings can be modified, and (2) comparing symbols takes constant time. If it's the Lisp interpreter protecting the string-representing-the-symbol, so be it; that doesn't affect me as a Lisp programmer.
[1]: Although if I recall, Ruby 2.0 will make its Symbols "frozen" (immutabilified) Strings, thus allowing things like regex matching on Symbols. This might be an interesting approach...
I'm on OS X using TextMate, which is fantastic (though €40 / US$50). I quickly modified the Scheme language bundle into an Arc language bundle--it's not perfect, but it's OK. For the REPL, I'm using an Input Manager called "Visor" for the Terminal, which puts a slide-down (tabbed!) Terminal window on a hotkey.
Visor sounds interesting. What sort of interaction is there between TM & the REPL? Do you have commands like "send defun to repl" and "send file to repl"?
No, just (load "~/Arc/deriv.arc") in the REPL (which suffices). I imagine I could hook something up with AppleScript... hmm, having problems accessing the tabs of the sliding window. If I could, then "send file to REPL" would be
on loadFile(fileName)
tell application "Visor Terminal" to ¬
do script "(load \" & POSIX path to fileName & "\") ¬
in current tab of window id -1
end sub
, assuming that the REPL was in the active tab. Well, if I can get that to work, I'll tell you.
Visor was written by the guy who wrote Quicksilver, and is similarly excellent. It's a bit tricky to get working on Leopard, but it's worth it.
I'm pretty stuck on Emacs for Lisp stuff, but interfacing with a REPL from TM would be a step closer for me to give it a shot. Understanding s-exps is next on the list.
I'll have to read more on Visor (or just try it). It doesn't look too interesting at a glance since iTerm is already a Cmb-tab away. There must be more to it that I'm missing.
I prefer Visor for a few reasons. First, I just prefer Terminal to iTerm (especially now that it has tabs). Second, F3 (my hotkey) always gets me Visor; cmd-tab may take more or less key presses depending on what apps I've been using. Third, since I set Visor up to use a different Terminal which runs in the background, so that's one less app to cmd-tab past. Mostly, it's a convenience thing-one F3, and always one F3.