Upload
jose-manuel-ortega-candel
View
176
Download
5
Embed Size (px)
Citation preview
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
Java 8 new features
Lambda expressions
Closures
Streams
Enhaced collections
Processing data in parallel
Pattern Filter-Map-Reduce
Annotations types
Methods References
(String s)-> System.out.println(s)
System.out::println
Filter-Map-Reduce
Book book=new Book(123455,"Beginning Java 8");
Book book1=new Book(3232332,"Java 8 Advanced");
Book book2=new Book(43434343,"Groovy Advanced");
List<Book> books=Arrays.asList(book,book1,book2);
Predicate<Book> condition=(it) -> it.getTitle().contains("Java");
String jsonFormat=books
.stream()
.filter(condition)
.map(Book::toJSON)
.collect(Collectors.joining(", "));
[{isbn:123455,title:'Beginning Java 8'}, {isbn:3232332,title:'Java 8 Advanced'}]
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
Sequential vs Parallel
books.parallelStream().filter((it) -> it.getTitle().contains("Java")).
forEach((it)->System.out.println(it+" "+Thread.currentThread()));
Book{isbn=3232332, title='Java 8 Advanced'} Thread[main,5,main]
Book{isbn=123455, title='Beginning Java 8'} Thread[main,5,main]
books.stream().filter((it) -> it.getTitle().contains("Java")).
forEach((it)->System.out.println(it+" "+Thread.currentThread()));
Book{isbn=3232332, title='Java 8 Advanced'} Thread[main,5,main]
Book{isbn=123455, title='Beginning Java 8'} Thread[ForkJoinPool.commonPool-
worker-2,5,main]
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
Java 8 vs Scala streams
bookList.parallelStream().filter(b -> b.title.equals(”Clojure”))
.collect(Collectors.toList())
bookList.par.filter(_.title == “Clojure”)
bookList.par.filter( b =>b.title == “Clojure”)
val bookFilter = bookList.par.filter(_.title.contains("Groovy"))
.foreach{i=> println(Thread.currentThread) } Thread[ForkJoinPool-1-worker-3,5,main]
Thread[ForkJoinPool-1-worker-5,5,main]
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<String, String>()
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
Operator overloading Default & name arguments
println(product(2))
println(product(2,3))
println(format(text="kotlin"))
println(format(text="kotlin", upperCase= true))
2
6
kotlin
KOTLIN
fun product(a:Int,b:Int=1):Int{
return a.times(b);
}
fun format(text:String,upperCase:Boolean=
false):String {
return if (upperCase) text.toUpperCase() else text
}
Kotlin
Iterators fun iterateOverCollection(collection: Collection<Int>) {
for (element in collection) {}
}
fun iterateOverString() {
for (c in "abcd") {}
"abcd".iterator()
}
fun iteratingOverMap(map: Map<Int, String>) {
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<String>) {
//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<String>) {
//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<String>) {
val book = Book(123456)
println(book.title);
}
Kotlin
Higher order functions • Lambda expressions
• it implicit parameter
val filter = books filter({ b: Book -> b.title.contains(“Kotlin") })
val book = Book(123455, "Beginning Java 8")
val book1 = Book(3232332, "Java 8 Advanced")
val book2 = Book(43434343, “Kotlin Advanced")
val books = Arrays.asList(book, book1,book2)
Filter[Book(isbn=43434343, title=Kotlin Advanced)]
val filter = books filter({ it.contains(“Kotlin") })
Kotlin collections
val listInmutable
=listOf("Java","Kotlin","Groovy","Scala")
val listMutable=ArrayList<String>()
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());
}
Kotlin vs Java types inference
val longJavaClassName = LongJavaClassName()
LongJavaClassName longJavaClassName =new LongJavaClassName()
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
Closures with lambda
or it implicit parameter
def upper = { s-> s.toUpperCase()}
def upper = {it.toUpperCase()}
Collections
def languages = ["Java":”James
Gosling”, "Scala":”Martin Odersky”,
"Clojure":”Rich Hickey”,
"Ceylon":”Gavin King”,
"Groovy":”James Strachan”]
languages.each { entry -> println}
languages.each { k,v -> println}
Methods as closures with .& operator
def object
object = 2
object = true
object = [1,2,3]
Optional typing
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
Groovy
Time execution
class TimeIt {
def static code(codeBlock){
def start = System.nanoTime()
try{
codeBlock()
}finally{
def end = System.nanoTime()
println "Time taken ${(end-start)/1e9} seconds"
}
}
}
Groovy Advantages Disadvantages
Java Collections Non-lazy evaluation
Closures
(like Lambda expressions in Java 8)
It's performance isn't great
(but it's improving)
Filter – Map – Reduce in streams
Easy interoperability with Java
Static and dynamic typing
@TypeChecked
@CompileStatic
Metaprogramming
Java Groovy
def languages = ["Java", "Scala", "Clojure",
"Kotlin", "Ceylon","Groovy"]
def filter = languages.stream()
.findAll { it.size()>5 }
.collect { it.toUpperCase()}
.first()
List<String> languages = Arrays.asList("Java",
"Scala", "Clojure", "Kotlin","Ceylon","Groovy");
Optional<String> bookFiltered = languages.stream()
.filter(s -> s.length()>5 )
.map(s -> s.toUpperCase())
.findFirst();
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
Sequences (defn count-down [n]
(if (<= n 0)
'(0)
(cons n (lazy-seq (count-down (dec n))))))
Filter – Map - Reduce
(filter integer? [1 2.71 3.14 5 42]) => (1 5 42)
(map (fn [n] (* n n)) [1 2 3 4 5]) => (1 4 9 16 25)
(reduce + [1 2 3 4]) => 10
user=> (count-down 8)
(8 7 6 5 4 3 2 1 0)
Clojure
Records
(defrecord Book [isbn title])
(def bookList [(Book. 432423 "Clojure")(Book. 534243 "Kotlin")
(Book. 432424 "Groovy")])
(println "count bookList "(count bookList))
(dorun (for [item bookList]
(println (:title item)(:isbn item))))
(println (filter #(= "Clojure" (get % :title)) bookList))
count bookList 3
Clojure 432423
Kotlin 534243
Groovy 432424
(#user.Book{:isbn 432423, :title
Clojure})
(defrecord Object [prop1 propn])
Clojure
Recursive functions with trampoline and memoize
(defn factorial ([x] (trampoline (factorial (dec x) x)))
([x a] (if (<= x 1) a #(factorial (dec x) (*' x a)))))
(def fibonaci
(memoize (fn [n]
(if (< n 2)
n
(+ (fibonaci (dec n))
(fibonaci (dec (dec n))))))))
(time(println (factorial 20)))
(time(println (fibonaci 30)))
"Elapsed time: 0.692549 msecs"
832040
"Elapsed time: 1.263175 msecs"
"Elapsed time: 24.574218 msecs"
832040
"Elapsed time: 118.678434 msecs"
2432902008176640000
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
Clojure vs Java
Code reducing
(defn blank [str]
(every#? (Character/isWhitespace %)
str))
public class StringUtils {
public static boolean isBlank(String str) {
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)))) {
return true;
}}
return false;
}}
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
Ceylon
Sequence languages = Sequence("Java",
"Groovy","Clojure","Kotlin");
//Check if the sequence is empty
if(nonempty languages){
String? firstElementValue = languages.value(1);
String? firstElement = languages.first;
}
Sequence more =
join(languages,Sequence("Ceylon","Scala"));
Sequences Generics & Union types
Iterable<String|Boolean> list =
{“string”,true,false}
ArrayList<Integer|Float> list =
ArrayList<Integer|Float>
(1, 2, 1.0, 2.0)
Comparing featues
• Reducing verbosity
• Variables definition
• Null-safety
• Optional types
• Lambdas
• Pattern matching
• Traits
• Java interoperability
Reducing Java verbosity Reducing Boilerplate Code
class MyClass{
private int index;
private String name;
public MyClass(int index, String name){
this.index = index;
this.name = name;
}
}
case class MyClass(index: Int, name: String)
public class MyClass(var index:Integer,var name:String){
}
class MyClass {
int index
String name
}
class MyClass(index,name) {
shared Integer index;
shared String name;
}
(defstruct MyClass :index :name)
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
Null-safety
• Operator ? used in Kotlin,Groovy,Ceylon
• Avoid NullPointerException
var b : String? = "b"
b = null // valid null assignment
val l = b?.length()
Elvis Operator(?:) and Safe navigation (?.)
def displayName = user.name ? user.name : "Anonymous“
def streetName = user?.address?.street
String? argument = process.arguments.first;
if (exists argument) { //checking null values
}
Optional Types
Optional<Object> 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
private val languages = Map(1 -> Language(1, "Java", Some("Gosling")),
2 -> Language(2, "Scala", Some("Odersky")))
def findById(id: Int): Option[Language] = languages.get(id)
def findAll = languages.values
def main(args: Array[String]) {
val language = Optional.findById(1)
if (language.isDefined) {
println(language.get.name)
}
}
val language = Optional.findById(3) None
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
Lambdas in streams
List<Book> books=Arrays.asList(book,book1,book2);
Optional<String> bookFiltered =
books.stream()
.filter(b -> b.getTitle().contains("Groovy"))
.map(b -> b.getTitle().toUpperCase())
.findFirst();
val books = Arrays.asList(book,book1,book2)
val bookFiltered : String? =
books.sequence()
.filter { b->b.title.contains("Groovy")}
.map { b->b.title.toUpperCase() }
.firstOrNull()
def bookfilter= books.
findAll { b->b.title.contains(" Groovy ") }
.sort { b->b.isbn }
.collect { b->b.title.toUpperCase() }
.find()
val bookList = List(book1,book2,book3);
val bookFilter = bookList
.filter(b=>b.title.contains("Groovy"))
.map(book => book.title)
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
Traits.Code in interfaces
trait Publication {
int number
def getNumberPublication(){
return (number)
}
}
trait Location {
String description
def getInfoPublication(){
return (description)
}
}
class MyBook implements Publication,Location{
Integer isbn
String title
def getInfoBook(){
return (isbn+ " "+title)
}
}
trait Publication {
def description() = println(“Description”)
}
class Book(var isbn:Int,var title:String) extends Publication{
def getInfoBook(){
return (isbn+ " "+title)
}
}
trait Publication{
var number:String
fun getNumberPublication(){
println(number)
}
}
class Book:Publication {
}
Java interoperability object list extends App {
import java.util.ArrayList
var list : ArrayList[String] = new ArrayList[String]()
list.add("hello")
list.add("world")
println(list)
}
import collection.JavaConversions._
java.util.Arrays.asList(1,2,3).
foreach(i =>println(i))
java.util.Arrays.asList(1,2,3).
filter(_ % 2 ==0)
fun list(source: List<Int>):ArrayList<Int> {
val list = ArrayList<Int>()
for (item in source)
list.add(item)
for (i in 0..source.size() - 1)
list[i] = source[i]
return list
}
(ns clojure-http-server.core
(:require [clojure.string])
(:import (java.net ServerSocket SocketException)
(java.util Date)
(java.io PrintWriter BufferedReader
InputStreamReader BufferedOutputStream)))
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<Language> 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 })
Read file and print lines import scala.io.Source
for (line <- Source.fromFile(“file.txt”).getLines())
println(line.length +" "+ line)
import java.nio.file.*;
import java.util.stream.Stream;
Path dict = Paths.get(“file.txt”);
Stream<String> linesStream = Files.lines(dict);
linesStream.forEach(System.out::println);
val dict = Paths.get(“file.txt")
val linesStream = Files.lines(dict)
val lines = linesStream.forEach{println(it)};
Read file and print lines
(defn read-file [file]
(with-open [rdr (clojure.java.io/reader file)]
(doseq [line (line-seq rdr)]
(println line))))
(read-file (file “file.txt"))
Files.lines(Paths.get(“file.txt")).forEach{println it};
Performance in recursion
(defn factorial ([x] (trampoline (factorial (dec x) x)))
([x a] (if (<= x 1) a #(factorial (dec x) (*' x a)))))
@TailRecursive
def fact(BigInteger n,acumulator = 1G) {
if (n <2){
acumulator
}else{
fact(n-1,n*acumulator)
}
}
@scala.annotation.tailrec
def factorialrec(fact:BigInt,number:BigInt=1):BigInt = {
if (fact<2) return number
else factorialrec(fact-1,fact*number)
}
Comparing features
Higher Order Functions
Mixin/traits
Pattern matching
Implicit casts
Nullables / Optionals
Modules
Promote inmutability
Lambdas
Palindrome
(use 'clojure.java.io)
(defn palindrome? [s]
(let [sl (.toLowerCase s)]
(= sl (apply str (reverse sl)))))
(defn find-palindromes[s]
(filter palindrome? (clojure.string/split s #" ")))
fun isPalindrome(s : String) : Boolean {
return s== s.reverse()
}
fun findPalindrome(s:List<String>): List<String>{
return s.filter {isPalindrome(it)}.map {it}
}
def isPalindrome(x:String) = x==x.reverse
def findPalindrome(s:Seq[String]) = s find isPalindrome
def isPalindrome(s) {
def s1 = s.toLowerCase()
s1 == s1.reverse()
}
def findAllPalindrome(list) {
list.findAll{isPalindrome(it)}
}
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.
Resources
SCALA • http://www.scala-lang.org
• http://www.scalakoans.org
• http://scala-ide.org
• https://www.coursera.org/course/progfun
KOTLIN • http://kotlinlang.org
• http://kotlin.jetbrains.org
• http://kotlin-demo.jetbrains.com
• http://github.com/Jetbrains/kotlin
Resources
CLOJURE • http://www.tryclj.com
• http://clojuredocs.org
• http://www.clojure-toolbox.com
• http://www.clojureatlas.com
CEYLON • https://modules.ceylon-lang.org
Resources
• http://vschart.com/compare/kotlin/vs/clojure/vs/scala
Book
• Seven Languages in Seven Weeks • A Pragmatic Guide to Learning Programming Languages
• https://pragprog.com/book/btlang/seven-languages-in-seven-weeks
• Ruby
• Io
• Prolog
• Scala
• Erlang
• Clojure
• Haskell