| Currently, function objects can also be used to encapsulate environments so that they can be accessed in a table-like manner: (= foo
(with (var1 1 var2 2 var3 3 var4 4)
(fn (v)
(case v
var1 var1
var2 var2
var3 var3
var4 var4))))
foo!var1
However, the problem is that this abstraction breaks when setting: (= foo!var1 42)
Of course, we could just use tables, but sometimes we don't want to just store data - sometimes we want to propagate the change in the data. For example, kennytilton's Cells would want to know if and when the user changes some cell (currently he just uses accessor form - i.e. (field obj) instead of (obj 'field) - and defines a bunch of defset - but this means that using obj!field will be a "back door".). Also, we might want to encapsulate an environment instead of a table, so that, say, a bunch of other functions (accessible by obj!field) would have different effects based on a non-global (also accessible via obj!field).What I'm proposing is overloading the (annotate <with-something> <something-else>). As it is, annotated functions will still operate as functions, regardless of annotation. What I'm proposing is to overload the second argument - if it's a function, this function is the "setterfunction" for the tagged function. For example: (= foo
(with (var1 1 var2 2 var3 3 var4 4)
(annotate
; value first, so that variable-arity functions can be done.
(fn (newv v)
(case v
; this amount of boilerplate will, of course, be
; macroized somewhere.
var1 (= var1 newv)
var2 (= var2 newv)
var3 (= var3 newv)
var4 (= var4 newv)))
(fn (v)
(case v
var1 var1
var2 var2
var3 var3
var4 var4)))))
then: (= foo!var1 42)
=> 42
foo!var1
=> 42
This will allow us to encapsulate away cases where a data structure will want to perform some internal calculations. For example, we could do something like this: (= weird-stuff
(let (input1 input2 output output-valid)
(annotate
(fn (newv v)
(case v
input1 (= output-valid nil input1 newv)
input2 (= output-valid nil input2 newv)))
(fn (v)
(case v
input1 input1
input2 input2
output (if output-valid output
(= output-valid t
output (some-really-complex-calculation input1 input2))))))))
|