Busy Developer's Guide to Functional Languages

ted@tedneward.com | Blog: http://blogs.tedneward.com | Twitter: tedneward | Github: tedneward | LinkedIn: tedneward

Objectives

Functional Programming

What's it mean, exactly?

Concepts

Basic functional concepts

Concepts

Optional functional concepts

Concepts

Immutable values

Values over variables

Concepts

A functional pseudocode example


let x = 0
let y = 1
let z = x + y

Concepts

Functions as first-class values

Concepts

Higher-order functions


let numbers = [1, 2, 3, 4, 5]
let squares = numbers.map((num) -> num * num);
// squares = [1, 4, 9, 16, 25]

Concepts

Partial application

Currying

Concepts

Partial application


let add x y = x + y

let five = add 2 3  // = 5
let addBy2 = add 2  // = (anonymous fn) = 2 + y
let six = addBy2 addBy2 2 // = 6

Concepts

Function composition

Concepts

Strongly-typed

Type-inferenced

Concepts

Recursion

Concepts

Expressions-not-statements

Concepts

Tuples, lists

Concepts

Pattern-matching

Concepts

Laziness

Concepts

Sequences

Concepts

- Expressions-not-statements


// Scala

object HelloWorld
{
  def main(args : Array[String]) =
  {
    System.out.println(
      if ((java.lang.Math.random() * 10) % 2 == 0) "Even!"
      else "Odd!"
    )
  }
}
  

Concepts

- Strongly type-inferenced


// F#

let x = 1
let mult x y = x * y
let swap a b = b a
    

% Erlang

-module(tut).
-export([swap/1, mult/2]).

mult(X, Y) ->
    X * Y.

swap({A, B}) ->
    {B, A}.
    

Concepts

- Nested functions


// Scala

def sqrt(x: Double) = {
  def sqrtIter(guess: Double, x: Double): Double =
    if (isGoodEnough(guess, x)) guess
    else sqrtIter(improve(guess, x), x)

  def improve(guess: Double, x: Double) =
    (guess + x / guess) / 2

  def isGoodEnough(guess: Double, x: Double) =
    abs(square(guess) x) < 0.001

  sqrtIter(1.0, x)
}
    

Concepts

- Tuples, lists * tuples are a compound data type with a fixed number of terms * lists are a singly-typed collection of elements


-- Jaskell

{name="tom"; age=1}  -- tuple of string * int

[]       -- empty list
[1, 2]   -- list of two integers
1 :: [2] -- 'cons'ing an integer to a list
    

Concepts

- Recursion-over-iteration


-- Haskell

fac :: Int -> Int
fac n
  | n==0  = 1
  | n > 0  = n * fac (n-1)
    

// Scala

def sumList(xs : List[Int]) =
  if (xs == List()) 0
  else (xs2.head + sumList(xs.tail)
  

Pattern-matching

- Pattern matching


// F#

let rec SumList xs =
  match xs with
  | []    -> 0
  | y::ys -> y + SumList ys

type Expr =
  | Num of int
  | Add of Expr * Expr
  | Mul of Expr * Expr
  | Var of string

let rec Evaluate (env:Map<string,int>) exp =
  match exp with
  | Num n -> n
  | Add (x,y) -> Evaluate env x + Evaluate env y
  | Mul (x,y) -> Evaluate env x * Evaluate env y
  | Var id    -> env.[id]
    

Concepts

# Higher-order functions * functions taking functins as parameters * functions captured as values


// F#

let (|>) x f = f (x)

let Square n = n * n

let SumOfSquaresUpTo n =
  [1..n]
  |> List.map Square
  |> List.sum
  

Concepts

# Closures * referenced values remain around as long as function does * this provides opportunities to "hide" members from the object on which a function operates, to avoid pollution


// JavaScript

var myObj = function() {
  var value = 0;
  return {
    increment: function(inc) {
      value += typeof inc === 'number' ? inc : 1;
    },
    getValue: function() {
      return value;
    }
  };
}();
    

Concepts

- Partial application


// Scala

def sum(f: Int => Int) : (Int, Int) => Int = {
  def sumF(a: Int, b: Int): Int =
    if (a > b) 0 else f(a) + sumF(a + 1, b)
  sumF
}

def powerOfTwo(x: Int): Int = if (x == 0) 1 else 2 * powerOfTwo(x 1)

def sumInts = sum(x => x) _
def sumSquares = sum(x => x * x) _
def sumPowersOfTwo = sum(powerOfTwo) _
  

Concepts

Resources

Attribution

Credentials

Who is this guy?