Does it really store a new copy of the function each time? I thought it would only store the closure, and apparently closures are cheap ( http://arclanguage.org/item?id=7342 ) (sorry almkglor, I end up quoting you all the time).
And as for redefining functions: once your api is stable there's probably less need to redefine functions, and if necessary you can still
(= p!until (fn () ...))
(although this way you don't have access to "private" variables in the lexical scope of the original. I'm completely with EliAndrewC in preferring (p!until ...) over (person-until p ...)
And thanks for nobj, it's awesome. It makes my macro look like Visual Basic. Slowly, I learn ...
Yes, a good implementation should store just the closed variables and a reference to the code - there shouldn't be any code duplication.
It thus depends on how many local variables are being closed over. Note that in some implementations (although not in arc2c, and by inference not in SNAP) a closure is just two pointers: a reference to an environment and a reference to the code. Of course each 'let form and function would create a new environment though, and this style is not so often used because lookup of closed variables can require indirection.
You're welcome---I'm glad to have been of assistance.
As for storing copies, I would have said that it would store extra copies because of the different variable it closes over, but almkglor points out that you can separate code and environment, so the question is what mzscheme does.
The thing about redefinition is that in, say, Ruby, you can do
class String
def foo
code_goes_here
end
end
And every string will have that new foo method. Here, you can only redefine the methods of one object.
For me, the real syntax question is whether we want (until p age) (which probably means that we are using the CLOS model of generic functions) or we want (p!until age) (which probably means that we are using the Smalltalk model of message passing). I sort of like the former syntax, but I also sort of prefer the Smalltalk model. What do you think?
Note that redefinition using (p!until age) syntax is still possible in Arc using 'defcall and if you predeclare the private variables.
For instance, consider this:
(deftype foo (x)
(private y z)
(meth niaw ()
(do-something x y z))
(meth arf (something)
(do-something-else something x y z)))
=>
(let methods
(table
; lambda lifted!
'niaw
(fn (x y z)
(do-something x y z))
'arf
(fn (x y z something)
(do-something-else something x y z)))
(def foo-replace-method (s f)
(= (methods s) f))
; so external code can determine the local variables
(def foo-get-private-variables ()
'(x y z))
(def foo (x)
(with (y nil z nil)
(let invoker
(fn (f rest)
(apply f x y z rest))
(fn (which-method)
(aif
(methods which-method)
(fn rest (invoker it rest)))))))