
Praxis – A live coding environment based on Lua, Lisp and Forth - createuniverses
https://github.com/createuniverses/praxis
======
davvid
If you're interested in this then you should definitely checkout extempore:

[https://github.com/digego/extempore](https://github.com/digego/extempore)

[http://benswift.me/extempore-docs/index.html](http://benswift.me/extempore-
docs/index.html)

------
seanmcdirmid
Is a language environment really live if it does not support interaction or
encapsulated state (inside rather than outside of the render loop)? Is it
really live if you have to manually refresh your code?

Well, I guess it does fit the requirements of live coding.

~~~
createuniverses
> 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
Your 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
What 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.

~~~
seanmcdirmid
You 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
I'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
Well, 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=2112...](http://research.microsoft.com/apps/pubs/default.aspx?id=211297))

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).

------
pmoriarty
Also see:

[http://www.pawfal.org/fluxus/](http://www.pawfal.org/fluxus/)

------
sklogic
So far all of the live coding demos were about graphics. I wonder if it's
possible to do something similar with something of a much less interactive
nature - say, number crunching, compilers, linkers, etc.

~~~
createuniverses
The whole thing is a repl with a graphical and audio engine at your disposal
to use as you see fit. As well as writing your program iteratively in the
"socratic" repl style, you are free to fluidly create whatever visualizations
you wish along the way to help you. As well as this, if you split the process
you have implemented into frames (a simple way is with coroutines or closures)
you can make whatever visualization you prefer of your number crunching. For
example, throw in some yield() calls in your program and every update() do a
coroutine.resume(). In render() visualize the state of your program how you
wish. The great thing about this is, as you change your program, the effect of
your change will be reflected in what is rendered.

~~~
sklogic
Interesting, it's something to think on. Creating such visualisations manually
may be prohibitively complicated, but I can imagine some cases where they can
be derived automatically (e.g., for compiler passes, an example IR can be
displayed before and after).

~~~
seanmcdirmid
You might also want to check out live programming, which focuses on
interactive debugging rather than the improvised problem solving (as well as
live performance) of live coding. Once you get to live programming, techniques
like time travel become viable, which otherwise don't make much sense with
live coding. You can then better tackle traditional programming problems with
better live feedback.

------
verytrivial
More often than not, these interactive / interpreted environments feel like
Smalltalk by installment.

~~~
seanmcdirmid
This is actually a law:

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.

~~~
verytrivial
No smugness intended, sorry. I only ever toyed with it. I am genuinely curious
why e.g. Squeak never caught on with the artsy types considering it has many
but by no means all of the interactivty and feedback that is desirable in
these spaces. And again Squeak at least tried to position itself as a media-
rich system. Perhaps performance always has primacy. And I don't seem to
follow your point regarding liveness -- a language that supports many aspects
of live programming but requires a supporting loop is of no value? That does
seem like a very strong criticism.

~~~
seanmcdirmid
Squeak supports two kinds of liveness. The first is general hotswapping, which
appears in mainstream languages (though not done as well as smalltalk), and as
mentioned, isn't very live. Once you add the loop, you still have lots of
problems to solve (e.g. is their encapsulated state, how is the state upgraded
on a code change?). To make it live requires huge compromises, and anyways you
could make the same modification with any language that supports hotswapping.

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).

------
3838
praxis makes me think of the dutch diy store chain - if you go to one in
amsterdam they play reggae and you can buy a bhudda for your garden (or
balcony more likely)

