I'm getting closer to figuring this stuff out (I hope).
One problem with this super-simple system is that I wasn't able to figure out how functions fit into it... And fexprs just seemed to really muck things up even worse, and it's just a big pain and all.
But I wasn't really able to get rid of fexprs, or to be more specific, I couldn't find a better idea. Haskell has all this loveliness going on by using functions for pretty much everything, but I want to try a different route. I want to see how far I can push a functional OOP language with immutable objects and gensyms.
So for now, here's the plan. $vau will have to be built-in (duh) but using this system, it could in principle be written in user-land, provided you had a few other primitives like $quote, each, etc.
$vau will return an object. This object has a %call property, which lets you specify custom behavior when calling an object. This %call property is actually another object, which has an %argument, %environment, %body, and %closure properties.
Each property is a Nulan datatype, like an object or number or whatever, so this avoids the problem of using native JavaScript functions (I don't want to expose native things to Nulan that have the same purpose as Nulan data types, unless the reason is for speed).
That means that this vau:
($vau E [Args Body]
(wrap (eval E [$vau ~ Args Body])))
%closure would be the environment that the vau was defined in. This makes it possible not only to inspect the argument, body, environment, etc. of all vaus/functions, but also lets you modify them (keep in mind objects are immutable, so this doesn't cause any problems).
It also lets you attach arbitrary properties to vaus. Including other things, this means that (in principle) you can implement "wrap" in user-land:
$def %wrapped (uniq)
$def wrap
$vau E [F]
$let F (eval E F)
{ @($vau E X
(F (each X; X -> (eval E X))))
%wrapped F }
And then define $fn in terms of wrap, like usual:
$def $fn
$vau E [Args Body]
wrap (eval E [$vau ~ Args Body])
And then define "unwrap":
$def unwrap
$fn [{ %wrapped F }]
F
So I guess this means Nulan is going into the "everything is an object" direction, rather than the hardcore Haskell way which isn't too far from "everything is a function"
It'll be interesting to see how these immutable objects combine with the functional/recursive style of Nulan.
---
Oh yeah, and I've been playing with the idea of getting rid of var, so that there's no mutation whatsoever. Recursive functions would have to use the Y combinator. I'm not decided on this either.