llava version 2004-12-05-alpha

llava

llava is Java in Lisp syntax (or a Scheme-like interface to Java).

Lisp + jAVA = lava (but lava.org already taken, thus: llava)

llava is pronounced "lava" - like the molten stuff, or "yava" - as in Spanish.


Table of Contents

I. Reference
1. Download, install, run
2. The llava Language
org.llava
Notation, Terminology and Convections
Creating a Java Object
Virtual Method Invocation
Static Method Invocation
Virtual Field Access
Static Field Access
Generic Procedure Definitions
Lambda Procedure Definitions
try/catch/finally and throw
Concurrency
Macros
package/import Namespaces
Misc
Read-Compile-Eval-Print-Loop
Semantics
Syntax
Immutable Syntax
Lexical Conventions
Expressions
Primitive Expression Types
Derived Conditionals
Binding Constructs
Iteration
Procedures
Equivalence Predicates
Numbers
Booleans
Pairs and Lists
Symbols
Strings
Vectors
Control Features
Input and Output
3. Libraries
org.llava.lib.Control
org.llava.lib.Exception
org.llava.lib.List
org.llava.lib.LlavaDoc
org.llava.lib.Macro
org.llava.lib.Program
org.llava.lib.String
org.llava.lib.Thread
org.llava.lib.Vector
org.llava.lib.cl.Control
org.llava.lib.cl.Macro
org.llava.lib.cl.Symbol
org.llava.lib.cl.Sequence
org.llava.lib.io.FileWalker
org.llava.lib.java.Lang
org.llava.lib.reflect.Namespace
org.llava.lib.reflect.Reflect
org.llava.lib.scm.List
org.llava.lib.scm.Predicate
org.llava.lib.scm.String
org.llava.lib.test.Test
org.llava.lib.xml.L2X
II. Implementation
III. Appendices
A. Motivation
B. Copyright and License

Reference

Chapter 1. Download, install, run

  • Requires J2SE 1.2 or greater.

  • Go to llava.org

  • Download llava.zip

  • Unzip it resulting in llava.jar

  • Startup: java -jar llava.jar

  • Or: java -cp llava.jar org.llava.Llava

  • Note, you should start up with the main class, org.llava.Llava, if you want to import llava files (i.e., *.lva) from locations on your classpath

  • Examples: check out the libraries in org.llava.lib in llava.jar

  • Optional source code: llavasrc.zip

  • ChangeLog

  • llava version 2004-12-05-alpha

  • Known bugs

  • For a full list of improvements see the TODO list

  • Previous versions

Chapter 2. The llava Language

org.llava

Notation, Terminology and Convections

Entry format

Each entry describes one language feature (or group) where a feature is either a syntactic construct or a procedure. An entry begins with lines of the form

(template)

-- category -- location

where category may be "syntax" or "procedure", and where location specifies the package containing the feature. If the location is contained inside (import location) then the package must be imported in order to use the feature. Otherwise the feature is already imported and location simply gives the package location of the feature.

Evaluation examples
The symbol ==> used in program examples should be read "evaluates to." For example,

(* 5 8)  ==>    40

means that the expression (* 5 8) evalutes to the object 40.

llava file suffix
By convention, llava files end with a .lva suffix. e.g., foo.lva

Creating a Java Object

(new packagePathAndClassName obj ...)

-- syntax -- org.llava

Examples:

(new 'java.util.Date)
(new 'java.lang.Integer 3)

Note: if the class has been imported then you can call the constructor directly:

(import java.lang.Integer)
(Integer 3)

or you can use new shorthand:

(new 'Integer 3)

Also note, even though new is syntax, all arguments are evaluated.


(new* packagePathAndClassName obj ...)

-- procedure -- org.llava

Like syntax new except it is a procedure and it must be given the full package and classname (i.e., it does not accept imported shorthand like new).

Virtual Method Invocation

(-i methodName targetObj obj ...)

-- procedure -- org.llava

Examples:

(-i 'getMonth (new 'java.util.Date))

Note, virtual methods may use standard (and preferred) prefix generic procedure notation:

(methodName targetObj obj ...)

If methodName has not been bound or has been bound to a generic procedure then this is equivalent to:

(-i methodName targetObj obj ...)

The above example is best written as:

(getMonth (new 'java.util.Date))

Static Method Invocation

(-si methodName classOrClassName obj ...)

-- procedure -- org.llava

Examples:

(-si 'parseInt 'java.lang.Integer "ff" 16)

Note, static methods may be called directly after their class has been imported. The above example can then be written:

(import java.lang.Integer)
(parseInt "ff" 16)

or

(Integer.parseInt "ff" 16)

Virtual Field Access

(-f fieldName targetObj optionalSetterValue)

-- procedure -- org.llava

Examples:

(-f 'minor (new 'org.omg.CORBA.BAD_PARAM))    ; get
(-f 'minor (new 'org.omg.CORBA.BAD_PARAM) 56) ; set

Note, virtual fields may be accessed directly after their class has been imported. The above example can then be written:

(import org.omg.CORBA.SystemException)
(minor (new 'org.omg.CORBA.BAD_PARAM))
(minor! (new 'org.omg.CORBA.BAD_PARAM) 56)

Static Field Access

(-sf fieldName classOrClassName optionalSetterValue)

-- procedure -- org.llava

Examples:

(-sf 'out 'java.lang.System)   ; get
(-sf 'out 'java.lang.System 0) ; set - and an error since Field is final

Note, static fields may be accessed directly after their class has been imported. The above example can then be witten as:

(import java.lang.System)
(out)
(out! 0)

or, preferred

(System.out)

Generic Procedure Definitions

(define ( variable requiredArg ... . optionalArg ) body)

-- syntax -- org.llava

Binds a procedure to variable that, when called, will first use Java reflection to find a method on the first argument that matches the types of the remaining arguments. If one is found it is invoked. Otherwise body is executed after the arguments are bound.

Example:

(define (name requiredArg1 requiredArg2 . optionalArgs) body)

Defines a generic procedure which, when called as:

(name 1 2)

will first try:

(-i name 1 2)

If no Java method is found (and invoked) then the generic procedure body will be called:

((lambda (requiredArg1 requiredArg2 . optionalArgs) body) 1 2)

Example:

(define (getMessage x)
  (cdr x))

(getMessage '(1 2 3)) ==> (2 3)

(getMessage (new 'java.lang.Exception "test msg")) ==> test msg

Lambda Procedure Definitions

(define variable ( lambda ( requiredArg ... . optionalArgs ) body ) )

-- syntax -- org.llava

Binds a procedure to variable that, when called, will always execute body after the arguments are bound.

Example:

(define name (lambda (requiredArg1 requiredArg2 . optionalArgs) body)

defines a generic procedure which, when called as:

(name 1 2)

will always call:

((lambda (requiredArg1 requiredArg2 . optionalArgs) body) 1 2)

try/catch/finally and throw

Example:

(let ((bomb 1))
  (define (demo)
    (try
     (begin
       (if (< bomb 0)
	   (throw (new 'java.lang.RuntimeException "Give up!")))
       (list "Normal result is: " (/ 2 bomb)))
     (catch (java.lang.ArithmeticException e)
       (list "Arithmetic: " e))
     (catch (java.lang.Exception e)
       (list "Exception: " e))
     (finally
       (set! bomb (- bomb 1))))))

(demo) ==> (Normal result is:  2)
(demo) ==> (Arithmetic:  java.lang.ArithmeticException: / by zero)
(demo) ==> (Exception:  java.lang.RuntimeException: Give up!)

Note, it is not necessary to give the full classpath in the catch clause if the class has been imported.

Concurrency

Also see org.llava.lib.Thread

(synchronized lock-obj expression1 ...)

-- procedure -- org.llava

Macros

Same as Common Lisp. See org.llava.lib.cl.Macro.

package/import Namespaces

package and import create, load and reference namespaces.

(package symbol)

-- syntax -- org.llava

package creates a namespace with the given name if it does not exist.

package changes to the named namespace such that definitions and references occur with respect to that namespace.


(import symbol)

-- syntax -- org.llava

import searches the roots of CLASSPATH for files ending in *.lva with the given path and name. If one is found it is loaded.

The first form in an imported *.lva file must be a package declaration.

The namespace of the imported package is added to the end of list of namespaces imported into the package current when the import statement is evaluated.

Variable definitions and references occur with respect to the current package. If the variable is not found in the current package the import list is searched in order. If not found in the import list the top-level org.llava package is searched last.

If symbol names a *.class file instead then it results in generic procedure definitions for all virtual methods and results in non-generic procedure definitions of static methods and fields (both static and virtual):

(import java.lang.System)

then

(java.lang.System.out)

and

(System.out)
	;; both equivalent to (-sf 'out 'java.lang.System)
(import java.lang.Integer)

then

(java.lang.Integer.TYPE)

and

(Integer.TYPE)
	;; both equivalent to (-sf 'TYPE 'java.lang.Integer)
(java.lang.Integer.parseInt "ff" 16)

and

(Integer.parseInt "ff" 16)
        ;; both equivalent to (-si 'parseInt 'java.lang.Integer "ff" 16)

Note: these definitions take places in the current package. In the future this will change such that a llava namespace is created, the definitions will be placed in that package and that package will be added to the import list of the current package.

Misc

(instanceof obj symbol-or-string)

-- procedure -- org.llava

Example:

(instanceof (new 'java.util.Hashtable) 'java.util.Hashtable) ==> true

Note, like new, the full classpath is not necessary if the class has been imported:

(import java.util.Hashtable)
(instanceof (new 'Hashtable) 'Hashtable) ==> true

(current-time-millis)

-- procedure -- org.llava

Read-Compile-Eval-Print-Loop

(-bt)

-- procedure -- org.llava

Prints a backtrace of the llava stack for the last exception. Note: the top of the stack is at the bottom of the trace.


(-jbt)

-- procedure -- org.llava

Prints a backtrace of the Java stack for the last exception. Note: the top of the stack is at the top of the trace.


(define-d ...)

-- syntax -- org.llava

Equivalent to define when defining generic and lambda procedures except procedures defined with define-d print procedure entry and exit values to the console. Exit value tracing indicates whether a normal value is returned or an exception has been thrown.


(set-define-d-indent! false-or-integer)

-- procedure -- org.llava

Controls the indentation of the call stack tracing of procedures defined with define-d. If false then no indentation. Otherwise tracing is indented the integer amount given.

Semantics

llava is statically scoped.

llava is dynamically typed.

llava is properly tail-recursive.

Arguments to llava procedures are passed by value.

Like Scheme, llava is a Lisp-1, meaning that functions and variables are stored in the same namespaces (which is different from Common Lisp, a Lisp-2, which uses different namespaces for functions and variables).

Syntax

llava uses a parenthesized prefix notation for programs and (other) data.

The -read procedure performs syntactic as well as lexical decomposition of the data it reads.

Immutable Syntax

The following llava syntax (i.e., special forms) is immutable.

From (or similar to) Scheme:

begin
define
define-final
lambda
let
letrec
quote
set!

From Java:

if

Lexical Conventions

llava is case-sensitive. For example, Foo is not the same identifier as FOO.

Identifiers

A sequence of letters, digits and "extended alphabetic characters" is an identifier. llava's extended alphabetic characters are identical with R5RS.

Comments

A semicolon (;) indicates the start of a comment. The comment continues to the end of the line on which the semicolon appears.

(-comment-)

-- syntax -- org.llava

A block comment is anything appearing inside the syntax: (-comment- ...).


(-package-)

-- syntax -- org.llava

A block comment. Recognized by org.llava.lib.LlavaDoc.


(-doc-)

-- syntax -- org.llava

A block comment. Recognized by org.llava.lib.LlavaDoc.

Other notations

. + - Used in numbers and identifiers, as in R5RS.

( ) Used for grouping and to notate lists, as in R5RS.

' Indicates literal data, as in R5RS.

` Indicates almost constant data, as in R5RS.

, ,@ Used in conjunction with backquote, as in R5RS.

" Used to delimit strings, as in R5RS.

\ Used in character constants and as an escape within string constants, as in R5RS.

true false These are the boolean constants.

#\ Introduces a character constants, as in R5RS.

#( Introduces a vector constant, as in R5RS.

Expressions

Primitive Expression Types

<variable>

-- syntax

An expression consisting of a identifier is a variable reference.

(quote <datum>)

-- syntax -- org.llava


(<operator> <operand1> ...)

-- syntax -- org.llava

A procedure call.


(lambda <formals> <body>)

-- syntax -- org.llava

A procedure definition.


(if <test> <consequent> <optional-alternate>)

-- syntax -- org.llava


(set! <variable> <expression>)

-- syntax -- org.llava


(begin <expression1> <expression2> ...)

-- syntax -- org.llava


(quasiquote <pp template>)

-- syntax -- org.llava

Backquote. Use ` , and ,@

Derived Conditionals

(cond ...)

-- syntax -- org.llava


(or ...)

-- syntax -- org.llava


(and ...)

-- syntax -- org.llava


(case ...)

-- syntax -- org.llava


(try <body> <catch> <finally>)

-- syntax -- org.llava

Example:

(try
 (/ 1 0)
 (catch (java.lang.Throwble t)
   (-print (s+ "Caught: " (toString t))))
 (finally
   (-print "finally")))

Binding Constructs

(let ...)

-- syntax -- org.llava


(let* ...)

-- syntax -- org.llava


(letrec ...)

-- syntax -- org.llava

Iteration

(do ...)

-- syntax -- org.llava

Procedures

Equivalence Predicates

(eq? obj1 obj2)

-- procedure -- org.llava

Equivalent to Java ==.

Handles null arguments.


(equal? obj1 obj2)

-- procedure -- org.llava

Equivalent to Java equals.

Handles null arguments.

Handles vector arguments.

Numbers

(= z1 z2 z3 ...)

-- procedure -- org.llava


(< x1 x2 x3 ...)

-- procedure -- org.llava


(> x1 x2 x3 ...)

-- procedure -- org.llava


(<= x1 x2 x3 ...)

-- procedure -- org.llava


(>= x1 x2 x3 ...)

-- procedure -- org.llava


(+ z1 ...)

-- procedure -- org.llava


(* z1 ...)

-- procedure -- org.llava


(- z1 ...)

-- procedure -- org.llava


(/ z1 ...)

-- procedure -- org.llava


(modulo n1 n2)

-- procedure -- org.llava


(| n1 n2 ...)

-- procedure -- org.llava

Bitwise OR.


(& n1 n2 ...)

-- procedure -- org.llava

Bitwise AND.

Booleans

(not obj)

-- procedure -- org.llava

Pairs and Lists

(pair? obj)

-- procedure -- org.llava


(cons obj1 obj2)

-- procedure -- org.llava


(car pair)

-- procedure -- reflect on Pair


(cdr pair)

-- procedure -- reflect on Pair


(-car pairOrNull)

-- procedure -- org.llava

Like car except returns null if given null.


(-cdr pairOrNull)

-- procedure -- org.llava

Like cdr except returns null if given null.


(setCar pair)

-- procedure -- reflect on Pair


(setCdr pair)

-- procedure -- reflect on Pair


(c????r pair)

-- procedure -- reflect on Pair

car, cdr, caar, cadr, cdar, cddr, caddr, cdddr


(first list)

-- procedure -- reflect on Pair

rest, first, second, third, fourth, firth, sixth


(null? obj)

-- procedure -- org.llava


(list obj ...)

-- procedure -- org.llava


(-list obj ...)

-- procedure -- org.llava

Alias for list. Useful to circumvent generic procedures.

(-list (new 'java.io.File "/tmp")) ==> (/tmp)

(length list)

-- procedure -- reflect on Pair


(append list ...)

-- procedure -- org.llava


(memq obj list)

-- procedure -- org.llava


(member obj list)

-- procedure -- org.llava

Symbols

(symbol? obj)

-- procedure -- org.llava


(string->symbol string)

-- procedure -- org.llava

Strings

(string-append string ...)

-- procedure -- org.llava


(s+ string ...)

-- procedure -- org.llava

Alias for string-append


(string->symbol string)

-- procedure -- org.llava

Vectors

(vector? obj)

-- procedure -- org.llava


(make-vector k . optionalFill)

-- procedure -- org.llava


(vector obj ...)

-- procedure -- org.llava


(vector-length vector)

-- procedure -- org.llava


(vector-ref vector k)

-- procedure -- org.llava


(vector-set! vector k obj)

-- procedure -- org.llava


(vector->list vector)

-- procedure -- org.llava


(list->vector vector)

-- procedure -- org.llava

Control Features

(apply proc list)

-- procedure -- org.llava


(map proc list . optionalList ...)

-- procedure -- org.llava

Examples:

(map (lambda (x) (+ x 1)) '(1 2 3)) ==> (2 3 4)
(map (lambda (x y) (+ x y)) '(1 2 3) '(0.1 0.2 0.3)) ==> (1.1 2.2 3.3)

(for-each proc list . optionalList ...)

-- procedure -- org.llava

Like map but does not collect results in a list.


(call/cc proc)

-- procedure -- org.llava

Only downward continuations supported.


(eval expression)

-- procedure -- org.llava

Input and Output

(-read . optional-java.io.Reader)

-- procedure -- org.llava

Reader that understands llava data types. Reads from stdin or the optional Reader argument.


(eof-object? obj)

-- procedure -- org.llava

Returns true if given an end-of-file read by read.


(load string)

-- procedure -- org.llava

Given a filename (relative or absolute), reads and evaluates the contents of the file with respect to the current package.


(-write obj . optional-java.io.PrinterWriter)

-- procedure -- org.llava

Equivalent to Java print except for special treatment of String, Character, vectors and quasiquote

Examples:

(write '("foo" #\c #(1 2))) prints ("foo" #\c #(1 2))

(-writeln obj . optional-java.io.PrinterWriter)

-- procedure -- org.llava

Equivalent to -write followed by -newline.


(set-vector-print-length! booleanOrInteger)

-- procedure -- org.llava

Controls the number of vector elements printed. true means all. false means 0.


(-print obj . optional-java.io.PrinterWriter)

-- procedure -- org.llava

Equivalent to Java print

Examples:

(-print '("foo" #\c #(1 2))) prints (foo c [Ljava.lang.Object;@988707)

(-println . optional-obj optional-java.io.PrinterWriter)

-- procedure -- org.llava

Equivalent to -print followed by -newline.

If called with no arguments it is equivalent to -newline.


(-newline . optional-java.io.PrinterWriter)

-- procedure -- org.llava


(-flush . optional-java.io.PrinterWriter)

-- procedure -- org.llava

Chapter 3. Libraries

org.llava.lib.Control

Misc., looping, mapping, case.

(case-eval-r ...)

-- syntax -- (import org.llava.lib.Control)

Like case except it explicitly calls eval on the right side.


(case-type ...)

-- syntax -- (import org.llava.lib.Control)

Like Common LISP typecase. The left forms should name class types.


(for <inits> <tests> <steps> <expression> ...)

-- syntax -- (import org.llava.lib.Control)


(map3 proc list)

-- procedure -- (import org.llava.lib.Control)

From Graham CL - p 263


(for-each3 proc list)

-- procedure -- (import org.llava.lib.Control)

From Graham CL - p 263


(tlet* <bindings> <body>)

-- syntax -- (import org.llava.lib.Control)

Like let* but <bindings> happen inside a try and <body> can contain catch and finally.

Known bug: if you bind a variable which shadows an outer variable and uses the value of the outer variable for its initial value the newly bound variable will always have false for a value:

(define (foo b)
  (list
   (tlet* ((b b))
     b
     (catch (java.lang.Exception e) -1))
   b))

(foo 3) ==> (false 3)

(while <test> <expression> ...)

-- syntax -- (import org.llava.lib.Control)

org.llava.lib.Exception

Procedures for handling or generating exceptions.

(apply-fail-on-false procedure list)

-- procedure -- (import org.llava.lib.Exception)

Identical to apply except it raises an exception if the result is false.

(apply (lambda (x) (pair? x)) '((1 . 2))) ==> true
(apply (lambda (x) (pair? x)) '(1)) ; throws exception

(error* obj ...)

-- procedure -- (import org.llava.lib.Exception)

Equivalent to:

(error (apply string-append (map toString (list obj ...))))

(ignore-errors thunk)

-- procedure -- (import org.llava.lib.Exception)

Calls thunk catching and ignoring all java.lang.Exceptions.

org.llava.lib.List

Useful list utilities.

(add-between obj list)

-- procedure -- (import org.llava.lib.List)

Returns a list with obj added between each element of the original list.


(build-list terminate-thunk step-thunk)

-- procedure -- (import org.llava.lib.List)

Example:

(let* ((lst '(1 2 3))
       (terminate? (lambda () (null? lst)))
       (step (lambda () (let ((result (* (car lst) 10)))
			  (set! lst (cdr lst))
			  result))))
  (build-list terminate? step))

(member-cadr obj list)

-- procedure -- (import org.llava.lib.List)

If obj is a member of list it returns the following element. Otherwise false.


(to-list obj)

-- procedure -- (import org.llava.lib.List)

Given is a list, string or vector it returns a list of obj's elements.

org.llava.lib.LlavaDoc

Generates package and procedure documentation in DocBook format.

(llava-doc source-dir destination-dir)

-- procedure -- (import org.llava.lib.LlavaDoc)

...

org.llava.lib.Macro

Utilities to help with writing macros.

(with-gensyms list-of-symbols expression ...)

-- procedure -- (import org.llava.lib.Macro)

From Paul Graham.

org.llava.lib.Program

Syntax for defining procedures and variables.

(define-with-setter name-and-args expression ...)

-- syntax -- (import org.llava.lib.Program)

Define a named function and a procedure to set that name. Useful from other namespaces when you cannot set dotted names.


(define-indirect-variable)

-- syntax -- (import org.llava.lib.Program)

Close over a free variable. Then set and access it via a named procedure.


(define-with-exc-hand ...)

-- syntax -- (import org.llava.lib.Program)


(define-with-keywords ...)

-- syntax -- (import org.llava.lib.Program)

org.llava.lib.String

Procedures to manipulate strings.

(list>string-with-space list)

-- procedure -- (import org.llava.lib.String)

Calls toString on each element of list. Then adds a blank space between each element. Then string-appends the stringified elements and blanks.

org.llava.lib.Thread

Starting and killing threads.

(kill-current-thread)

-- procedure -- (import org.llava.lib.Thread)

Calls deprecated stop on the current thread.


(start-new-thread thunk)

-- procedure -- (import org.llava.lib.Thread)

Executes thunk in a new thread.


(start-new-thread* expression ...)

-- syntax -- (import org.llava.lib.Thread)

Executes expression ... in a new thread.

org.llava.lib.Vector

Procedures for manipulating vectors.

(list>class-vector list-of-classnames)

-- procedure -- (import org.llava.lib.Vector)

Given a list of symbols or strings naming classes. Returns a vector of corresponding classes.


(list>typed-vector list)

-- procedure -- (import org.llava.lib.Vector)

Creates a vector of the type of the first element. Puts the elements of the list into the vector.


(vector-map proc vector)

-- procedure -- (import org.llava.lib.Vector)


(vector-for-each proc vector)

-- procedure -- (import org.llava.lib.Vector)

org.llava.lib.cl.Control

Common Lisp control features.

(setq variable obj)

-- syntax -- (import org.llava.lib.cl.Control)


(dotimes variable-and-limit expression ...)

-- syntax -- (import org.llava.lib.cl.Control)

org.llava.lib.cl.Macro

Common Lisp macros.

(defmacro name vars expression ...)

-- syntax -- (import org.llava.lib.cl.Macro)

org.llava.lib.cl.Symbol

Common Lisp symbols utilities.

(gentemp optional-prefix)

-- procedure -- (import org.llava.lib.cl.Symbol)

Generate a new interned symbol.


(gensym optional-prefix)

-- procedure -- (import org.llava.lib.cl.Symbol)

Generate a new uninterned symbol.

org.llava.lib.cl.Sequence

Common Lisp sequence procedures.

(remove obj list)

-- procedure -- (import org.llava.lib.cl.Sequence)

Uses equal? for comparison.


(remove-duplicates list)

-- procedure -- (import org.llava.lib.cl.Sequence)

Uses equal? for comparison.

org.llava.lib.io.FileWalker

Generic procedures to walk the contents of a file.

(file-walker-files input-filename output-filename)

-- procedure -- (import org.llava.lib.io.FileWalker)

...

org.llava.lib.java.Lang

Java operations.

(new-array class-or-class-name length)

-- procedure -- (import org.llava.lib.java.Lang)

Creates a new array of the given type.

org.llava.lib.reflect.Namespace

Procedures for looking at package namespaces and their contents.

(list-packages)

-- procedure -- (import org.llava.lib.reflect.Namespace)

Returns a list of package names for all packages that exist.


(current-package)

-- procedure -- (import org.llava.lib.reflect.Namespace)

Returns the name of the current package.


(find-package symbol-or-string)

-- procedure -- (import org.llava.lib.reflect.Namespace)

Given a package name. Returns matching package or null if it does not exist.


(list-imports optional-symbol-or-string)

-- procedure -- (import org.llava.lib.reflect.Namespace)

Given a package or package name. If no argument is given then uses the current package. Returns a list of package names imported into that package in search order.


(list-variables optional-symbol-or-string)

-- procedure -- (import org.llava.lib.reflect.Namespace)

Given a package or package name. If no argument is given then uses the current package. Returns a list of variable names contained in that package.


(contains? symbol-or-string optional-symbol-or-string)

-- procedure -- (import org.llava.lib.reflect.Namespace)

Given a variable name and an optional package or package name. Returns true if that variable exists in the given package. Otherwise false.


(which-package)

-- procedure -- (import org.llava.lib.reflect.Namespace)

Given a variable name. Returns the package name in which it exists if that package is imported by the current package. Otherwise false.


(which-package-all symbol-or-string)

-- procedure -- (import org.llava.lib.reflect.Namespace)

Given a variable name. Returns a list of package names for all packages that contain a variable of the given name.

org.llava.lib.reflect.Reflect

Reflective display and equality.

(display-class class-name-or-instance)

-- procedure -- (import org.llava.lib.reflect.Reflect)

Displays constructions, methods and fields.


(display-object obj)

-- procedure -- (import org.llava.lib.reflect.Reflect)

Displays field names and values.


(get-proxy-class ...)

-- procedure -- (import org.llava.lib.reflect.Reflect)


(new-invocation-handler ...)

-- procedure -- (import org.llava.lib.reflect.Reflect)


(new-proxy-instance ...)

-- procedure -- (import org.llava.lib.reflect.Reflect)


(reflect-equals obj1 obj2)

-- procedure -- (import org.llava.lib.reflect.Reflect)

Uses reflections to compare objects.

org.llava.lib.scm.List

Scheme list procedures.

(append! list list)

-- procedure -- (import org.llava.lib.scm.List)


(reverse list)

-- procedure -- (import org.llava.lib.scm.List)


(assoc obj alist)

-- procedure -- (import org.llava.lib.scm.List)

Uses equals for comparison.

(assoc '(1) '(((1) 1) (((2) 2)))) ==> ((1) 1)
(assoc '(3) '(((1) 1) (((2) 2)))) ==> false

(assq obj alist)

-- procedure -- (import org.llava.lib.scm.List)

Uses eq? for comparison.

(assq 'a '((a 1) (b 2))) ==> (a 1)
(assq 'c '((a 1) (b 2))) ==> false

org.llava.lib.scm.Predicate

Scheme type predicates.

(boolean? obj)

-- procedure -- (import org.llava.lib.scm.Predicate)


(char? obj)

-- procedure -- (import org.llava.lib.scm.Predicate)


(procedure? obj)

-- procedure -- (import org.llava.lib.scm.Predicate)


(string? obj)

-- procedure -- (import org.llava.lib.scm.Predicate)

org.llava.lib.scm.String

Scheme string procedures.

(string->list string)

-- procedure -- (import org.llava.lib.scm.String)

org.llava.lib.test.Test

llava test utilities.

(check)

-- procedure -- (import org.llava.lib.test.Test)


(begin-test optional-symbol-or-string)

-- procedure -- (import org.llava.lib.test.Test)


(end-test optional-symbol-or-string)

-- procedure -- (import org.llava.lib.test.Test)


(throw-exception-if-failures)

-- procedure -- (import org.llava.lib.test.Test)


(exit-if-failures)

-- procedure -- (import org.llava.lib.test.Test)


(tprintln obj)

-- procedure -- (import org.llava.lib.test.Test)

testBuiltins cannot use -println because it is running a llava that is not connected to System.out.


(dprintln obj)

-- procedure -- (import org.llava.lib.test.Test)


(toggle-print-results)

-- procedure -- (import org.llava.lib.test.Test)


(toggle-print-progress)

-- procedure -- (import org.llava.lib.test.Test)

org.llava.lib.xml.L2X

Transform a "lispy" version of XML (called "lxml") into angle bracket xml.

(l->x)

-- procedure -- (import org.llava.lib.xml.L2X)


(l->x-string)

-- procedure -- (import org.llava.lib.xml.L2X)


(l->x-files)

-- procedure -- (import org.llava.lib.xml.L2X)

Implementation

...

Appendices

Appendix A. Motivation

During the 80s and early 90s I was involved in designing and building Lisp systems. When funding for Lisp became scarce I switched to distributed computing and ended up working for SUN Microsystems on CORBA software in C++ (DOE/NEO). Then Java arrived. At SUN, our group's efforts in C++ were redirected towards Java.

Immediately, upon first using Java, I was struck by the fact that it was fun to program again (vis-a-vis the tedious nature of programming in C++). It was clear that the reason for this joy was Java's higher level ala Lisp. However, once I tasted that level again I was soon disappointed by Java since it lacked many features of Lisp which make working at that level fun and productive.

Then Per Bothner released Kawa, a version of Scheme in Java. Using Kawa I was able to program a little more interactively with Java but I kept running into missing library items. I was continually forced to choose between finding versions of btrees, hash tables, etc., in public-domain Scheme code, or making foreign-function interfaces to Java versions of the same.

I ended up doing more of the later. I automated this with an "import" macro which would automatically wrap all or selected methods of specified Java classes using Java reflection. However, I then kept running into the need to convert between Kawa/Scheme IO, strings, characters, etc., and Java IO, strings, characters, etc. When I wanted to define classes for use in Kawa I either had to write the classes in Java which I could import with my macro, or I could use Meroon or some other Scheme object system. However the Scheme objects did not interoperate with the Java objects so I was back to the non-interoperability of Kawa and Java types again. This lack of interoperability just kept cropping up every step of the way, particularly in exceptions. (I haven't kept track of Kawa, so many of these problems, problems for me at least, may be resolved. Plus, I definitely recommend Kawa where performance is a concern. Kawa is a great system.)

That's when I got the idea for llava.

Why not create a version of Java which uses Lisp syntax (or, more precisely, Lisp's lack of syntax) to write Java classes? Then extend that system to include a few special forms (lambda, set!, if, quote, define-syntax), a read-eval-print loop and support for incremental (re)definition to support interactive program development. In other words, a minimal Lisp system with complete interoperability with Java to leverage the Java Virtual Machine and growing Java class libraries.

Originally my name for llava was JIST: for Java + lIST. I called it JIST (not JISP), to emphasize the combination of Java and lIST capabilities and syntax, rather than give the impression of a Lisp system written in Java.

But JIST (or JISP) didn't sound right. So I went with LAVA: for Lisp + jAVA. But lava.org was already taken so I added an "l" - thus: llava (pronounced either "lava" - like the volcanic stuff - or "yava" - like in Spanish - your choice).

llava is not a Lisp/Scheme system written in Java. llava is access to Java via Lisp syntax and features. The philosophy of llava is: maximum leverage of Java—only add what is missing or cannot be done in Java (e.g., list "syntax" and library, repl, incremental (re)definition, macros).

Appendix B. Copyright and License

Copyright (c) 1997 - 2005 Harold Carr (http://haroldcarr.com/)

This work is licensed under a Creative Commons License

llava is not associated with Sun Microsystems.

Java is a trademark of Sun Microsystems.

Last Modified : Fri Aug 5 10:34:46 PDT 2005 by hcarr.