(* A closure is a lambda term with free variables. We can think of a closure as consisting of two parts: one part refers to the lambda expression - the source code, and another part refers to a context, or environment, that binds values to its free variables. So lambda x.x+y, for example, can be part of multiple closures each with a different binding for y. A closure that mutates its free variables is "stateful". Such a closure itself mutates. *) open System // accumulator: let make_accumulator init = let mutable x = init fun y -> x <- x + y x // make_accumulator let a1 = make_accumulator 0 let a2 = make_accumulator 0 printfn "%d" (a1 2); printfn "%d" (a1 2); printfn "%d" (a1 2); // a1 itself mutates printfn "%d" (a2 2); /////// bank accounts (simulates objects) let make_account init = let mutable balance = init let inquiry = fun x -> printfn "balance = %d" balance; let withdraw amt = if amt>0 && amt0 then balance <- balance + amt; else printfn "invalid transaction" let public_interface req = match req with | "inquiry" -> inquiry | "deposit" -> deposit | "withdraw" -> withdraw | _ -> printfn "invalid request"; fun x -> () public_interface;; // body of make_account returns the public interface // make_account // convenient ways to call methods let withdraw acc amt = (acc "withdraw" amt); let deposit acc amt = (acc "deposit" amt); let inquiry acc = (acc "inquiry" 0); let ac1 = make_account 1000 let ac2 = make_account 2000 withdraw ac1 500 deposit ac2 200 withdraw ac2 100 inquiry ac1 inquiry ac2;; // #load "closures.fsx"; open Closures;;