Note: The LJRI is only available for the Java implementation, and has no analogue in the C implementation.

Lavender Java Runtime Interface

The Lavender Java Runtime Interface (LJRI) enables one to define Lavender functions within the JVM language family. These functions may then be loaded and called from Lavender code. Functions created with LJRI have full access to Lavender functions, and visa-versa.

Example

The example given below defines a function test:addTo that takes in one argument and returns a function that adds it to another argument.

public class Test {

    @LavenderFunction("test:addTo")
    public LFunction addTo(LEnv env, LFunction b) {
    
        LFunction plus = env.getFunction("i_:+");
        return env.capture(plus, b);
    }
}
It is equivalent to the following Lavender code. @namespace test
def addTo(b) => def(a) => a + b
After the function is loaded, it can be used within Lavender the same as any Lavender function.

Creating Functions for LJRI

Functions using the LJRI are defined in normal Java classes. The class in question must have a publicly accessible constructor that takes either no arguments or a single argument of type LEnv. This constructor is called to initialize the object before any functions are loaded. @LavenderFunction("namespace:name")
public LFunction name(LEnv env, LFunction arg1, ...) { ... }
LJRI functions are instance methods annotated with the @LavenderFunction annotation. In addition to telling the LJRI that this function is a Lavender function implementation, the value of the annotation gives the name of the Lavender function to create for this function. Fuctions must additionally return the type LFunction and take parameters of type LFunction except for the first parameter, which is always of type LEnv. LJRI functions must not throw exceptions. If an LJRI function throws an exception, the runtime will terminate with a fatal linkage error.

LJRI Methods

All interactions with the Lavender runtime are done through the LEnv object passed to each function. This object contains methods for getting and using Lavender functions, binding values to a function, and converting between Lavender functions and Java types. These functions are documented in the LJRI source code in addition to this page. public LFunction getFunction(String name); Retrieves the Lavender function with the specified qualified name. The given name must be prefixed with either u_ for a prefix function or i_ for an infix function. public LFunction capture(LFunction func, LFunction... args); Returns a Lavender function that binds the given arguments to the last parameters of the given function. The number of arguments passed must be no more than the number of parameters taken by the function. public LFunction apply(LFunction func, LFunction... args); Returns the result of calling the given function with the given arguments. The number of arguments must exactly match the arity of the function, or else the Lavender NaN value is returned. public LFunction wrap(Object obj); Wraps the specified object in a Lavender function. This allows for any Java object to be used as a value in Lavender. While Lavender function cannot access the Java object directly, function using the LJRI may access the object using the unwrap method. public <T> T unwrap(LFunction f, Class<T> cls); Unwraps the specified Lavender function and returns the wrapped Java object. This function checks that the argument f actually wraps a Java object of the specified class, and returns null if this is not the case. Code using this method should check the return value.