-
Notifications
You must be signed in to change notification settings - Fork 12
Function
Santanu Sinha edited this page Feb 3, 2022
·
7 revisions
Hope provides supports for functions to be used to generate values, partial values or parameters of other functions in both LHS or RHS of a Hope expression. A function may have zero or more parameters. Parameters can be hard coded values, functions, json pointer or json path that get evaluated during runtime.
final ObjectMapper mapper = new ObjectMapper();
final JsonNode node = mapper.readTree("{ \"a\" : 2, \"b\" : 3, \"c\" : 5 }");
Assert.assertTrue(
HopeLangEngine.builder()
.build()
.evaluate(""math.negate(math.sub(math.add(\"$.a\", \"$.b\", 7), 13)) == 1"", node));
A function call is always evaluated during evaluation phase even if all parameters are resolved even during parse time. This means that all type checking etc is done done only during evaluation phase and never during parse phase.
Clients might need to provide custom functions for use in Hope expressions.
The following details will come in handy when trying to implement a function:
- The function class need to derive from
HopeFunction
class - All implementations need to provide a name for the function that can be used in an expression. This is acheived by annotating the implementation with
@FunctionImplmentation(name)
. Functions without this annotation cannot be registered to Hope. - A function can accept zero or more parameters of Value type. What this means that core data types, arrays, json-pointers, json-paths and function calls can be passed as parameters to a function.
- Implementors can use static functions in
Converter
class to get evaluated values of parameters. Never assume that a value will not be evaluated at runtime. - A function must return a subclass of
Value
as response. -
Variable arguments are supported. This can be used to implement functions like math.sum(...) or math.prod(...). If a variable type param is used, the function implementation class must have only one argument of variable type. Check implementation of
math.sum()
in Sum.java to see example. - *Overloading of functions is achieved by having multiple constructors with differing number of arguments. See implementation of
str.substr
in SubStr.java to see this in action. - Hope will instantiate a copy of the function per eval, it is advisable to not use mutable statics members in the implementation code to keep everything thread safe
@FunctionImplementation("ss.blah")
public class Blah extends HopeFunction<StringValue> {
@Override
public StringValue apply(Evaluator.EvaluationContext evaluationContext) {
return new StringValue("blah");
}
}
public class CustomTest {
@Test
public void testBlah() {
final HopeLangEngine hope
= HopeLangEngine.builder()
.registerFunction(Blah.class) //Register class by class
.addPackage("org.ss.hope.customfunctions") //Register a package full of functions
.build();
JsonNode node = ...
Assert.assertTrue(hope.evaluate("ss.blah() == \"blah\"", node));
}
}