install

tutorials

- Java API

- Java + LISP

- Lisp Repl

- Assembler

Javadoc

Lisp manual

fun4j - functional programming for the JVM

The Lisp Read Eval Print Loop

The most simple way to interact with a Lisp system is through an interactive Read-Eval-Print Loop. Fun4J also comes with such a "REPL".

To start up the fun4j REPL just call java -jar fun4j.jar. If you are working in an IDE you could as well start up the class org.fun4j.Repl directly.

After starting up you are prompted with the follwoing welcom message:

Welcome to fun4j [1.0.x]
input: 

You can enter any lisp expression at the input prompt. See the next snippet for an example:

input: (+ 3 4)
elapsed time in msecs:0
value1: 7

The result of the computation is printed after a value<n>: label. The result of the computation is also bound to a global variable value<n>. So you can reuse the results of previous computations in new lisp expressions. See the following snippet for a simple example:

input: (* value1 10)
elapsed time in msecs:0
value2: 70 

Please have a look at the following interactive session:

input: (lambda (m n) (* m n))
elapsed time in msecs:15
value1: Example1(args) => args[0]*args[1][]
input: (value1 7)
elapsed time in msecs:0
value2: Example1(args) => args[0]*args[1][7]
input: (value2 6)
elapsed time in msecs:0
value3: 42

A lambda term (lambda (m n) (* m n)) is entered. The result of this expression is a compiled function. Each compiled functions maintains a string representation of its underlying AST which can be used for a human readable representation. This representation is printed out: value1: Example1(args) => args[0]*args[1][]

In the next line this function object is applied to the argument 7. As the original function has two arguments this function application is only a partial one, as one argument remains unbound. Thus the result of this application is a closure of the original function and the single argument 7: value2: Example1(args) => args[0]*args[1][7]

This closure is again a function, now one with only one unbound variable. Thus a call to the single argument 6 (value2 6) results in a multiplication of the bound arguments 6 and 7.

Useful functions

Enter (tracing true) to enable tracing of function calls. (tracing false) deactivates tracing. Here is a short example of tracing the factorial function:

input: (tracing true)
<-Example1: true
elapsed time in msecs:0
value1: true
input: (fac 5)
->Example2()
 ->fac2(5)
  ->fac2(4)
   ->fac2(3)
    ->fac2(2)
     ->fac2(1)
      ->fac2(0)
      <-fac2: 1
     <-fac2: 1
    <-fac2: 2
   <-fac2: 6
  <-fac2: 24
 <-fac2: 120
<-Example2: 120
elapsed time in msecs:0
value2: 120

By default fun4j uses BigIntegers for all int arithmetic operations. If you want to change this you can call (bigints false). It is important to note that this flag affects the Lisp parser and the Lisp compiler. If you change this flag in the middle of a session the Parser will generate Integer object while the compiled code still expects BigIntegers and vice versa. To avoid problems with this flag better use it before doing any compilations. Or reload all definitions like in the following example session:

input: (fac 32)
elapsed time in msecs:0
value1: 263130836933693530167218012160000000
input: (bigints false)
elapsed time in msecs:0
value2: true
input: (fac 32)
java.lang.Integer cannot be cast to java.math.BigInteger
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.math.BigInteger
	at fac1.applyInternal(Unknown Source)
	at org.fun4j.compiler.BaseFunction.apply(BaseFunction.java:81)
	at Example3.applyInternal(Unknown Source)
	at org.fun4j.compiler.BaseFunction.apply(BaseFunction.java:81)
	at org.fun4j.Repl.mainLoop(Repl.java:64)
	at org.fun4j.Repl.main(Repl.java:31)
input: (load 'lisp/init.lsp)
elapsed time in msecs:109
value4: true
input: (fac 32)
elapsed time in msecs:0
value5: -2147483648
input: 

In order to allow debugging and better understanding of the internal code generation you can call:

(debug-enable true)

Enabling this flag will advice the compiler to write .lsp files for AST-Pseudocode and .class files for the generated Java bytecode. It will also trigger the generation of JVM debugging bytecode.

You can use the functions (printlength n) and (printdepth n), n being an Integer value, to control the printing of lists. This feature is useful to avoid problems with huge or recursive lists.

input: (printlength 5)
elapsed time in msecs:0
value5: 10
input: (list 1 2 3 4 5 6 7 8 9)
elapsed time in msecs:0
value6: (1 2 3 4 5 6 ***)

Enter (quit) to terminate your interactive session.

input: (quit)
good bye...