7 ms·
> supporting interaction or encapsulated state I don't know what you mean. Could you give an example of this? What would you like to be able to do?
by createuniverses 12y ago
> supporting interaction or encapsulated state
I don't know what you mean. Could you give an example of this? What would you like to be able to do?
- seanmcdirmid 12y agoYour render loop looks like: while true: renderP() Now, renderP will get executed afresh each time. Assuming no static data, if you want any state at all it must be global to the loop; e.g. var state = initValue while true: renderP(ref state) Immediate-mode UIs suffer from the same constraint, and really, the author is getting most of their liveness by being immediate.
- alloyed 12y agoWhat about the old let-over-lambda? do var state = init fn renderP() ... end end Depending on what you wanted the state for, I think it satisfies most of the properties you'd be missing with a persistent, not-in loop state. It wipes itself on refresh, it has a distinct owner, it can be individually refreshed just by re-evaluating everything inside the do-block, etc.
- createuniverses 12y agoThank you for that succinct and immediately useful example of let-over-lambda!
- seanmcdirmid 12y agoYou actually don't want to wipe on refresh; i.e. if you are doing a physics simulation using a standard stepped based integrator. You'd be surprised how many artists want to live code particle simulations.
- createuniverses 12y agoI've wrangled a crazy way to have your cake and eat it too. do local state = 0 function render() drawLine(0,5,0, 0,5,50*math.sin(state)) state = state + math.pi * 0.03 end end To fiddle with the "state" variable from the outside: name,val = debug.getupvalue(render, 1) print(name) -- state print(val) -- state's value debug.setupvalue(render, 1, 0) -- set state to 0 To find out how many upvalues are available: dt = debug.getinfo(render) print(dt.nups) If you want to redefine render without disturbing state, you need to backup state and make a new closure with the new definition of render and the restored state: do local savedstate = {debug.getupvalue(render,1)} local state = savedstate[2] function render() local h = 5 drawLine(0,h,0,50 * math.sin(state), h,0) state = state + math.pi * 0.06 end end I don't think its possible (or I don't know how) to redefine a function inside a closure. So just make a new closure and restore its state.
- seanmcdirmid 12y agoWell, there are many hacks around it; see the immediate-mode programming frameworks like Sol. My own personal take on this problem is to make "refresh" a first-class part of the programming model (rather than something managed by the programmer), and then to define encapsulated state that is preserved on refresh (by the programming model). You can read about it in my paper. (http://research.microsoft.com/apps/pubs/default.aspx?id=211297 http://research.microsoft.com/apps/pubs/default.aspx?id=2112...) The trick is to generate stable IDs to represent the state, then you can think of it as a global map: var map = new Map() def render(): var x = map[0x138293] ... map[0x13244] = y This resembles your last solution above. The trick is then automatically reproducing those IDs when render is called again (not to mention tearing down any side effects no longer performed, but that is another kettle of fish).