Feather2 / documentation / FunctionTypes.md
Function Types
Function Types are a feature not seen in Java (AFAIK).
They are similar in spirit to lambdas, but the implementation is much simpler.
Let's take a look at an example :
class Foo {
// Nothing weird here yet!
func plus( a : double, b : double ) = a + b
func minus( a : double, b : double ) = a - b
// This is odd.
var myFunction = ::plus
func applyFunction( a : double, b : double ) : double {
// This looks simple, but `myFunction` is a `var`, not a `func` or `meth`.
return myFunction( a, b )
}
}
myFunction
is a field, whose type is a Function
, which takes two double
arguments, and returns a double
.
We could have explicitly stated the type in the var
definition :
var myFunction : (double, double)->double = ::plus
We can call (invoke) a Function
just like we would a regular fun
:
myFunction( 1, 2 )
The result is obviously 3
, when myFunction
== ::plus
.
But myFunction
is a var
, so we could change it to ::minus
, or
any other function with the same argument types and return type.
A function can be treated like any other object.
It can be passed as an argument to a func
or meth
, stored in fields/lists/arrays etc.
Curried Functions
Currying a function means we give one or more arguments to the Function
,
without invoking the Function
.
For example, we can curry myFunction
like so :
val myCurriedFunction = myFunction.curry( 4 )
myCurriedFunction
is also a Function
, but as the first parameter is
already given, myCurriedFunction
now only has a single argument.
We could have explicitly stated its type like so :
val myCurriedFunction : (double)->double = myFunction.curry( 4 )
To invoke it :
myCurriedFunction( 2 )
The result is 6 (4+2), assuming myFunction
is ::plus
.
Note that myCurriedFunction
is NOT the same type as myFunction
,
because they have different arguments.
meth vs func
In the example above the ::plus
is a func
.
We can also use methods (meth
). In which case, the first argument to the Function
is the instance of the class.
How it works
Function
is a regular Java class in the Feather runtime.
When a Function
is created, it is passed a Java Method
(from the java.lang.reflect
package)
Invoking the function calls Method.invoke
.
Differences with Java/Kotlin Lambdas
Functions
are simpler. They only have access to their parameters.Functions
ultimately use plain oldfunc
ormeth
, you cannot (yet) create aFunction
from an in-line expression or block of code.
Lambdas are much more powerful, because they don't have either of these limitations.
However, there's no simple equivalent of currying with lambdas.
Why?
Why did I implement Functions
, when lambdas
are more powerful, and easy to use?
Quite frankly, lambdas
are really tricky to implement, whereas Functions
are dead easy!
I fondly remember using pure functional languages, where functions as first-class-citizens is the norm, and currying is common. So I wanted to see how this could work in Feather.