I would also like to answer some questions you had in the brainstorm file.
---
"besides quasiquoting, a big challenge will be implementing closures"
If you have first-class environments, then implementing closures is a piece of cake. And since you're writing an interpreter, first-class environments make an awful lot of sense.
How it works is that every function has an environment. This environment contains two bits of information: a mapping between variables and values, and a reference to the outer environment.
Then, when looking up a variable, you start in the current environment, and if it's not found, you check in the outer environment. You then repeat this process as many times as necessary until you either find the variable, or reach the global scope.
I wrote an interpreter in Python that implements a language that is almost identical to Arc, so I can help out if you like.
---
"maybe there's no need to "declare" local variables; if you set a variable that doesn't exist, it will just be local (like coffee script)"
Probably a bad idea. Paul Graham already experimented with that with a (very) early version of Arc[1], but then realized that implicit bindings causes problems with macros. It's not a technical problem, but rather a human one: with implicit binding, it's very easy to accidentally create local bindings when you didn't want to.
You can, of course, experiment with it yourself, and perhaps you'll find a way to make it work. But personally, I like keeping binding/assignment separate. I find that it makes working with closures a lot easier. Consider this:
(let x nil
(def foo ()
(map [= x _] '(1 2 3))))
As you can see, we're creating a local variable "x", and then creating a global function "foo" that has access to "x". Then we're mapping over 3 numbers, and assigning each one to the outer variable "x".
Python gets around it by having a "nonlocal" and "global" keyword. If you're wondering, here's how you would do that in Python:
def foo():
x = None
def bar():
nonlocal x
for _ in [1, 2, 3]:
x = _
return bar
foo = foo()
Thus, you must either make bindings implicit, or assignment implicit. Python chose to make bindings implicit, which works out just fine in Python, but Python doesn't have macros.
The brainstorm file is never updated. I keep putting some brain dump there without cleaning the previous brain dumps.
I think closures already work; I just haven't tested them enough.
> How it works is that every function has an environment. This environment contains two bits of information: a mapping between variables and values, and a reference to the outer environment.
> Then, when looking up a variable, you start in the current environment, and if it's not found, you check in the outer environment. You then repeat this process as many times as necessary until you either find the variable, or reach the global scope.