// AOP in F# - using nothing unusual except mutable functions open System; type Gexpr = interface end; type expr = | Num of int | Plus of Gexpr * Gexpr interface Gexpr;; let mutable fact = fun (x:int) -> 1;; // trick for recursive lambdas fact <- fun n -> if n<2 then 1 else n*fact(n-1);; let mutable fstr = fun (s:string) -> s.Length;; let mutable println = fun (s:string) -> Console.WriteLine(s);; let main() = let x = fact(fstr("abcd")) println(string(x));; //main();; /////// aspect oriented interceptors: let Trace(target:unit->unit) = let pfact = fact let pfstr = fstr // simulate dynamic scoping let mutable cx = 1; // controls number of times advice is used. // note proper closure fact <- fun n -> let ccx = cx if cx>0 then // advice not executed on recursive calls printfn "factorial called with argument %d" n cx <- cx-1 let y = pfact(n) if (ccx>0) then printfn "factoral returning value %d" y y; fstr <- fun s -> printfn "fstr called on string %s" s let y = pfstr(s) printfn "fstr returning %d" y y; target(); // execute target fact <- pfact // exit dynamic scope fstr <- pfstr;; // how to distinguish between recursive and outer calls? Trace(main);; printfn "factorial of 5 is %d" (fact(5));; let rec eval = function | Num(n) -> n | Plus(x,y) -> eval(x) + eval(y);;