Praxis – A live coding environment based on Lua, Lisp and Forth
github.com
github.com
Well, I guess it does fit the requirements of live coding.
I don't know what you mean. Could you give an example of this? What would you like to be able to do?
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. 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. 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.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).My ideal environment would have the ability to pause at a certain point, saving the state. Then I want to run to a another point (maybe only a few lines to a couple dozen lines down) and see the variable values and results in between.
Basically I want to live code with some defined input to section off parts of the program and still be able to iterate quickly by seeing results every time what I am typing will compile.
I also want to be able to visualize more data than just single values. I want to be able to see results of flat arrays, and write custom visualizers for more complex data structures. I have actually done a lot in this area, essentially by having a window in a separate thread that I can pass closures to (that run openGL functions on their data to draw it). This works incredibly well to let you see your software run. I don't know how I would have been able to write and debug some very difficult programs without it.
Whenever someone brings up any kind of interactive programming environment, no matter how much it does not resembles Smalltalk or Lisp, someone will always say it completely resembles Smalltalk or Lisp with no significant improvement. We call it the "smug smalltalk/lisp weenie" syndrome.
BTW, Smalltalk supports hotswapping without the liveness of course. There is nothing in smalltalk that allows the code to re-execute in its proper context without execution coming back to the code in a refresh loop setup by the user.
The second is direct object manipulation via morphic, which is quite different from manipulating the program via its code. The line is blurred a bit given that Squeak is image based (so changes to objects that you make will persist).