Live Programming for Event-based Languages
Christopher Schuster, Cormac Flanagan
University of California, Santa Cruz
{cschuste, cormac}@ucsc.edu

Traditional Edit-Compile-Restart-Cycle

Live Programming Environment

Live Edits to Running Programs

Classic Problem: Dynamic Software Updating, Hot Swapping, etc.

No General Solution! — Design Space of Alternatives

Desired behavior after code updates

  • Replay all events since program start
  • Continue executing with potentially inconsistent state

Data might need to be updated along with code

  • Production systems: specify patches/data migrations manually
  • Debugging/live programming: minmize impact on development flow

Code Updates and Execution State

Challenge 1: Call Stack

var i = 0;
function inc() { i++; }
inc(); i+=2;
console.log(i);

Where does inc() return to?

Challenge 2: Output out of date

<div>
  <button>Click Me</button>
  <span>Count: 0</span>
</div>  Clicks:

Count: 0
<script>
var i = 0;     "mouseover"
$("button").on("click", function() {
  $("span").html("Count: " + (++i));
});              "Clicks: "
</script>

Challenge 3: Closures in State

<div>
  <button>Click Me</button>
  <span>Count: 0</span>
</div>

<script>           (i,n)
function mkCounter(i) {      i+=n
  return function() { return ++i; };
}                      (0,2)
var counter = mkCounter(0);
$("button").on("click", function() {
  $("span").html("Count: " + counter());
});
</script>

Challenge 4:
New Code Incompatible with State

<div>
  <button>Click Me</button>
  <span>Count: 0</span>
</div>

<script>
var i = 0;[];
$("button").on("click", function() {
  i.push(Date.now());
  $("span").html("Count: " + (++i));i.length);
});
</script>

Live Programming in
Event-based Languages

Single-threaded event loop (e.g. JavaScript)

  • Treat code updates as events
  • No code updates during event processing

⟶ No Active Call Stack or Program Counter

Separate Event Handling
and Rendering

init :: () ⟶ State

  • Computes initial application state

handle :: Event × State ⟶ State

  • Processes an event and returns new application state

render :: State ⟶ Output

  • Determines output based on the current state

Contraints

  • render should not change state
  • The application state should not contain function values

Separate Event Handling from Rendering: Example

var i = 0;

function inc() { i++; }

function render() {
  return (
    <div>
      <button onclick={inc}>Click Me</button>
      <span>Count: 0{i}</span>
    </div>);
}

Implementation 1/2

Code gets parsed, checked, rewritten and evaluated upon each change

Rewriting turns global references to access a managed state object

  function inc() { i++; }
⟶ function inc() { ENV.state.i++; }

Variable initializations will be extracted to an init function

  var i = 0;
⟶ function init() { ENV.state.i = 0; }

JSX (JavaScript with inline-XML) will be expanding to regular JavaScript (other ways of generating HTML would work equally well)

  var i = <p>Hello!</p>;
⟶ var i = {type: 'p', children: ['Hello!']};

Implementation 2/2

After each event,

  • the state will be checked for function values
  • a clone of the state will be saved for time travel
  • render is called with an immutable clone of the state
    (using Object.freeze)

UI for accessing previous code versions and states

Github Repository: https://github.com/levjj/rde/

Online Live Demo: https://levjj.github.io/rde/

Demo

Navigating history of execution and code

Summary

Challenge Proposed Solution
Updating running functions Use single event loop to update code
Outdated visual feedback Seperate rendering from event handling
Updating function values/closures Restrict application state !
Inconsistencies between state and code Programmer may need to restart

Enables live programming, time travel and continous feedback

Implemented in JavaScript but works for any event-based language

Future Work

Restricting function values in the state may be too strong (e.g. OOP)

Use programming language features to ...

  • enforce constraints (static analysis, contracts, etc.)
  • optimize performance (incremental computation, copy-on-write, etc.)

Improve tool support, e.g. programming by example

  • Write render function by direct manipulation in the output
  • Write event handling function by providing examples of states before and after an event

Related Work

Literature

  • Burckhardt, Fahndrich, de Halleux, McDirmid, Moskal, Tillmann, and Kato. It’s Alive! Continuous Feedback in UI Programming. PLDI ’13.
  • McDirmid. Usable Live Programming. Onward!'13.

Inspirations

  • Bret Victor. Inventing on Principle. 2012.

Smalltalk/Squeak

Elm

React/Redux

Thank you!

Degenerated Case: DOM as part of Application State

var i = 0;
var dom = (
  <div>
    <button onclick={inc}>Click Me</button>
    <span>Count: 0</span>
  </div>);

function inc() {
  dom.find('span').html = 'Count: ' + (++i);
}

function render() { return dom; }

  /