Functional programming
Scala & Clojure
@joelcorrea_ @humbertostreb
JVM powered languages
Imperative vs Functional
-
Martin Odersky
- Current stable version = 2.11.0
- OO + FP
Who is using
-
Rich Hickey
- Current stable version = 1.6.0
Who is using
Clojure is a LISP
Rationale
"It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures."Alan J. Perlis
Data structures
Lists
(1 2 3 4 5), (list 1 2 3)
Vectors
[1 2 3], ["string-1" "string-2" "string-3"]
Maps
{:a 1 :b 2 :c 3}, {1 "sample1" 2 "sample2"}
Sets
#{sample1 sample2 sample3}
Concepts
- Immutability
-
Referential transparency (no side-effects)
- Lazy evaluation
- Hybrid FP + OO
- Simplicity
- Immutability
Sum numbers in a list
public double sum(ArrayList<Double> numbers)
{
double sum = 0;
for(int i = 0; i < numbers.size(); i++)
{
sum = sum + numbers.get(i);
}
return sum;
}
Sum numbers in a list
> List(1, 2, 3, 4, 5).sum
> Int = 15
> (reduce + [1 2 3 4 5])
> 15
Increment list values
public double increment(ArrayList
numbers) { ArrayList incNumbers = new ArrayList();
for(int i = 0; i < numbers.size(); i++) { incNumbers.append(numbers.get(i)+1); } return newNumbers; }
Increment list values
> List(1,2,3).map(_ + 1)
> List(2, 3, 4)
> (map inc [1 2 3])
> (2 3 4)
Higher Order Functions (HOFs)
Anonymous function
((x : Int) => x + 1)(1)
> 2
(#(+ % 1) 1)
> 2
Filter
List(1,2,3).filter(_ == 1)
> List(1)
(filter #(= % 1) [1 2 3])
> (1)
Map + Reduce
List("a","bb","").map(_.size).reduce(_+_)
> Int = 3
(reduce + (map count ["a" "bb" ""]))
> 3
Sort
List(100, 25, 10, 1).sorted
> List[Int] = List(1, 10, 25, 100)
(sort [3 10 25 100 1 0])
> (0 1 3 10 25 100)
Unit tests
class FizzBuzzTest extends FunSuite{
test("Is fizz") assert(isFizz(3) == true)
test("Is buzz") assert(isBuzz(5) == true)
}
(deftest fizBuzzTest
(testing "is fizz" (is (= (isFizz 3) true)))
(testing "is buzz" (is (= (isBuzz 5) true))) )
Immutable
> val a = 1
a: Int = 1
> a = 2
:8: error: reassignment to val
> var b = 1
b: Int = 1
> a = 2
b: Int = 2
> case class Person(name: String, age: Int)
> val person = Person("person", 30)
person: Person = Person(person,30)
> val personOlder = person.copy(age = 31)
personOlder: Person = Person(person,31)
Reduce
> Seq(20, 10, 30) reduce { (accum, current) => accum + current }
Int = 60
> Seq(20, 10, 30) reduce(_ + _)
Int = 60
> Seq(20, 10, 30) sum
Int = 60
Map
> val people = List(Person("a", 20), Person("b", 10), Person("a", 30))
people: List[Person] = List(Person(a,20), Person(b,10), Person(a,30))
> people.map(_.age).sum
Int = 60
Higher order functions
> val underAge = (person: Person) => person.age < 18
underAge: Person => Boolean =
> people.filter(underAge)
List[Person] = List(Person(b,10))
Anonymous function
> people.filter(person => person.age > 18)
List[Person] = List(Person(a,20), Person(a,30))
> people.sortBy(person => person.age)
List[Person] = List(Person(b,10), Person(a,20), Person(a,30))
Java way
public List peopleUnderAge(List people) {
List result = new ArrayList();
for (Person person : people) {
if (person.getAge() < 18) {
result.add(person);
}
}
return result;
}
For-comprehension
> val nameAge = for {
| person <- people
| age <- Seq(20, 10, 30)
| if (person.age == age)
| } yield (person.name, age)
List[(String, Int)] = List((a,20), (b,10), (a,30))
Thank you!
functional programming - Scala & Clojure
By Joel Corrêa
functional programming - Scala & Clojure
- 1,323