16 — Advanced

Functions

Functions in rulii are like Actions but they return a value. They support 0 to 10 parameters (via NoArgFunction through DecFunction), and parameter names are matched to bindings automatically, just like conditions and actions.

Creating Functions

import static org.rulii.model.function.Functions.function;

// No parameters
Function<String> greeting = function(() -> "Hello World!");
String result = greeting.apply(Bindings.builder().standard());
// result == "Hello World!"

// With parameters (matched by name to bindings)
Function<String> fullName = function(
    (String firstName, String lastName) -> firstName + " " + lastName);
String name = fullName.apply(firstName -> "Alice", lastName -> "Smith");
// name == "Alice Smith"

Parameter Arity

rulii provides typed functional interfaces for 0 through 10 parameters:

NoArgFunction<R>

Zero parameters, returns R

UnaryFunction<A, R>

One parameter, returns R

BiFunction<A, B, R>

Two parameters, returns R

TriFunction ... DecFunction

Three through ten parameters

Use as RuleSet Result Extractor

RuleSet<String> ruleSet = RuleSet.builder()
    .with("MyRules")
    .rule(/* ... */)
    .resultExtractor(function((String name) -> "Result for " + name))
    .build();

Function Composition

Functions support composition via compose() and andThen():

compose(f, bindingName)

Apply f first, then this function

andThen(f, bindingName)

Apply this function first, then f

Function<Integer> addOne = function((Integer x) -> x + 1);
Function<Integer> multiplyByTwo = function((Integer value) -> value * 2);

// compose: apply addOne first, then multiplyByTwo
Function<Integer> composed = multiplyByTwo.compose(addOne, "value");
// (5 + 1) * 2 = 12

// andThen: apply multiplyByTwo first, then addOne
Function<Integer> chained = multiplyByTwo.andThen(addOne, "value");
// (5 * 2) + 1 = 11