# Dynamic Functions in EK9

These are just functions, but rather than being declared in the *functions*
block they can be defined and used in any **scope**. They are by their nature 'anonymous' but can be
referenced as a *function delegate* and they must always extend an *abstract function*.

The main use of these *dynamic functions* is to provide a very light weight and easy mechanism to
provide specific and varied functionality. You could view these as similar to __lambdas__ in some ways.

But there is one significant and valuable difference to normal *functions*; *dynamic functions*
can (but don't have to) capture variables and can therefore hold state (a little like a closure).
This gives them different capabilities to normal *functions* as demonstrated in the following example.

This fact may go against the grain for many with a __functional__ background (you don't have to use them!).
They have real power and value when building stream pipelines; using *dynamic functions* where you
want to retain/collate state information as part of pipeline process rather than just depending on a single
'reduce' at the end of the pipeline gives you flexibility in processing.

### Example

This function example shows how standard
*functions* and *abstract functions* can be implemented. There is also
an example that shows how *dynamic functions*
can be used in stream pipelines (see 'nameMapping', 'dateMapping', 'recordMapping' and 'functionMapping').

The example below highlights how *dynamic functions* can provide a light weight alternative to declaring
*functions* in the functions block.

#!ek9 defines module introduction defines type List of mathOperation defines function mathOperation() as abstract -> x as Float y as Float <- result as Float defines program DynamicMathExample1() stdout <- Stdout() stdout.println("Math Dynamic Operation Example1") fixedValue <- 9.8 //You can use 'is' or 'extends', 'as' and 'function' are optional addFunction <- () is mathOperation as pure function result: x+y subtractFunction <- () extends mathOperation as pure result: x-y divideFunction <- () is mathOperation as pure result: x/y multiplyFunction <- () is mathOperation as pure result: x*y //Capture 'fixedValue' so it can be used in the dynamic function specialFunction <- (fixedValue) is mathOperation as pure result: (x+fixedValue) * y^fixedValue //Make a list of mathOperation functions (polymorphism of functions) for op in [addFunction, subtractFunction, divideFunction, multiplyFunction, specialFunction] stdout.println(`Result: ${op(21, 7)}`) DynamicMathExample2() stdout <- Stdout() stdout.println("Math Dynamic Operation Example2") fixedValue <- 9.8 //It is possible to delare the list with the dynamic functions in - if the function is a one liner ops <- [ () is mathOperation as pure (result: x+y), () is mathOperation as pure (result: x-y), () is mathOperation as pure (result: x/y), () is mathOperation as pure (result: x*y), (fixedValue) is mathOperation pure (result: (x+fixedValue) * y^fixedValue) ] for op in ops stdout.println(`Result: ${op(21, 7)}`) //EOF

The code above will produce the following output:

Math Dynamic Operation Example1 Result: 28.0 Result: 14.0 Result: 3.0 Result: 147.0 Result: 5.895375993827891E9 Math Dynamic Operation Example2 Result: 28.0 Result: 14.0 Result: 3.0 Result: 147.0 Result: 5.895375993827891E9

##### Explanation

The use of **pure** is useful as it makes it very clear that nothing is 'mutated'. If you are going to use
a functional approach or are very keen on immutability the use of **pure** is essential in EK9.

The add, subtract, divide and multiply functions are quite short and to the point, note that the incoming and returning
parameters do not need to be declared. They are just assumed. The syntax:

**addFunction <- () is mathOperation**

is just a declaration of a new function delegate 'addFunction' as a *function* that extends (**is**) 'mathOperation'.

The suffix syntax of **'as function'** is optional, 'addFunction' shows this the other functions omit
this syntax. This is developer choice but it is quite obvious that a new *dynamic function*
has been defined because it **is**/**extends** 'mathOperation' and that __is a function__.

The 'specialFunction' has a completely different mathematical operation; importantly it __captures__ a variable.
The variable must be named; it cannot be a literal such as **9.8**. It has to be named so that it can be
addressed in the function body. Any number of variables can be captured and used in the function body.

This is __similar__ (but not the same) to a lambda/closure in many ways, but the 'capturing' of
variables is explicit and not automatic like lambdas and closures.

##### Why two ways to define functions?

Some functions are widely useful and should therefore be named and reused. Others really are just useful in a few contexts and can therefore be 'anonymous'. But there are times when you want to hold state in functions or pass them back from higher order functions/classes and pass them around like variables.

The approach in EK9 gives maximum flexibility; albeit at the cost of variation in syntax. Initially EK9
only had *standard functions*, then it became obvious that *abstract functions* were essential.
Finally with the introduction of stream pipelines that concept of 'lambda' like lightweight functions
were needed, but so as not to distract from the pipeline and encourage reuse - they were designed to be
used via __delegates__. But as a compromise, a single line dynamic function can be wrapped in parenthesis.

When defining *dynamic functions* it is best to create them via higher functions and that way they can be unit tested.
Clearly for trivial dynamic functions you have to make the call on unit testing!

### Next Steps

As you would expect, if there are *dynamic functions*; there are Dynamic Classes.
These are sightly different in nature however (with good reason).

But the combinations of *abstract functions*, *standard functions* and *dynamic functions* provide
a polymorphic and type safe way to implement flexible/reusable functionality.