REAL WORLD

λ Programming

Suraj Atreya

Glassbeam

Goal of this talk

Collections

 

Hashtable<String, String> flnames = new Hashtable<String, String>();
flnames.put("Bill", "Gates");
flnames.put("Steve", "Jobs");
flnames.put("John", "Doe");
		
Set<String> keys = flnames.keySet();
		
for(String key: keys){
    System.out.println(key + "," + StringOps.getLastNameInitials(flnames.get(key)));
}
Steve,J
John,D
Bill,G
public class StringOps {

	public static char getLastNameInitials(String lname){
		return lname.charAt(0);
	}
	
}
public class MathOps{

    public ArrayList<Integer> multipleOf3(ArrayList<Integer> arr1){
    		
            ArrayList<Integer> result = new ArrayList<Integer>();
    		
            for(int i : arr1){
                if(i % 3 == 0){
                    result.add(i);
                }
            }
            
            return result;
    }
}
ArrayList<Integer> alInts = new ArrayList<Integer>();
		
for (int i = 0; i < 100; i++){
    alInts.add(i);
}
		
ArrayList<Integer> res = new MathOps().multipleOf3(alInts);
		
System.out.println(res);
//Output
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, ...]
public class MathOps{

    public ArrayList<Integer> multipleOf5(ArrayList<Integer> arr1){
    		
            ArrayList<Integer> result = new ArrayList<Integer>();
    		
            for(int i : arr1){
                if(i % 5 == 0){
                    result.add(i);
                }
            }
            
            return result;
    }
}
ArrayList<Integer> alInts = new ArrayList<Integer>();
		
for (int i = 0; i < 100; i++){
    alInts.add(i);
}
		
ArrayList<Integer> res = new MathOps().multipleOf5(alInts);
		
System.out.println(res);
//Output
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, ...]
Hashtable<String, String> flnames = new Hashtable<String, String>();
flnames.put("Bill", "Gates");
flnames.put("Steve", "Jobs");
flnames.put("John", "Doe");
		
Set<String> keys = flnames.keySet();
		
for(String key: keys){
    System.out.println(key + "," + StringOps.getLastNameInitials(flnames.get(key)));
}
scala> val ls = List(("Bill", "Gates"), ("Steve", "Jobs"),  ("John", "Doe"))
ls: List[(String, String)] = List((Bill,Gates), (Steve,Jobs), (John,Doe))

scala>  ls.map ( t => println(t._1 + "," +  t._2(0)) )
Bill,G
Steve,J
John,D
public class StringOps {

	public static char getLastNameInitials(String lname){
		return lname.charAt(0);
	}
	
}
scala> (1 to 100).toList.filter(x => x % 3 == 0)
public class MathOps{

    public ArrayList<Integer> multipleOf3(ArrayList<Integer> arr1){
    		
            ArrayList<Integer> result = new ArrayList<Integer>();
    		
            for(int i : arr1){
                if(i % 3 == 0){
                    result.add(i);
                }
            }
            
            return result;
    }
}
λ>filter (\x -> x `mod` 3 == 0) [1..100]
//Output
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, ...]
public class MathOps{

    public ArrayList<Integer> multipleOf5(ArrayList<Integer> arr1){
    		
            ArrayList<Integer> result = new ArrayList<Integer>();
    		
            for(int i : arr1){
                if(i % 5 == 0){
                    result.add(i);
                }
            }
            
            return result;
    }
}
scala> (1 to 100).toList.filter(x => x % 5 == 0)
λ>filter (\x -> x `mod` 5 == 0) [1..100]
//Output
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, ...]

But, what is Functional Programming anyway?

All this is funky and cool!

Functional Programming

  • Programing with pure functions
    • Functions are first class citizens
  • No state (read Immutability)
  • Referential transparency
object PureFPEx {

  def strLength (str: String): Int = {
    str.length
  }
  
  def findLength(f: String => Int, str : String): Int = {
    f(str) + 1
  }
  
  def main(args: Array[String]): Unit = {
    println(findLength(strLength, "hello"))
  }

}

Pure Function

object PureFPEx {

  def strLength (str: String): Int = {
    str.length
  }
  
  def strLengthBy2(str: String): Int = {
    str.length / 2
  }
  
  def findLength(f: String => Int, str : String): Int = {
    f(str) + 1
  }
  
  def main(args: Array[String]): Unit = {
    println(findLength(strLength, "hello"))
    println(findLength(strLengthBy2, "hello"))
  }

}

Pure Function

val x = “Hello, World”
x:java.lang.String = Hello, World
val r1 = x.reverse
r1:String = dlroW ,olleH
val r2 = x.reverse
r2:String = dlroW ,olleH

scala> val r1 = “Hello, World”.reverse
r1:String = dlroW ,olleH
scala> val r2 = “Hello, World”.reverse
r1:String = dlroW ,olleH

Substitute "x" with its value

Refential Transparency

  • "x" is referentially transparent
  • No side effects after substitution

Refential Transparency

val x = new StringBuilder(“Hello”)
x: java.lang.StringBuilder = Hello

val r1 = x.append(“, World”).toString
r1:java.lang.String = Hello, World

val r2 = x.append(“, World”).toString
r2:java.lang.String = Hello, World, World
  • x is not referentially transparent
  • After substitution, the output is different - “side effects”
def countPrimesImpure(lim: Int) = {
    var count = 0    
    val l = (1 to lim).toList.par
    l.map(x => if (isPrime(x)) count = count + 1)
    count
}
//Calling code
countPrimesImpure(1000000)

State: Mutability

def countPrimesPure(lim: ParSeq[Int]) = {
    lim.filter(isPrime).length
}
//Calling code
val s =  countPrimesPure(Stream.from(1).takeWhile(p => p < 1000000).par)
println(s)

State: Immutability

  • "count" is the source of problem
  • holds state
  • leads to race conditions - shared by threads

Mutability: not a good idea

Immutability: rocks!

  • No state
  • Implicit locking - translates to no mutexes
  • Concurrency for free!
  • functor

  • applicative functors

  • monads

functor

λ>:t fmap
fmap :: Functor f => (a -> b) -> f a -> f b

functor: map

map is an instance of functor typeclass

λ>:t map
map :: (a -> b) -> [a] -> [b]
λ>map (\x -> x + 1) [1,2,3]
[2,3,4]
scala> List(1,2,3) map (x => x + 1)
List[Int] = List(2, 3, 4)

applicative functor

  • applicative functor is also a functor

λ>:t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
λ>pure (*) <*> [1,2,3] <*> [4,5,6]
[4,5,6,8,10,12,12,15,18]
public ArrayList<Integer> carteseanProduct(ArrayList<Integer> arr1, 
                ArrayList<Integer> arr2) {
		
    ArrayList<Integer> res = new ArrayList<Integer>();
		
    for (Integer in1 : arr1) {
        for (Integer in2 : arr2) {
            res.add(in1 * in2);
        }
    }
    return res;
}
ArrayList<Integer> l1 = new ArrayList<Integer>();
ArrayList<Integer> l2 = new ArrayList<Integer>();

l1.add(1);
l1.add(2);
l1.add(3);
		
l2.add(4);
l2.add(5);
l2.add(6);

System.out.println(new MathOps().carteseanProduct(l1, l2));

monads

 

  • a lifetime isn't enough to learn about monads
  • can find more articles on monads than the number of stars in the galaxy
  • ALL OF THAT IS HYPE!
object Monads {

  def square(ls: List[Int]) : List[Int] = {
    ls.map(x => x * x)
  }
  
  def filterMultiple4(ls: List[Int]) : List[Int] = {
    ls.filter(x => x % 4 == 0)
  }
  
  def divideBy2(ls: List[Int]): List[Int] = {
    ls.map(x => x / 2)
  }
  
  def main(args: Array[String]): Unit = {
    
    val myList = (1 to 100).toList
    
    val aa = square(myList)
    
    val bb = filterMultiple4(aa)
    
    val cc = divideBy2(bb)
    
    println(cc)
    
  }

}
  1. square every element in the list
  2. pick only mutilples of 4 from step (1)
  3. divide by 2 every element from step (2)

Non-monadic

object Monads2 {

  def square(ls: List[Int]): List[Int] = {
    ls.map(x => x * x)
  }

  def filterMultiple4(ls: List[Int]): List[Int] = {
    ls.filter(x => x % 4 == 0)
  }

  def divideBy2(ls: List[Int]): List[Int] = {
    ls.map(x => x / 2)
  }

  def main(args: Array[String]): Unit = {
    val transformed = for {
      a <- Some(square(myList))
      b <- Some(filterMultiple4(a))
      c <- Some(divideBy2(b))
    } yield c

    println(transformed)
  }

}
  1. square every element in the list
  2. pick only mutilples of 4 from step (1)
  3. divide by 2 every element from step (2)

monadic

REAL WORLD λ Programming

By surajatreya

REAL WORLD λ Programming

  • 891