Live coding (fluxus) captured my interest. Evolutionary programming a game system using scheme will be a nice pet project to experiment with.

PLT-Scheme

Checking out different versions of scheme i stumbled upon gambit and ypsilon and plt-scheme. After some deliberation i chose plt-scheme. Nicely organised, good documentation and standard libraries and big community. Very active irc channel on irc.freenode.org #scheme which answered my questions within 5 minutes.

Wikipedia describes PLT scheme in a nice fashion:

From the beginning, the PLT project was also an experiment in evaluating the suitability of Scheme as a programming language for large projects. In a sense, the language failed and yet it also proved to be an ideal platform. Scheme per se failed because the standard language, as defined in the reports, is too small for a team of 20-30 developers, distributed across three continents. If taken as an ideal kernel, however, Scheme succeeded beyond the team's expectations.

We need a window to run our app in

PLT Scheme has a gui toolkit which can be loaded with.

(require scheme/gui/base)

This library needs primitive graphics support at runtime an cannot be executed with mzscheme. For these programs we have mred.

MzScheme, MrEd, PLT's graphical user toolkit

As I understand it, PLT-Scheme has mzscheme as an ideal lightweight scripting environment. And MrEd for GUI based apps.

 mred -iz -l readline -l scheme/enter

We load 2 libraries not standard included in my version of mred:

Windowing time

The gui/base consist of an hierarchy of classes, interesting for us are:

Every painter needs a canvas

For our app to at least draw anything we need an opengl ready canvas. The window should also be able to recognize size changes and a method to actually draw something on our canvas.

the functions resize and paint will be defined later.

(define gl-canvas%
  (class* canvas% ()
          (inherit with-gl-context swap-gl-buffers)

          (define/override (on-paint)
                           (with-gl-context
                             (lambda ()
                               (paint)
                               (swap-gl-buffers))))

          (define/override (on-size width height)
                           (with-gl-context
                             (lambda ()
                               (resize width height))))

          (super-instantiate () (style '(gl))))) 

Without the frame we cannot hang the painting

Our canvas needs to framed for the os to display it.

(define window 
  (new frame% (label "Minimal") (min-width 200) (min-height 200)))

Rendering time

Now we have setup a minimal frame with a canvas which is opengl ready. Now we can execute OpenGl calls to actually start drawing. resize is called on a resize and since this is minimal does nothing. paint is called when the canvas is exposed or resized so that the image in the canvas can be repainted.

;; gl-canvas functions resise and main draw
(define (resize w h) #t)

(define (paint)
  (glClearColor 0.0 0.0 0.0 0.0)
  (glClear GL_COLOR_BUFFER_BIT)
  (glColor3d 1.0 1.0 1.0)

  (glMatrixMode GL_PROJECTION)
  (glLoadIdentity)
  (glOrtho 0.0 1.0 0.0 1.0 -1.0 1.0)
  (glMatrixMode GL_MODELVIEW)
  (glLoadIdentity)

  (glBegin GL_QUADS)
  (glVertex3d 0.25 0.25 0.0)
  (glVertex3d 0.75 0.25 0.0)
  (glVertex3d 0.75 0.75 0.0)
  (glVertex3d 0.25 0.75 0.0)
  (glEnd)
  )

Putting it all together

To actually create the frame canvas, and fire the on-paint and on-size triggers send the window instance the show message. This should create all.

;; show window
(send window show #t)

And now for live coding!

The essential element here is the live coding. This is accomplished by changing the paint function and sending it to your repl. First we need to change the evaluation context. This is done by:

(enter! "minimal.ss")

and redefining paint:

(define (paint)
  (glClearColor 0.0 0.0 0.0 0.0)
  (glClear GL_COLOR_BUFFER_BIT)
  (glColor3d 0.0 1.0 1.0)

  (glMatrixMode GL_PROJECTION)
  (glLoadIdentity)
  (glOrtho 0.0 1.0 0.0 1.0 -1.0 1.0)
  (glMatrixMode GL_MODELVIEW)
  (glLoadIdentity)

  (glBegin GL_QUADS)
  (glVertex3d 0.25 0.25 0.0)
  (glVertex3d 0.75 0.25 0.0)
  (glVertex3d 0.75 0.75 0.0)
  (glVertex3d 0.25 0.75 0.0)
  (glEnd)
  )

now change size of the window to trigger a on-paint and the colour of the square changes. The basic elements of live coding are accomplished.


Fork me on GitHub