PK - Chapter 5 Flashcards
What is a higher order function ?
A higher order function does one, or both, of the following:
- accepts another function as a parameter
- returns a function as its return value
fun foo(firstParam: String, someFunction: (String) -\> String) { println(someFunction(firstParam)) }
fun bar(firstParam: String): (String) -\> String = { println("The first parameter is $firstParam") }
foo(“FIRST”, bar() )
Why would you want a function
to return another function ?
There are 2 common reasons to have
a function return another function:
- you might want to initialize a function variable
in more than one place - you might want the function to use a when
to determine which function would be appropriate
to use based on current state
Create a variable that
contains a function.
val isEven: (Int) -> Boolean = modulo(2)
OR
val isEven: { k: Int -> k % 2 == 0 }
listOf(1,2,3,4,5,6).filter(isEven)
What is a closure ?
A function that has access to variables
and parameters defined in outer scopes.
It is said that they “close over” these
variables.
What is an anonymous function ?
- It looks similar to a normal function
definition, except the name is omitted
fun(a: String, b: String) : String = a + b - If the parameter type(s) can be inferred,
then that can also be omitted
fun(a) = a % 2 == 0
What is a top-level function ?
Top-level functions are defined outside the scope of a class or interface.
fun isEven(k) = k % 2 == 0 val intList = listOf(1,2,3,4,5,6) intList.filter { isEven(it) } // OR intList.filter(::isEven)
Create an extension function
on Int that identifies an odd number.
fun Int.isOdd() = this % 2 != 0 val intList = listOf(1,2,3,4,5,6) intList.filter { it.isOdd() } // OR intList.filter(Int ::isOdd)
Create an extension function
on Int that returns a to the power of b.
fun foo(a: Double, b: Double, f: (Double, Double) -\> Double) = f(a,b)
foo(2.0, 3.0, { a, b -\> Math.pow(a,b) }) // OR foo(2.0, 3.0, Math.pow)
Explain a bound function reference.
- a function reference that is bound
to a particular instance - created by placing an expression
before the “::” operator - this allows us to eliminate an argument
to the function
fun String.equalsIgnoreCase(other: String) =
this.toLowerCase() == other.toLowerCase()
val stringList = listOf("foo", "bar", "baz", "buz") stringList.filter("bar"::equalsIgnoreCase) // Instead of stringList.filter { (String:equalsIgnoreCase) ("bar", it) }
Explain a function-literal receiver.
- a function with a parameter defined
to accept a receiver when invoked - the receiver is provided inside the
body of the function
fun foo(fn: String.() -\> Boolean) { var someBoolean = "some string".fn() ... }
Explain inline functions ?
- functions introduce overhead because:
- they are instances of objects, so
they require an allocation in the heap - there are additional method invocations
to invoke the function
- they are instances of objects, so
- the inline keyword generates the bytecode
at the call site, eliminating the allocation in
the heap and the additional method invocations - the savings in overhead is most impactful in loops
- the cost is in the additional amount of code
generated, versus avoiding many allocations
in a tight loop - an inline function cannot be asigned to an
inlined variable - many standard library functions are inline
inline fun foo() { }
What is noinline and
when would you use it ?
* sometimes you do not want a function to be inlined * typically used when creating an inline higher-order function, but you don't want a function parameter to be inlined
inline fun foo(noinline fn: (Int) -> Boolean) { }
Explain function currying.
- currying is the process of transforming
a function that accepts multiple parameters
into a series of functions, each of which
accept a single function - currying is a technique that allows functions
with multiple parameters to work with other
functions that only accept single arguments - related to the concept of partial appliction,
where not all parameters are specified in
advance, returning a new function that
accepts the missing parameters
Why is function currying useful?
- when some parameters are available
in the current scope, but not every scope - when some parameters are available
in the current scope, but not all of them - to reduce the arity of a function, to match
a lower arity input type of another function
What is the arity of a function ?
The number of parameters.