INDEX Functional programming and closures 2 Language classification 1 Java 8 new features 3 Scala, Groovy, Kotlin, Clojure and Ceylon 4 Advantages and drawbacks 5 Comparing features 6
Functional programming •Data structure persistent and immutable •Closures •Higher order functions •Pass functions to functions as parameter •Create functions within functions •Return functions from other functions •Functions as first class values
Closures •Reduce amount of “boiler plate” code •Eliminate the boilerplate code of anonymous inner classes •Allow the use of idiomatic functional programming code •Allow the creation of custom control structures •In Java 8 closures are just syntactic sugar for defining anonymous inner classes
Parallel Streams List myList = .. Stream stream = myList.stream(); Stream parallelStream = myList.parallelStream(); Stream parallel = stream.parallel(); •Streams are sequential by default •With Parallel you can optimize number of threads •More efficient with bigger collections
Scala Combines the paradigms of functional programming and object-oriented Statically typed No types primitives like Java Everything is an Object, including functions Performance equivalent to Java
Scala features Pattern matching Closures,lambdas,anonymous functions Traits and mixins for multiple inheritance Operator overloading Support Data Paralell like Java 8 Concurrency models(Akka,actors) Inmutable and mutable data structures
Scala examples def factorial(n : Int): Int = n match{ case 0 => 1 case x if x >0 => factorial(n-1) *n } val languages = List("Scala", "Groovy", "Clojure", "Kotlin") val headList = languages.head // Scala val tailList = languages.tail; //List( "Groovy", "Clojure", "Kotlin") val empty = languages.isEmpty //false def orderList(xs: List[String]): List[String] = if (xs.isEmpty) Nil else insert(xs.head, isort(xs.tail) @BeanProperty Annotation which is read by the Scala compiler to generate getter and setter class Bean { @scala.reflect.BeanProperty var name: String } val someNumbers = List(-11, -10, -5, 0, 5, 10) someNumbers.filter((x) => x > 0) someNumbers.filter(_ > 0) List[Int] = List(5, 10) scala.collection.immutable
Inmutability in Scala scala> var languages = Set("Scala", "Kotlin") languages : scala.collection.immutable.Set[java.lang.String] = Set(Scala, Kotlin) scala> languages += "Clojure" scala> languages res: scala.collection.immutable.Set[java.lang.String] = Set(Scala, Kotlin, Clojure) scala> languages -= " Kotlin " scala> languages res: scala.collection.immutable.Set[java.lang.String] = Set(Scala, Clojure) • You can add elements in a inmutable collection
Kotlin Object-oriented with functional elements Developed by JetBrains Statically typed like Scala Smarts casts Elvis operator(?) for checking null like Groovy Type inference 100 % interoperability with Java
Kotlin syntax & rules Inmutable/Mutable variables No new keyword for create objects No primitive types No static members Primary constructors No fields, just properties By default, all classes are final
Kotlin Smart casts Maps val languages = mapOf("Java" to "Gosling", "Scala" to "Odersky","Groovy" to "Strachan") for((language,author) in languages){ println("$author made $language") } fun eval(e: Expr): Double = when (e) { is Num-> e.value.toDouble() is Sum -> eval(e.left) + eval(e.right) else -> throw IllegalArgumentException("Unknown expression") } val mapLanguages = hashMapOf() mapLanguages.put("Java", "Gosling") mapLanguages.put("Scala", "Odersky") for ((key, value) in mapLanguages) { println("key = $key, value = $value") } fun patternMatching(x:Any) { when (x) { is Int -> print(x) is List<*> ->{print(x.count())} is String -> print(x.length()) !is Number -> print("Not even a number") else -> print("can't do anything") } }
Kotlin Iterators fun iterateOverCollection(collection: Collection) { for (element in collection) {} } fun iterateOverString() { for (c in "abcd") {} "abcd".iterator() } fun iteratingOverMap(map: Map) { for ((key, value) in map) {} }
Kotlin Data classes Data annotation changes behavior of hashCode, equals, toString functions public class Book (var isbn:Int, var title:String) fun main(args: Array) { //Books val book = Book(123456, "Beginning Kotlin") val book2 = Book(123456, "Beginning Kotlin") println(book); println(book.hashCode()); println(book2.hashCode()); println(book.equals(book2)); if (book == book2) println("Same Book"); if (book != book2) println("Diferent Book"); } books.Book@2a84aee7 713338599 168423058 false Diferent Book data public class Book (var isbn:Int, var title:String) fun main(args: Array) { //Books val book = Book(123456, "Beginning Kotlin") val book2 = Book(123456, "Beginning Kotlin") println(book); println(book.hashCode()); println(book2.hashCode()); println(book.equals(book2)); if (book == book2) println("Same Book"); if (book != book2) println("Diferent Book"); Book(isbn=123456, title=Beginning Kotlin) 1848623012 1848623012 true Same Book
Kotlin Classes constructor • It is not necessary define a constructor like in Java • You can use the class definition to pass the properties and default values data public class Book (var isbn:Int, var title:String="My Default Book") fun main(args: Array) { val book = Book(123456) println(book.title); }
Kotlin collections val listInmutable =listOf("Java","Kotlin","Groovy","Scala") val listMutable=ArrayList() listMutable.add("Java") listMutable.add("Kotlin")
Kotlin vs Java list iterate for ((index,element) in list.withIndex()) { println(“$index$element”); } int index=0 for (String element:list) { System.out.println(index+””+element); index++ }
Kotlin smart cast vs Java if (expr is Number) { println(expr.getValue()); //expr is automatically cast to Number } if (expr instanceof Number) { System.out.println((Number)expr).getValue()); }
Groovy Java supercharged(syntactic sugar) Object oriented and dynamic language Optional typing like Scala and Kotlin All type checking is at run time It reduces Java boilerplate code including no semi colons, no getters/setters, type inference, null safety, elvis operators
Groovy @Memoized annotation @Inmutable annotation @Memoized def BigInteger fibRecursiveMemoized(n) { if (n<2) return 1 else return fibRecursiveMemoized(n-1) + fibRecursiveMemoized(n-2) } TimeIt.code{println(fibonnaci.fibRecursive(40))} TimeIt.code{println(fibonnaci.fibRecursiveMemoized(40))} 165580141 Time taken 42.083165464 seconds 165580141 Time taken 0.061408655 seconds //with memoize import groovy.transform.Immutable @Immutable class Language { String title; Long isbn; } def l1 = new Language (title:'Beginning Groovy',isbn:100) def l2 = new Language (title:'Groovy advanced',isbn:200) l1.title = 'Groovy for dummies' // Should fail with groovy.lang.ReadOnlyPropertyException
Clojure Pure functional language JVM language based in Lisp Not Object Oriented Dynamically typed All data structure including list ,vectors, maps, sequences, collections, are inmutable and fully persistent The main data structure is the list The key is the use of High Order Functions
Clojure Alternate implementations in functions (defn square-or-multiply "squares a single argument, multiplies two arguments" ([] 0) # without arguments ([x] (* x x)) # one argument ([x y] (* x y))) # two arguments List operations (first '(:scala :groovy :clojure))return scala (rest '(:scala :groovy :clojure))return all elements excepts the first (cons :kotlin '(:scala :groovy :clojure))add kotlin to head in the list
Clojure Advantages Disadvantages Very simple Not Object oriented The language has little elements compared with other languages Difficult to decipher stacktraces and errors Excellent concurrency support Requires a new way to solve problems Easy interoperability with java There are no variables Powerful language features (macros,protocols) Thre is no inheritance concept Clojure programs run very quickly No mecanism for avoid NullPointerException JVM is highly optimized
Ceylon Is very similar to Java, reducing verbosity Object oriented with functional features Strong static typing with type inference Explicit module system Comparing with Java Eliminates static, public, protected, private Add new modifiers like variable, shared, local Shared is used for make visibility outside in other modules(like public in Java) Arrays are replaced by sequences
Variables definition • In Kotlin and Scala you can define 2 types • var myMutableVariable • val myInmutableVariable • In Ceylon we have variable modifier for mutable variable Integer count=0; count++; //OK Integer count=0; count++;//ERROR val name: Type = initializer // final “variable” var name: Type = initializer // mutable variable
Optional Types Optional optional = findObject(id); //check if Optional object has value if (optional.isPresent()) { System.out.println(optional.get()); } Type safe Option[T] in Scala New class java.util.Optional
Optional Type in Scala val languages =Map("Java"->"Gosling","Scala"->"Odersky") languages:scala.collection.immutale.Map[java.lang.String,java.lang.String] languages get "Scala" Option[java.lang.String] = Some(Odersky) languages get "Groovy" Option[java.lang.String] = None
Pattern matching • Is a generalization of Java switch/case def generalSize(x: Any) = x match { case s: String => s.length case m: Map[_, _] => m.size case _ => -1 } scala> generalSize("abc") res: Int = 3 scala> generalSize(Map(1 -> 'a', 2 -> 'b')) res: Int = 2 fun fib(n: Int): Int { return when (n) { 1, 2 -> 1 else -> fib(n - 1) + fib(n - 2) } } fun patternMatching(x:Any) { when (x) { is Int -> print(x) is List<*> ->{print(x.size())} is String -> print("String") !is Number -> print("Not even a number") else -> print("can't do anything") } }
Traits vs Java interfaces Traits allow declare method definitions A trait is an interface with an implementation(behavior and/or state) Traits support “multiple inheritance” One class can inherit from many traits
Java interoperability import scala.beans.BeanProperty class Language( @BeanProperty var name: String, @BeanProperty var author: String) { } public static void main(String[] args) { Language l1 = new Language(“Java",”Gosling”); Language l2 = new Language(“Scala",”Odersky”); ArrayList list = new ArrayList<>(); list.add(l1); list.add(l2); }
List Partitions • We can use partition over a list for obtain 2 lists scala> List(1, 2, 3, 4, 5) partition (_ % 2 == 0) res: (List[Int], List[Int]) = (List(2, 4),List(1, 3, 5)) // partition the values 1 to 10 into a pair of lists of even and odd numbers assertEquals(Pair(listOf(2, 4, 6, 8, 10), listOf(1, 3, 5, 7, 9)), (1..10) .partition{ it % 2 == 0 })
Conclusions Full interoperability with Java Reducing Java verbosity These languages allow developer be more productive comparing with java Pragmatic Programmer advice: When you learn a new language, you learn a new way to think.