Changeset 13335

06/16/11 14:56:43 (10 years ago)
Mark Evenson

Fold freestanding documentation into the Manual.

1 deleted
1 edited


  • trunk/abcl/doc/manual/abcl.tex

    r13334 r13335  
     80\subsubsection{Lisp FFI}
     82FFI stands for "Foreign Function Interface", which is the way the
     83contemporary Lisp world refers to methods of "calling out" from Lisp
     84into "foreign" langauges and envrionments.  This document describes
     85the various ways that one interacts with Lisp world of Abcl from Java,
     86considering the hosted Lisp as the "Foreign Function" that needs to be
     90\subsubsubsection{Calling Lisp from Java}
     92Note: As the entire ABCL Lisp system resides in the org.armedbear.lisp
     93package the following code snippets do not show the relevant import
     94statements in the interest of brevity.
     96Per JVM, there can only ever be a single Lisp interpreter.  This is
     97started by calling the static method `Interpreter.createInstance()`.
     100Interpreter interpreter = Interpreter.createInstance();
     103If this method has already been invoked in the lifetime of the current
     104Java process it will return null, so if you are writing Java whose
     105lifecycle is a bit out of your control (like in a Java servlet), a
     106safer invocation pattern might be:
     109Interpreter interpreter = Interpreter.getInstance();
     110if (interpreter == null) {
     111  interpreter = Interpreter.createInstance();
     117The Lisp `EVAL` primitive may be simply passed strings for evaluation,
     118as follows
     121String line = "(load \"file.lisp\")";
     122LispObject result = interpreter.eval(line);
     126Notice that all possible return values from an arbitrary Lisp
     127computation are collapsed into a single return value.  Doing useful
     128further computation on the `LispObject` depends on knowing what the
     129result of the computation might be, usually involves some amount
     130of instanceof introspection, and forms a whole topic to itself
     131(c.f. [Introspecting a LispObject](#introspecting)). 
     133Using `EVAL` involves the Lisp interpreter.  Lisp functions may be
     134directly invoked by Java method calls as follows.  One simply locates
     135the package containing the symbol, then obtains a reference to the
     136symbol, and then invokes the `execute()` method with the desired
     140    interpreter.eval("(defun foo (msg) (format nil \"You told me '~A'~%\" msg))");
     141    Package pkg = Packages.findPackage("CL-USER");
     142    Symbol foo = pkg.findAccessibleSymbol("FOO");
     143    Function fooFunction = (Function)foo.getSymbolFunction();
     144    JavaObject parameter = new JavaObject("Lisp is fun!");
     145    LispObject result = fooFunction.execute(parameter);
     146    // How to get the "naked string value"?
     147    System.out.prinln("The result was " + result.writeToString());
     150If one is calling an primitive function in the CL package the syntax
     151becomes considerably simpler if we can locate the instance of
     152definition in the ABCL source, we can invoke the symbol directly.  To
     153tell if a `LispObject` contains a reference to a symbol.
     156    boolean nullp(LispObject object) {
     157      LispObject result = Primitives.NULL.execute(object);
     158      if (result == NIL) {
     159        return false;
     160      }
     161      return true;
     162   }
     166/subsubsubsection{Introspecting a LispObject}
     168We present various patterns for introspecting an an arbitrary
     169`LispObject` which can represent the result of every Lisp evaluation
     170into semantics that Java can meaniningfully deal with.
     172/subsubsubsubsection{LispObject as \java{boolean}}
     174If the LispObject a generalized boolean values, one can use
     175\java{getBooleanValue()} to convert to Java:
     178     LispObject object = Symbol.NIL;
     179     boolean javaValue = object.getBooleanValue();
     182Although since in Lisp, any value other than NIL means "true", the
     183use of Java equality it quite a bit easier and more optimal:
     186    boolean javaValue = (object != Symbol.NIL);
     189/subsubsubsubsection{LispObject is a list}
     191If LispObject is a list, it will have the type `Cons`.  One can then use
     192the `copyToArray[]` to make things a bit more suitable for Java
     196    LispObject result = interpreter.eval("'(1 2 4 5)");
     197    if (result instanceof Cons) {
     198      LispObject array[] = ((Cons)result.copyToArray());
     199      ...
     200    }
     203A more Lispy way to iterated down a list is to use the `cdr()` access
     204function just as like one would traverse a list in Lisp:;
     207    LispObject result = interpreter.eval("'(1 2 4 5)");
     208    while (result != Symbol.NIL) {
     209      doSomething(;
     210      result = result.cdr();
     211    }
Note: See TracChangeset for help on using the changeset viewer.