JVM technologies Spring certified trainer 4+ years with Scala 2+ years with Kotlin funKTionale KotlinPrimavera RxKotlin original developer and team leader* NOT an expert on functional programming * I hit “Merge” and “Release” buttons
0 1L -> 1 else -> { var a = 0L var b = 1L var c = 0L for (it in 2..n) { c = a + b a = b b = c } c } } fun functionalFib(n: Long): Long { fun go(n: Long, prev: Long, cur: Long): Long { return if (n == 0L) prev else go(n - 1, cur, prev + cur) } return go(n, 0, 1) } fun tailrecFib(n: Long): Long { tailrec fun go(n: Long, prev: Long, cur: Long): Long { return if (n == 0L) prev else go(n - 1, cur, prev + cur) } return go(n, 0, 1) } fib(93)* 0μs 30000μs 60000μs 90000μs 120000μs fib functional tailrec Error Value 110.028 115.192 97.997 0,003 0,012 0,013 0,013 0,012 0,003 *Calculated with JMH, SampleTime mode
= JavaSparkContext(conf) val spam = sc.textFile("spam.txt") val ham = sc.textFile("ham.txt") val tf = HashingTF(10000) val posExamples = ham.map { LabeledPoint(1.0, tf.transform(listOf(it.split(" ")))) } val negExamples = spam.map { LabeledPoint(0.0, tf.transform(listOf(it.split(" ")))) } val trainData = posExamples.union(negExamples) trainData.cache() val model = LogisticRegressionWithLBFGS().run(trainData.rdd()) } import org.funktionale.currying.curried fun main(args: Array<String>) { val conf = SparkConf().setMaster("local[*]").setAppName("ML") val sc = JavaSparkContext(conf) val spam = sc.textFile("spam.txt") val ham = sc.textFile("ham.txt") val tf = HashingTF(10000) val labeling = { label: Double, email: String -> LabeledPoint(label, tf.transform(listOf(email.split(" ")))) } val curried = labeling.curried() val posExamples = ham.map(curried(1.0)) val negExamples = spam.map(curried(0.0)) val trainData = posExamples.union(negExamples) trainData.cache() val model = LogisticRegressionWithLBFGS().run(trainData.rdd()) }
of a meaningful value Examples of meaningful value • Succesful operation (no exceptions) • An existent value (record in DB) • An useful value (non-empty list)
same type defined by convention indexOf(x) will return -1 if x doesn’t exists in the structure (Array, List) • Is not mandatory to check • Based on oral tradition An exception Spring’s JdbcTemplate will throw an EmptyResultDAE if no record is available* • Runtime Exception • Exception-based logic null Hibernate will return null if no record is available • is null * I kinda like it
% den != 0) { None } else { Some(num / den) } } fun division(a: Int, b: Int, c: Int): Option<Pair<Int, Int>> { val ac = divide(a, c) return when (ac) { is Some<Int> -> { val bc = divide(b, c) when (bc) { is Some<Int> -> { Some(ac.get() to bc.get()) } else -> None } } else -> None } } An example* Based on Ken Barclay’s* post http://kenbarclay.blogspot.co.uk/2014/02/kotlin-option-type-2.html division function let me check if two numbers (a,b) are divisible by a third one (c) Even if ugly, this is still possible with -1, exceptions or null
return divide(a, c).flatMap { ac -> divide(b, c).flatMap { bc -> Some(ac to bc) } } } division with flatMap fun division(a: Int, b: Int, c: Int): Option<Pair<Int, Int>> { val ac = divide(a, c) return when (ac) { is Some<Int> -> { val bc = divide(b, c) when (bc) { is Some<Int> -> { Some(ac.get() to bc.get()) } else -> None } } else -> None } } = replaced by 1st flatMap = replaced by 2nd flatMap