Functions are one of the main components of op4j. They are implementations of the org.op4j.functions.IFunction<T,R> interface, being T the input type and R the result type.
For example: IFunction<String,Integer> defines a function which takes a String as input and returns an Integer.
Inside expressions, functions are executed by the exec(...) action or by any of its variants: map(...), execAsArray(...), etc.
op4j provides more than 200 functions out-of-the-box. They are usually obtained by calling static methods in function hub classes. For example:
Function<String,String> fn = FnString.toUpperCase();
FnString is one of the predefined function hub classes (most of them start with Fn), and the toUpperCase() static method returns a function which takes a String input and returns a String result (IFunction<String,String>).
All predefined functions, as well as functions defined with function expressions are org.op4j.functions.Function objects, which are an implementation of IFunction adding a special execute(T input) method for easily calling them even outside op4j expressions.
Let's see some random examples:
Function<String,String> fn = FnString.trim(); Function<String,Calendar> fn = FnString.toCalendar("dd/MM/yyyy"); Function<Number,BigDecimal> fn = FnNumber.toBigDecimal(2, RoundingMode.HALF_UP); Function<Iterable<Double>,Double> fn = FnDouble().avg(); Function<Iterable<Integer>,Integer> fn = FnInteger().max(); Function<String[],String[]> fn = FnArray.ofString().distinct();
As we can see, some function hub classes like FnArray are a little bit special because they require specialization (type parameterization), which is what is done with the ofString() method.
Let's see another example of specialization:
Type<User> type = ...; Function<List<User[]>,List<User>> fn = FnList.ofArrayOf(type).flattenArrays();
Functions can be created by means of Fn.on expressions:
Function<List<String>,List<Calendar>> fnParseStringDates = Fn.onListOf(Types.STRING).map(FnString.toCalendar("dd/MM/yyyy")).get();
As functions created with function expressions return org.op4j.functions.Function objects they can be easily called even outside op4j expressions:
List<Calendar> calendars = fnParseStringDates.execute(stringDates);
Creating a custom function without using a function expression is as simple as implementing the one-method IFunction interface:
public class MyFunction implements IFunction<Integer,String> { public String execute(Integer input, ExecCtx ctx) throws Exception { return "The input number is: " + input; } }
...which can also be done anonymously:
String result = Op.on(value).exec(new IFunction<Integer,String>() { public String execute(Integer input, ExecCtx ctx) throws Exception { return "The input number is: " + input; } }).get();