Apama 10.15.3 | Developing Apama Applications | Developing Apama Applications in EPL | Using Functional Operations in EPL | Partially bound functions
 
Partially bound functions
Partial function binding is a concept that allows you to bind some of the arguments to a function, resulting in a function with fewer (or no) arguments that can be executed later when the remaining arguments are supplied.
Often it is useful to bind all arguments except the final one, which is then supplied by the values from a sequence (or other functional container). For example, the following produces a sequence of ["Hello Bob", "Hello Alice"]:
Fn.map(["Bob", "Alice"], Fn.partial(Fn.concat, "Hello "))
This can be used to specialize a callback action by providing some of the arguments in advance, similar to how capture of locals works in languages with lambdas. Without partial function evaluation, if you want to capture locals in a callback, you would have to write an event type to wrap the local you wanted to capture and provide the function as an action on it:
event Multiplier { integer factor; action func(integer i) returns integer { return factor * i; } }
...
integer factor := 5;
Fn.map(container, Multiplier(factor).func);
As an alternative, Fn provides a function to partially satisfy function arguments and return an object which can be used in the place of a functor action to later evaluate with the full arguments. For example:
action mul(integer factor, integer i) returns integer { return factor * i; }
...
Fn.map(container, Fn.partial(mul, 5));
The partial stores the first argument and then map is called with the second argument, evaluating the function once all arguments are available.
If you want to bind arguments in a different order - that is, you want to provide the last argument in the partial and then execute it with an earlier argument - then you can use placeholder variables provided by the Fn.$(n) method. So for example, given the following action:
static action replaceString(string s, string needle, string replacement) returns string
you can call this with a map operator, using a placeholder to specify that the value from map should be the first argument:
log Fn.map(["Hi Bob", "Hi Alice"],
Fn.partial(replaceString,
[Fn.$(1), "Hi", "Hello"])
).valueToString(); // prints ["Hello Bob", "Hello Alice"]
The argument to Fn.$ specifies the nth argument to the resulting partial function. This is indexed starting at 1, so Fn.$(1) refers to the first argument, and so on. Any arguments which are provided to the resulting function which are not referred to by a placeholder are appended to all the specified arguments.
You can also store and directly execute a partially evaluated function with the exec function:
Partial p := Fn.partial(mul, 5);
p.exec(3);
You can also chain partials and stash multiple arguments using a sequence:
Fn.partial(fn, [1,2,3]).partial(4).exec(5); // executes fn(1,2,3,4,5)