2
2
.
.
5
5
.
.
5
5
F
F
u
u
n
n
c
c
t
t
i
i
o
o
n
n
v
v
s
s
L
L
a
a
m
m
b
b
d
d
a
a
v
v
s
s
C
C
l
l
o
o
s
s
u
u
r
r
e
e
F
F
u
u
n
n
c
c
t
t
i
i
o
o
n
n
v
v
s
s
L
L
a
a
m
m
b
b
d
d
a
a
v
v
s
s
C
C
l
l
o
o
s
s
u
u
r
r
e
e
Function is
block of code
that accepts Input Parameters
and returns a single value
To Declare a Function means to
specify block of code that should be executed when Function is called
specify Names and Data Types of Input Parameters (Names or indexes are used to reference Parameters)
specify Data Type of Return Value (or it is inferred by return value)
In Kotlin Function can be declared using following Programming Syntaxes
Lambda Expression declares Anonymous Function (Function that has no Name)
Anonymous Function Declaration declares Anonymous Function (Function that has no Name)
Named Function Declaration declares Named Function (Function that has a Name)
Closure is Object that has
a single Method
Properties which are all referenced from that Method
Function Declaration is used to create Class & Object Methods and blocks of code that need to be called multiple times.
Lambda Expression is used to declare Function that is used as Input Parameter or Return Value of another Function.
Closure is created
when Function needs to return a Function (together with values of referenced Variables from the enclosing Scope)
when Function is used as Input Parameter to another Function
L
L
a
a
m
m
b
b
d
d
a
a
E
E
x
x
p
p
r
r
e
e
s
s
s
s
i
i
o
o
n
n
s
s
Lambda Expression is Programming Syntax that allows us to
declare a block of code
that accepts Input Parameters
and returns a single value
To be able to call and execute that block of code we need to
store Lambda Expression into a Variable (or Constant or Function Input Parameter)
use that Variable's Name to call that code (can't use Named Parameters)
Unlike Functions, Lambda Expressions can't have Name which is why they are sometimes referred to as Anonymous
Functions. But since Lambda Expressions can be stored into Variables, and then we can use that Variable's Name to call
that Lambda Expression, the difference is negligible (as long as you don't care about Named Parameters during calls).
Lambda Expression
{ name:String, age:Int -> "$name is $age years old." }
Using Lambda Expressions to store Anonymous Function into Variable (and call it through Variable Name)
//DECLARE CLOSURE. STORE IT INTO VARIABLE
var closureVariable = { name:String, age:Int -> "$name is $age years old." }
var closureVariable = { name , age -> "$name is $age years old." }
//CALL CLOSURE THROUGH VARIABLE.
closureVariable ("John", 50) //Indexed Parameters
N
N
a
a
m
m
e
e
d
d
F
F
u
u
n
n
c
c
t
t
i
i
o
o
n
n
D
D
e
e
c
c
l
l
a
a
r
r
a
a
t
t
i
i
o
o
n
n
s
s
Function declaration is also a Programming Syntax that allows us to do the same as with Lambda Expression.
But in additional we can also
give the Name to that block of code
use that Name to call that block of code
use Named Parameters when calling that block of code (depending on the Language but Kotlin supports this)
If Lambda Expression and Function Declaration have the same Signature then you can store Reference to a Function into
the same Variable. Now you can call that Function in the same way as you would the Lambda Expression, by using that
Variable's Name (but without using Named Parameters).
You can think of Function as a Wrapper around Lambda Expression allowing you to assign a name to a Lambda Expression
and call Lambda Expression with Named Parameters. But when you store Function reference into a Variable then when
using this Variable your Function starts behaving the same as an Lambda Expression (you can't have Named Parameters).
Function Declaration
//DECLARE FUNCTION.
fun greet (name:String, age:Int = 20) : (String) { return("$name is $age years old.") } //Block Syntax
fun greet (name:String, age:Int) : (String) = "$name is $age years old." //Assignment Syntax
//CALL FUNCTION.
greet(name="John", age=50) //Named Parameters
greet("John" , 50) //Indexed Parameters
Such Variables need to be declared to accept Function Data Type specific to the Closure we want to store.
Function Data Type (also known as Signature) defines Data Types of Input Parameters and Return Value.
These can be inferred from the Closure Signature (so you don't need to explicitly specify them in Variable declaration).
But once Closure is stored into Variable, this Variable is set to accept only this Function Data Type so you can't store in it
other Data Types or Functions with different Signatures.
Variables that accept Function Data Type can store Closure, Function & Anonymous Function with the same Signature.
To store Function into Variable you actually have to store a reference to a Function using "::" operator as a prefix before
the Function name: closureVariable = ::greet. You can now use Variable to call Function. But you can't use Named
Parameters anymore because this information is not stored into Variable (it is part of Function Declaration).
Declare Variable that holds specific Function Data Type
var closureVariable : (String, Int) -> (String) //Function that accepts 2 Parameters & returns String
Store Function Reference into Variable
//DECLARE FUNCTION.
fun greet (name:String, age:Int) : (Unit) { println("$name is $age years old.") }
//DECLARE VARIABLE. (THAT HOLDS SPECIFIC FUNCTION DATA TYPE)
var closureVariable : (String, Int) -> (Unit)
//STORE REFERENCE TO FUNCTION INTO VARIABLE.
closureVariable = ::greet
//CALL FUNCTION THROUGH VARIABLE (NO NAMED PARAMETERS).
closureVariable("John", 20)
C
C
l
l
o
o
s
s
u
u
r
r
e
e
Closure Object (or just Closure for short) is a special type of Object that has following basic characteristics
it has a single public Method (optional private Methods from other inner Functions)
it only has Properties that are referenced from that Method (optional Properties referenced from private Methods)
it is created when
returning a Function from another Function
using Function as Parameter into another Function
When Closure is created
Function that is being returned or used as parameter is added as a Method to the Closure Object
enclosing Function Variables, that are referenced by that Function, are stored as Properties with their current Values
Such Closure Object can then be passed around and its Method can be freely executed at any time since Closure contains
all Variables used by the Method. Multiple executions change their Values?
So Closure Objects are implicitly created to allow this kind of functionality. You could rewrite that Functionality by
explicitly creating Class, Object, Properties and Method and explicitly pass it around.
Method returned inside Closure Object is said to be partially applied since Properties already have some value. To get the
final result from the method you need to provide values for its Input Parameter (this is the part that is missing).
Outer Function behaves exactly like a Class. By calling it you get its instances - Closure Objects that contain
Outer Function Variables as its Properties (referenced by either returned or other inner Functions)
returned Function as its public Method (so that it can be called from outside)
all other Inner Functions as its private Methods (since they might be referenced from the returned public Method)
Function that returns Closures
//===========================================================================================================
// FUNCTION: factory
//===========================================================================================================
fun factory (name:String, age:Int) : ( (Int) -> String ) {
fun greet(weight: Int) : (String) {
return "$name is $age years old and $weight kg heavy."
}
return ::greet
}
//===========================================================================================================
// FUNCTION: main
//===========================================================================================================
fun main() {
//DECLARE VARIABLE. (THAT HOLDS CLOSURE)
var greet : (Int) -> (String)
//GET CLOSURE.
greet = factory("John", 20) //CLOSURE PROPERTIES: name="John", age=20
//CALL CLOSURE METHOD.
var result = greet(150)
//DISPLAY RESULT.
println(result)
//GET ANOTHER CLOSURE.
var greet2 : (Int) -> (String) = factory("Bill", 50)
println(greet2(100)) //DIFFERENT CLOSURE COPY: name="Bill", age=50
println(result) //PREVIOUS CLOSURE IS UNCHANGED
}
Here we implement the same behaviour by declaring a class that creates Closure-like Object that only has one Method
and Properties referenced by that Method (like Input Parameters to Outer Function/Class Constructor).
Returned Method looks the same but the way we call it from the Closure if different then when calling from Object.
Also Variable that stores Closure accepts Function Data Type and the one that stores Object accepts Class Data Type.
If outer Function had some additional code you would transfer that inside init{} blocks of the Primary Constructor.
Class that returns Closure-like Objects
//===========================================================================================================
// FUNCTION: factory
//===========================================================================================================
class Factory (var name:String, var age:Int) {
fun greet(weight: Int) : (String) {
return "${name} is $age years old and $weight kg heavy."
}
}
//===========================================================================================================
// FUNCTION: main
//===========================================================================================================
fun main() {
//DECLARE VARIABLE. (THAT HOLDS OBJECT)
var greet : Factory
//GET OBJECT.
greet = Factory("John", 20) //OBJECT PROPERTIES: name="John", age=20
//CALL OBJECT METHOD.
var result = greet.greet(150)
//DISPLAY RESULT.
println(result)
//GET ANOTHER OBJECT.
var greet2 : Factory = Factory("Bill", 50)
println(greet2.greet(100)) //DIFFERENT OBJECT: name="Bill", age=50
println(result) //PREVIOUS OBJECT IS UNCHANGED
}
Output
John is 20 years old and 150 kg heavy.
Bill is 50 years old and 100 kg heavy.
John is 20 years old and 150 kg heavy.
H
H
i
i
g
g
h
h
e
e
r
r
-
-
O
O
r
r
d
d
e
e
r
r
F
F
u
u
n
n
c
c
t
t
i
i
o
o
n
n
s
s
a
a
n
n
d
d
L
L
a
a
m
m
b
b
d
d
a
a
s
s
[
[
R
R
]
]
Kotlin Functions are First-Class Citizens which means that they can be
assigned to Variables
passed as Input Parameters to other Functions
returned from other Functions
Higher-Order Function is function that
returns Function
takes Functions as Input parameter