Victor J. Reventos
// Imperative
fun evenNumbers(integers: List<Int>): List<Int> {
val result = mutableListOf<Int>()
for (i in integers) {
if (i % 2 == 0) {
result.add(i)
}
}
return result
}
// Declarative / Function
fun evenNumbers(integers: List<Int>): List<Int> {
// return integers.filter { i -> i % 2 == 0 }
return integers.filter { it % 2 == 0 }
}fun value(): Int {
return 10
}
fun add(x: Int, y: Int): Int = x + y
fun countCharacters(strings: List<String>): Int = strings
.map(String::length)
.sum()
fun countOccurences(names: List<String>): Map<String, Int> = names
.groupingBy { it }
.eachCount()class Impure {
private var counter = 1
fun value(): Int {
return counter++
}
fun add(x: Int, y: Int): Int {
return x + y + counter++
}
}
// Another example
fun sayHello(person: Person): String {
// Nasty side effect
person.setGreeted(true)
return "Hello " + person.getName()
}
In short, it does what the type signature says its going to do.
// referentially transparent
// no surprises
fun multiply(x: Int, y: Int): Int = x * y
// Not referentially transparent
// is not valid for y = 0 and it will throw an exception
fun divide(x: Int, y: Int): Int {
return x / y
}
// Where does it force me to handle an error?
fun doSomething(): Int {
// do work
// sneaky who knew I would give you a nasty side effect
// exceptions: the glorified GOTO statement.
throw RuntimeException()
}fun <T> lock(lock: Lock, block: () -> T): T {
lock.lock()
try {
return block()
} finally {
lock.unlock()
}
}
// usage
val result = lock(someLock) {
// use the shared resource here safely
}fun <T> time(block: () -> T, timeConsumer: (Long)-> Unit): T {
val startTime = System.nanoTime()
val value = block()
timeConsumer(System.nanoTime() - startTime)
return value
}
@Log4j2
class Timing {
fun doRealWork(): Int {
return 20 * 20
}
fun timeDoRealWork(): Int {
return time(this::doRealWork, { log.info("doRealWork took $it ns") })
}
}Is applying one function to the results of another: The result of f() is sent through g() It is written: (g º f)(x)
newFunction(x) = g(f(x))
import org.funktionale.composition.*
fun times2(x: Int) = x * 2
fun square(x: Int) = x * x
fun squareTimes2(x: Int) = (::square andThen ::times2)(x)
fun squareTimes4(x: Int) = (::square andThen ::times2 andThen ::times2)(x)
// see... LEGOS!
fun squareTimes2InHex(x: Int) = (::square andThen ::times2 andThen Integer::toHexString)
data class ImmutableDataClass(val name: String, val phone: String)
data class MutableDataClass(val name: String, var phone: String)data class Album(val title: String)
fun countTheNumberOfTitlesThatStartWithPop(albums: List<Album>): Long {
return albums
// transform Album -> String
.map(Album::title)
// filter - keep titles that start with "Pop"
.filter { it.startsWith("Pop") }
// fold - Accumulates value starting with [initial] value
// and applying [operation] from left to right to current
// accumulator value and each element.
// this could also be written using .count()
.fold(0) { acc: Int, s: String -> acc + 1}
.toLong()
}May the Function be with you.