Open ckknight opened 11 years ago
Now that I'm thinking about it, it would kind of make some sense to have the value
be a method instead, like get()
.
Providing that functionality, one could also test for a Box
-like object by doing is-function! o.get
.
It would also allow for formulas to mark themselves as "dirty" and only update when needed.
Also, in the following example:
let alpha = box! true
let bravo = box! "hello"
let charlie = box! "world"
let formula = formula!
if &alpha
&bravo
else
&charlie
assert &formula == "hello"
&charlie := "friend" // this should not recalculate `formula`
assert &formula == "hello"
&alpha := false // this would mark `formula` as dirty
assert &formula == "friend"
That could place a dependency on alpha
, which would then evaluate to bravo
or charlie
, only updating itself if the one actually being needed were updated, ignoring any results of the other unless alpha
changed.
It should not do any recalculations if a particular Box
is not referenced but whose value changes.
Also, in the event that a method rather than a normal property is used for the Box
interface, another macro could be useful:
let box = lazy! factorial(6)
assert &box == 720 // only at this point is factorial(6) calculated
assert &box == 720 // uses the cached version, no recalculation.
This seems a bit like lenses, unless I don't understand fully what you're suggesting. Which provide get
and set
functions over immutable structures. I don't have enough experience using them to pass worthwhile judgement on the idea, but I say go for it.
Hm, do I sense monads here? :-)
For the record, I would love a better abstraction for promises / async / lazy computation. It's just that it's a huge area and requires a lot of thinking; you can't expect an immediate useful feedback in here. If you let this idea cook for several months, maybe we can come up with something good.
On a completely different note, you should probably use TypeScript notation when describing interfaces; I think it's pretty awesome:
interface Box<T> {
// value can be a normal property or a getter, but is never expected to be set manually
value: T;
// whenever the box's value is manually being changed, the set method will be called.
// it is expected to return the new value of the Box
// if not provided, then the Box is essentially seen as read-only.
set?(newValue: T): T;
}
Btw I've seen you mention reactive stuff on IRC; I've spent a lot of time building a reactive library for LiveReload 3 (which I ended up ditching, because it was requiring exponential effort to make it handle everything I needed it to handle). Would love to discuss language support for reactive stuff.
I think this is really neat and would make a worthwhile addition, though I agree with @andreyvit that it might be useful to think this through the grander scheme of async and even promises. How compatible could nesting of such constructs as formula! and async and promises be made to be? On another note, have you looked into Elm, @ckknight? It has a lot of FRP built in and could provide ideas.
The idea is to provide an API for using and manipulating a standardized "box" interface that holds a value without being that value outright.
Although there would be a syntax for generating one of these boxes on-the-fly, the basic interface would be expected to be as such:
Essentially, any JavaScript object can function as a read-only
Box
, as long as.value
can be accessed.The way it could be used in GorillaScript is with the following syntax:
This functionality could also be expanded upon by extra methods on one's
Box
, such as something like.on-change(func)
, then the following capability could open up:This essentially allows reactive code at the language level.
This would be doable by making
formula!
walk the AST tree looking for uses of the&
prefix and declaring a dependency on that box using theon-change
API (or something similar).Some things I'm not sure about:
value
as a normal property or a method. A normal property would be more efficient in the general case, but may lead to unnecessary calculations in the case offormula!
if it's never accessed (which would be an atypical use case anyway)on-change
pseudo-API.&
would work well enough and hearkens back to C's references, but not in the same way.box!
to create a typical read-write box?formula!
referring to its parent while also being self-referential, thus leading to a case where the callback passed to its dependencies refers to a formula that has become otherwise unreachable, but unable to be GC'd due to the callback's reference to it.This would also pretty much invalidate the need for #60