Overview

RubyLisp is a relatively simple Lisp dialect based on Scheme implimented using Ruby.

RubyLisp is a lexically scoped Lisp-1:

Lexically scoped:
The scope of definitions are determined by where they are made in the lexical structure of the code. Each lambda, let, and do creates a new lexical scope. FromĀ [2]:

Here references to the established entity can occur only within certain program portions that are lexically (that is, textually) contained within the establishing construct. Typically the construct will have a part designated the body, and the scope of all entities established will be (or include) the body.

Lisp-1:
A Lisp where functions and variables share a single namespace. This differs from a Lisp-2 in which functions and variables have separate namespaces.

Installation

Add this line to your application's Gemfile:

gem 'rubylisp'

And then execute:

$ bundle

Or install it yourself as:

$ gem install rubylisp

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

The rubylisp command

Installing the rubylisp gem installs the rubylisp command

>:rubylisp help
  NAME:

    rubylisp

  DESCRIPTION:

    A large sub/super-set of MIT/GNU-Scheme implemented in pure Ruby.

  COMMANDS:

    help Display global or [command] help documentation         
    repl Rubylisp REPL          
    test Runs tests     

  GLOBAL OPTIONS:

    -h, --help 
        Display help documentation

    -v, --version 
        Display version information

    -t, --trace 
        Display backtrace when an error occurs

>:

REPL

RubyLisp includes a very basic REPL that, as expected, lets you type in snippets (it does not support multiline snippets) of Lisp code, evaluates them, and prints the result.

>:rubylisp help repl

NAME:

    repl

  SYNOPSIS:

    rubylisp repl [options]

  DESCRIPTION:

    Rubylisp REPL

  EXAMPLES:

    # Simply run the REPL
    rubylisp repl

    # Run the REPL, loading a file first
    rubylisp repl --file code.lsp

  OPTIONS:

    -f, --file LISPFILE 
        The name of the lisp file to load



>: rubylisp repl

RubyLisp REPL
> 4
4
> (+ 2 3)
5
> (define (fib x) (if (eq? x 0) 1 (* x (fib (- x 1)))))
<function: fib>
> (fib 4)
24

The repl uses readline for editing and history. History is saved in ~/.rubylisp_history. Evaling (quit) will exit the repl.

Test runner

The rubylisp command also contains a test runner.

>:ruby -Ilib bin/rubylisp help test

  NAME:

    test

  SYNOPSIS:

    rubylisp test [options]

  DESCRIPTION:

    Runs tests

  EXAMPLES:

    # Run the tests in tests/list_tests.lsp with verbose output
    rubylisp test -v -f tests/list_tests.lsp

    # Quietly run all tests in the directory tests
    rubylisp test -q -d tests

  OPTIONS:

    -f, --file TESTFILE 
        The name of the test file to run

    -d, --dir TESTDIR 
        The name of a directory of test files, all of which will be run

    --verbose 
        Verbose test output: all context & it labels, and each assertion and it's result.

    --terse 
        terse test output (the default): + for passes, - for failures, and ! for errors

    --quiet 
        Only output a summary

>:rubylisp test -d lisptest --terse


Running lisp tests
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++
Ran 928 lisp tests in 7.0789 seconds
928 passes, 0 failures, 0 errors

Integrating

The simplist way to integrate RubyLisp is to have it parse and evaluate strings of lisp code.

>: irb
2.0.0-p247 :001 > require 'rubylisp'
 => true
2.0.0-p247 :002 > Lisp::Initializer.register_builtins
 => ...
2.0.0-p247 :003 > Lisp::Parser.new.parse_and_eval('(+ 1 2)').to_s
 => "3"
2.0.0-p247 :004 >

But lets say you are using rubylisp to do something more embedded such as provide an extension language to your application. It's easy to provide the Lisp runtime with functions written in Ruby that can be called from Lisp code.

to be continued...