The L3 language and interface

L3 Logo

Table of Contents Logo

L3 is a Python-like language with convenient interaction features and a worksheet interface.

1 Overview

l3lang(1) is a persistent, interpreted language designed to make interacting with scripts and the data they produce convenient. It does this by keeping track of all computed values (reducing file clutter), providing nested namespaces and functions (avoiding name clashes), and giving point-and-click access to the computed values through the script itself (avoiding the filesystem detour).

It is primarily used through l3gui(1), a worksheet-style interface. Long-running scripts can be executed without the interface, and the results loaded later for interaction.

To avoid the need to learn yet another language, L3 is compatible with a subset of Python and can use any Python library, including Python C/C++ extensions. In particular, the sparx tools (image processing) and NumPy (numerical linear algebra) are known to work. The RPy (statistical computing via R) package also works, but extra care must be taken to make sessions persistent.

In l3gui, every part of a script is an object and its value(s) can be examined via mouse menus, or reinserted into the gui for use in other scripts. This mechanism includes nested loops and function definitions; all values computed in a loop or function can be inspected later.

Scripts and code fragments can be assembled as structures, providing graphical script construction for problems with few steps.

2 Examples

The introduction is somewhat bland, so here are some examples to illustrate why you may want to use L3. They are all included with the gui.

2.1 Hello world

The standard example, with twists. See hello, world!

2.2 Statistics via RPy

This example is the the rpy demo with minor modifications to run in L3. A nice example of worksheet convenience. See the L3 rpy demo.

2.3 Graphics and web data via matplotlib

Using the matplotlib library, this demo loads, graphs and manipulates some financial data.

2.4 Numerical convergence

Implement a simple iteration to compute sqrt(x), and examine intermediate results. See the sqrt demo.

3 Status: developer

The l3 language is functional with some small command-line interface adjustments still needed.

The l3 gui is also usable, but still contains menu entries and cruft more useful for developers than users.

Documentation is very rudimentary and gaps will be filled over the first few months of 2008.

4 Documentation

Manual pages

5 Installation

The raw files are available from the sourceforge project page, but read the following before installing.

l3lang and l3gui are separate packages, with different prerequisites.

l3lang only requires Python (2.4 or newer) and is therefore trivial to install.

l3gui requires l3lang, Python, pygtk (2.4 or newer), libgnomecanvas, and the canvas part of the gnome-python binding. In recent linux distributions, these are available via the package handling system; follow the system installation steps.

For older or customized systems, use the self-contained alternate installation method.


5.1 Using system libraries

5.1.1 Prerequisites

Newer releases of linux and FreeBSD make the prequisites available via simple commands. First install these prerequisites, then install L3.

  • Fedora core

      yum install  gnome-python2-canvas

  • Ubuntu / Debian

     apt-get install  python-gnomecanvas

5.1.2 Download L3

To install l3 proper, download l3lang-0.3.1.tar.gz and l3gui-0.3.1.tar.gz, extract them, and run The download steps using the shell are:

    cd /tmp
    tar zxf l3lang-0.3.1.tar.gz
    tar zxf l3gui-0.3.1.tar.gz

5.1.3 Install L3

Installation can be to system directories, a local directory, or l3 can be run from the distribution directory without installation. Choose one of the following.

  • System installation
    System installation is done via
        cd l3lang-0.3.1
        python install --record INSTALLED-FILES
        cd ../l3gui
        python install --record INSTALLED-FILES
    but requires root access.
  • Installation to prefix
    Installation to a local directory is supported; the minimal shell setup for bash/ksh for using a local directory $HOME/linux-local with Python 2.4 is:
       export PYVERSION=2.4
       export MYPREFIX=$HOME/linux-local
       export PATH=$MYPREFIX/bin:$PATH
       export PYTHONPATH=$MYPREFIX/lib/python${PYVERSION}/site-packages:$PYTHONPATH 
       export MANPATH=$MYPREFIX/man:$MYPREFIX/share/man:$MANPATH

    followed by installation via

       cd l3lang-0.3.1
       python  install --prefix=$MYPREFIX --record INSTALLED-FILES
       cd ../l3gui-0.3.1
       python  install --prefix=$MYPREFIX --record INSTALLED-FILES


  • Use without installation
    The minimalistic adjustments are to ignore the installation step and only set the PATH, PYTHONPATH, and MANPATH:
       export PYTHONPATH=`pwd`/l3gui:`pwd`/l3lang:$PYTHONPATH 
       export PATH=`pwd`/l3gui/bin:`pwd`/l3lang/bin:$PATH
       export MANPATH=`pwd`/l3gui/doc/man:`pwd`/l3lang/doc/man:$MANPATH
    This requires removing the version number:
       mv l3lang-0.3.1 l3lang
       mv l3gui-0.3.1 l3gui
       chmod a+x l3lang/bin/*    l3gui/bin/*

5.1.4 Quick test

Once installed, a quick installation check can be done by reading the documentation and running the toplevel:

   man l3
   man l3gui
Or run the gui via


5.2 Self-contained installation

An installer based on GARNOME (itself based on the linux-bbc gar build setup) is available. This provides a local environment for using / incorporating other packages outside the system's package handler (rpm/dpkg/pkg_add), which is particularly useful for

  • older linux/UNIX versions lacking the gtk/gnome canvas;
  • a self-contained installation to a local directory, including environment-setting scripts and other niceties;
  • multiple independent development trees.

This installer is used for the sparx project that l3 is part of and contains rules for many more packages, but installation of the L3 subset is simple.

Installation from source can be done as follows.


    mkdir /your/installer/path
    cd /your/installer/path

Then, preferably:

    svn co svn:// \

If you do not have subversion, and don't mind reinstalling everything occasionally, you can instead use this:

    tar zxvf sparx-installer.tar.gz

If you don't have wget, try curl instead:

    curl -o sparx-installer.tar.gz


    cd sparx-installer
    ./configure /your/sparxroot

The last step (./configure) will print a summary. If there are any errors, your system is missing the listed prerequisite(s).

The install is done via

    cd sparx/l3gui
    make install

When run successfully, this takes between 1.5 and 2.5 hours, depending on the machine used.

6 Licenses

7 Developer download

Development is done using git so anyone can have their own local development branches. The web interface is at, and you can get the whole repository including l3doc, -lang, and -gui via

git-clone git:// l3full

The working directories can be directly used with appropriate settings, via minimalistic adjustments:

   cd l3full
   export PATH=`pwd`/l3gui/bin:`pwd`/l3lang/bin:$PATH
   export MANPATH=`pwd`/l3gui/doc/man:`pwd`/l3lang/doc/man:$MANPATH

8 Developer tools

Several parts of l3lang can be used as libraries for other purposes.

8.1 Language manipulation tools

L3 parser / pattern matcher / pretty printer

The l3lang.reader module implements the l3 parser, currently using the Python tokenize module and a PLY grammar to parse input text and produce the l3 AST.

The l3lang.pretty module is a box-based pretty-printer providing horizontal (H) vertical (V), and horizontal-or-vertical (HOV) boxes. It is a transliteration from the ocaml version of Wadler's pretty printer.

l3lang.ast provides AST manipulation tools, including a simple pattern matcher.

l3lang.view provides tools for printing the AST. Two functions of general interest are get_infix_string() which returns a pretty-printed representation of an AST, and print_info() which produces a prefix dump of the AST.

As example, the full read / print cycle starts from

tree = reader.parse('''
a = 1
def loop(a):
    if a < 3:
        print a
        loop(a + 1)


print tree.get_infix_string(40)
    def loop(a):
        if (a < 3):
            print_(a);loop((a + 1))
print tree.get_infix_string(10)
tries to squeeze more:
    def loop(a):
        if (a

9 Author / Contact info

Author: Michael Hohn <mhhohn at users dot>

Date: 2008/04/07 12:15:27