Reflex Modules - RapturePlatform/Rapture GitHub Wiki

Modules

Reflex has the concept of modules that can be used to extend the functionality of Reflex through custom Java code that can be deployed alongside the environment. In this way application developers can create (or link to) more complex concepts and can interact with those libraries through normal Reflex scripts. As an example, in a Financial services application using Reflex the complete analytics library was exposed to Reflex users using this technique.

Use in Reflex

In Reflex a module is referenced using an import statement. This statement takes the following form:

import "classname" as "modulename" [with ( parameters ) ];

The classname refers to a Java class that is on the classpath loaded by Reflex, and the module name is an alias for this module that is used later on in scripts. The classname can omit 'reflex.module' if the class is in that package already. The module name will be converted to a normal Java convention of having first letter capitalization. The module can be initialized with parameters if necessary. To call a function in a module a script writer uses the $ prefix on the module name, like in the example below:

import testModule as test;

answer = $test.addOne(5);
assert(answer == 6);

This example refers to a testModule that will be explored in later sections.

Creating a module

Classes that are referred to in import statements must implement the reflex.importer.Module interface. This is reproduced below:

public interface Module {
    ReflexValue keyholeCall(String name, List<ReflexValue> parameters);
    boolean handlesKeyhole();
    boolean canUseReflection();
    void configure(List<ReflexValue> parameters);   
    void setReflexHandler(IReflexHandler handler);
}

There are two ways a developer can create a module -- using a keyhole interface and using reflection. A module could support both but would normally support just one. Reflection is preferred for ease of development and rapid extension at a small cost of Java reflection.

Keyhole module

A keyhole module would return true for the method handlesKeyhole. If a module returns true to this method Reflex will invoke the keyholeCall method for each module method invocation in a Reflex script. In the example above, a call to $test.addOne(5) would be translated into the following call:

List<ReflexValue> params = new ArrayList<ReflexValue>();
params.add(new ReflexValue(5));
ReflexValue result = module.keyholeCall("addOne", params);

In this way the implementation of the keyholeCall method must test the value of the name parameter to switch to the appropriate implementation.

Reflection module

A reflection module would return true for the method canUseReflection. If a module returns true to this method Reflex will look for a method with a very specific signature in the class implementation of the module. If that method exists it will be invoked. The signature is for a method that returns a ReflexValue and takes a single List<ReflexValue> parameter. As an example, the implementation of the testModule demonstrated above could be completely implemented by the following Java class:

package reflex.module;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import reflex.IReflexHandler;
import reflex.ReflexException;
import reflex.importer.Module;
import reflex.value.ReflexValue;

public class TestModule implements Module {

    @Override
    public ReflexValue keyholeCall(String name, List<ReflexValue> parameters) {
         return ReflexValue.VOID;
    }

    @Override
    public boolean handlesKeyhole() {
        return false;
    }

    @Override
    public boolean canUseReflection() {
       return true;
    }

    @Override
    public void configure(List<ReflexValue> parameters) {
    }

    @Override
    public void setReflexHandler(IReflexHandler handler) {
    }

    public ReflexValue addOne(List<ReflexValue> parameters) {
      if (parameters.size() != -1) {
          throw new ReflexException(-1, "addOne needs one parameter!");
      }
      Integer v = parameters.get(0).asInt();
      return new ReflexValue(v.intValue() + 1);
    }
  }

In the listing above we check the size of the parameters and throw a ReflexException if incorrect, and then use simple mathematics to return the result. Not that the asInt method on ReflexValue will throw an exception if the value passed is not an integer (or cannot be coerced to an integer) and this is exactly the behavior we want -- Reflex Exceptions are handled correctly by the interpreter and can be caught by \Reflex exception handlers.

Built-in modules

Reflex has a number of built-in modules that have been created to extend Reflex using commonly used third party (and open source) libraries. All are implemented as reflection based modules.

Statistics module

The statistics module draws on the Apache Commons Math library. The main function computes the statistics associated with a list of values and is called "statistics". It returns a map with three values, the "mean", the "std" (standard deviation) and "median" (the value of the 50th percentile).

The other three functions in the module work with "Frequency" objects. A frequency object is created using the frequency function - it returns a special Reflex Value that can be passed into the other two methods as the first value. The other two methods calculate the number of values that match the value passed (frequency_count) and the cumulative percentage of values up to a value (frequency_cum_pct). This is best illustrated by example:

import reflexStatistics as stat;

points = [ 1,2,3,4,5,6,7,8,9,10,100];

res = $stat.statistics(points);

println("Result is " + res);

multiplePoints = [ 1,2,1,1,1,1,2,1,2,4,5,1,2,3,5];

freq = $stat.frequency(multiplePoints);

println("Count of 1 in frequency is " + $stat.frequency_count(freq, 1));

for i = 1 to 5 do
   println("CumPct at " + i + " is " + $stat.frequency_cum_pct(freq, i));
end

The result of running this script would yield the following output:

Result is {median=6.0, std=28.637229424141385, mean=14.09090909090909}
Count of 1 in frequency is 7
CumPct at 1 is 0.4666666666666667
CumPct at 2 is 0.7333333333333333
CumPct at 3 is 0.8
CumPct at 4 is 0.8666666666666667
CumPct at 5 is 1.0

Gamma module

The Gamma module uses the Apache Commons Math library to compute values relating to the Gamma function and its derivatives.

Gamma function

The gamma function (gamma) takes zero or one parameter. In its no parameter form, it returns the value of the Euler-Mascheroni constant (also known as Euler's constant), and referred to as gamma. With one parameter it reurns the gamma function on the parameter.

DiGamma function

The digamma function (digamma) takes one parameter and returns the digamma function on the parameter.

TriGamma function

The trigamma function (trigamma) takes one parameter and returns the trigamma function on the parameter.

Erf module

The Erf module uses the Apache Commons Math library to compute Error Function values. It has two functins - erf returns the error function of its parameter, and erfc returns the error function coefficient of its parameter.

Math module

The math module provides standard support through the Java Math package. The functions exposed are shown in the table below:

Function Parameters Description
pi none Returns the constant pi
e none Returns the constant epsilon
abs value Returns the absolute value of a number
acos value Returns the arc-cosine of the number
asin value Returns the arc-sine of the number
atan value Returns the arc-tangent of the number
atan2 x,y Returns the arc-tangent "2 parameter" result of the (x,y) values passed
cbrt value Returns the cube root of the number
ceil value Returns the value rounded up to the nearest integer
cos value Returns the cosine of the value in radians
cosh value Returns the hyperbolic cosine of the value
exp value Returns epsilon raised to the power of the value
expm1 value Returns epsilon^x - 1
floor value Returns the value rounded down to the nearest integer
hypot x,y Computes sqrt ( x^2 + y^2 )
log value Computes the natural logarithm of the value
log10 value Computes the base-10 logarithm of the value
log1p x Computes log(1+x)
max x,y Returns the maximum of x or y
min x,y Returns the minimum of x or y
pow x,y Returns x^y
sin value Returns the sine of the angle in radians
sinh value Returns the hyperbolic sine
sqrt value Computes sqrt x
tan value Computes the tangent of the angle in radians
tanh value Computes the hyperbolic tangent
degrees value Converts radians to degrees
radians value Converts radians to degrees

Back to Overview