Showing posts with label continuous passing style. Show all posts
Showing posts with label continuous passing style. Show all posts

Sunday, April 7, 2013

On CPS - Part 2

"I was employed in passing to and fro
About relieving of the sentinels."
-- Shakespeare, Henry VI Part I
Act II Scene I Lines 69-70


Continuous passing style (CPS) is way of  programming in which you take direct control of the control flow by passing where the called function will return.


In the example above, the "function" is passed "values" to operate on along with the "continue function" it will pass control to after it is done (hence it does not return directly to the caller).  Using this style of programming one can construct the call stack.

Why would anyone want to do this?  Say you want to execute a recursive function obtaining some value really deep in the recursion.  The Fibonacci sequence is a great example of this type of problem.  Say you want to find the value of the 100,000th number in the Fibonacci sequence (well maybe this is pushing it for what I am going to show in this blog post, but you get the idea).

Non-CPS example (on tryfsharp.org):

let rec fib =
  function
  | 0 | 1 -> 1
  | n -> fib (n-2) + fib (n-1);;


If you were going to look for the 100,000th Fibonacci number using the standard recursive solution, you would get a stack overflow.  What you would like to do is use the heap instead of the stack, but how does one do that?  This is where CPS comes into play.  If you are working on a system which supports it, your continuations will go into the heap instead of being placed on the stack.

CPS example (on tryfsharp.org):


let rec fib_cps n k =
  match n with
  | 0 | 1 -> k 1
  | n -> fib_cps (n-1)
         (fun x -> fib_cps (n-2) (fun y -> k (x+y)));;


What you are doing in the example above is creating a closure with the next two calls which will placed in the heap.  Once fib_cps(0) and fib_cps(1) are hit then the whole calculation is solved for and the value is returned to the caller of the function.

For the Fibonacci sequence this is still wasteful since same values are calculated many times.



In the figure above, everything in salmon color is wasted effort.  What we would rather do is reuse the values we have already calculated (which is way you would not want to use this method to calculate the 100,000th Fibonacci number).

Along the lines of reducing waste we can look at using a data structure instead of using a closure.

Defunctionalization example (on tryfsharp.org):

type fib_cont =
  | Fib_zero
  | Fib_minus1 of int * fib_cont
  | Fib_minus2 of fib_cont * int;;

let rec fib_cps_defun n k =
  match n with
  | 0 | 1 -> fib_cont_eval 1 k
  | n -> fib_cps_defun (n-1) (Fib_minus1 (n, k))
and fib_cont_eval acc =
  function
  | Fib_zero -> acc
  | Fib_minus1 (n, k) -> 
      fib_cps_defun (n-2) (Fib_minus2 (k, acc))
  | Fib_minus2 (k, acc') -> fib_cont_eval (acc+acc') k;;


I first came across this idea, while reading what I will say is one of the greatest responses on StackOverflow.    What we are doing is constructing the heap with the Fib_minus1 type and then evaluating this to it function fib(n-1) + fib(n-2).  This can be more efficient on systems where data structures are easier to allocate than allocation of a closure call.

We still have not solved the problem of finding the 100,000th Fibonacci number, but we are along the correct path.

Full example (using FsUnit):

open NUnit.Framework
open FsUnit

type fib_cont =
  | Fib_zero
  | Fib_minus1 of int * fib_cont
  | Fib_minus2 of fib_cont * int

let rec fib_cps_defun n k =
  match n with
  | 0 | 1 -> fib_cont_eval 1 k
  | n -> fib_cps_defun (n-1) (Fib_minus1 (n, k))
and fib_cont_eval acc =
  function
  | Fib_zero -> acc
  | Fib_minus1 (n, k) -> fib_cps_defun (n-2) (Fib_minus2 (k, acc))
  | Fib_minus2 (k, acc') -> fib_cont_eval (acc+acc') k

let fib n = fib_cps_defun n Fib_zero

[<Test>]
let ``Validate that fib 0 is 1`` () =
  fib 0 |> should equal 1

[<Test>]
let ``Validate that fib 1 is 1`` () =
  fib 1 |> should equal 1

[<Test>]
let ``Validate that fib 2 is 2`` () =
  fib 2 |> should equal 2

[<Test>]
let ``Validate that fib 3 is 3`` () =
  fib 3 |> should equal 3

[<Test>]
let ``Validate that fib 4 is 5`` () =
  fib 4 |> should equal 5

[<Test>]
let ``Validate that fib 17 is 2584`` () =
  fib 17 |> should equal 2584

Friday, March 29, 2013

On CPS Part 1

"O, many
Have broke their backs with laying manors on 'em
For this great journey. What did this vanity
But minister communication of
A most poor issue?"
-- Shakespeare
Henry VIII
Act I, Scene I
Lines 83-87

I've moved further along in my journey of functional programming.  I find myself in a densely wooded forest of colossal pine trees.  The smell of juniper fills the air, bring with it memories of winters gone by.  This forest is where continuation lives.

Continuation-passing style is programming with no return, literally there is no return statement when you use continuation-passing style (CPS).  Instead what you do is pass in the function which you would like the function you are calling to return its result to.

Simple CPS example

Say you have function called f and you want f to take what ever value you give it and pass it to another function you give it that well call k.



In F# (on tryfsharp)

let f = fun x k -> k(x)


> val f : x:'a -> k:('a -> 'b) -> 'b


What we do is pass a function through k which takes one argument, like this:


f 5 (printfn "%d")



> 5
val it : unit = ()


FizzBuzz example

Lets do my favorite kata FizzBuzz using CPS.

First we make the fizzer and buzzer.


In F# (on tryfsharp)

let xzz n (w:string) =

    fun x ->
      match x with
      | x when x % n = 0 -> Some(w)
      | _ -> None
  
  let fizz x = (xzz 3 "Fizz") x
  
  let buzz x = (xzz 5 "Buzz") x

> val xzz : n:int -> w:string -> x:int -> string option
> val fizz : x:int -> string option
> val buzz : x:int -> string option


We now have a fizzer and a buzzer which will return string options.

Now let's make the fizzBuzzer using these functions.  We'll also use List.choose so we'll have either ["Fizz"], ["Buzz"], ["Fizz";"Buzz"], or [] as a result of applying fizzer and buzzer against the numerical input.  We'll then use List.reduce to concat the possible ["Fizz";"Buzz"] result.

In F# (on tryfsharp)



let fizzBuzzer n k =
  match [fizz; buzz] |> List.choose (fun f -> f n) with
  | [] -> k(n.ToString())
  | x -> k(x |> List.reduce (+))



> val fizzBuzzer : n:int -> k:(string -> 'a) -> 'a


Note this uses the fizz and buzz from before.

In order to consume this CPS version of FizzBuzz you could do the following:


 let p = (fun x -> printfn "%s" x);;
  fizzBuzzer 2 p;;
  fizzBuzzer 9 p;;
  fizzBuzzer 10 p;;
  fizzBuzzer 30 p;;

> val p : x:string -> unit

> 2
val it : unit = ()
> Fizz
val it : unit = ()
> Buzz
val it : unit = ()
> FizzBuzz
val it : unit = ()

The great thing about CPS with TDD is that you can pass what you are testing its own test case (see Full FizzBuzz example below).  I'll have more on CPS, once I wrap my head around it fully.  I am working on understanding one of the best responses I've seen on StackOverflow.


Full Fizz Buzz example in F# (with FsUnit):

open NUnit.Framework

open FsUnit

let xzz n (w:string) =
  fun x ->
    match x with
    | x when x % n = 0 -> Some(w)
    | _ -> None

let fizz x = (xzz 3 "Fizz") x

let buzz x = (xzz 5 "Buzz") x

let fizzBuzzer n k =
  match [fizz; buzz] |> List.choose (fun f -> f n) with
  | [] -> k(n.ToString())
  | x -> k(x |> List.reduce (+))

[<Test>]
let ``Validate that 2 can be Done`` () =
  (xzz 2 "Done") 2 |> should equal (Some("Done"))

[<Test>]
let ``Validate that 2 can not match`` () =
  (xzz 42 "Wrong") 2 |> should equal None

[<Test>]
let ``Validate that 6 is Fizz`` () =
  fizz 6 |> should equal (Some("Fizz"))

[<Test>]
let ``Validate that 5 is not Fizz`` () =
  fizz 5 |> should equal None

[<Test>]
let ``Validate that 10 is Buzz`` () =
  buzz 10 |> should equal (Some("Buzz"))

[<Test>]
let ``Validate that 3 is not Buzz`` () =
  buzz 3 |> should equal None

[<Test>]
let ``Validate that 2 is 2`` () =
  fizzBuzzer 2 id |> should equal "2"

[<Test>]
let ``Validate that k can be assert`` () =
  fizzBuzzer 2 (fun x -> Assert.AreEqual("2", x))

[<Test>]
let ``Validate that k can be shoulded`` () =
  fizzBuzzer 2 (fun x -> should equal "2" x)

[<Test>]
let ``Validate that 9 is Fizz`` () =
  fizzBuzzer 9 (fun x -> should equal "Fizz" x)

[<Test>]
let ``Validate that 20 is Buzz`` () =
  fizzBuzzer 20 (fun x -> should equal "Buzz" x)

[<Test>]
let ``Validate that 30 is FizzBuzz`` () =
  fizzBuzzer 30 (fun x -> should equal "FizzBuzz" x)