//[snippet: Clojure-like syntax sugar] //needs to install the F# PowerPack open Microsoft.FSharp.Quotations open Microsoft.FSharp.Quotations.DerivedPatterns open Microsoft.FSharp.Quotations.ExprShape open Microsoft.FSharp.Linq.QuotationEvaluation let _0<'T> : 'T = failwith "placeholder" let _1<'T> : 'T = failwith "placeholder" let _2<'T> : 'T = failwith "placeholder" let _3<'T> : 'T = failwith "placeholder" let _4<'T> : 'T = failwith "placeholder" let _5<'T> : 'T = failwith "placeholder" let _6<'T> : 'T = failwith "placeholder" let _7<'T> : 'T = failwith "placeholder" let _8<'T> : 'T = failwith "placeholder" let _9<'T> : 'T = failwith "placeholder" let L (expr : Expr<'T>) : 'U = let rec iter acc expr = let f acc name ty = let var, acc = acc |> List.tryFind (fun (v:Var) -> v.Name = name) |> function | Some(var) -> var, acc | None -> let var = Var(name, ty) var, var::acc Expr.Var(var), acc match expr with | ShapeVar(_) as v -> v, acc | ShapeLambda(var, expr) -> let expr, acc = iter acc expr Expr.Lambda(var, expr), acc | SpecificCall <@ _0 @> (_,[ty],_) -> f acc "_0" ty | SpecificCall <@ _1 @> (_,[ty],_) -> f acc "_1" ty | SpecificCall <@ _2 @> (_,[ty],_) -> f acc "_2" ty | SpecificCall <@ _3 @> (_,[ty],_) -> f acc "_3" ty | SpecificCall <@ _4 @> (_,[ty],_) -> f acc "_4" ty | SpecificCall <@ _5 @> (_,[ty],_) -> f acc "_5" ty | SpecificCall <@ _6 @> (_,[ty],_) -> f acc "_6" ty | SpecificCall <@ _7 @> (_,[ty],_) -> f acc "_7" ty | SpecificCall <@ _8 @> (_,[ty],_) -> f acc "_8" ty | SpecificCall <@ _9 @> (_,[ty],_) -> f acc "_9" ty | ShapeCombination(obj, []) -> RebuildShapeCombination(obj, []), acc | ShapeCombination(obj, exprs) -> let exprs, acc = let e, a = iter acc (List.head exprs) List.tail exprs |> List.fold (fun (es, a) e -> let e, a = iter a e (e::es, a) ) ([e], a) let exprs = List.rev exprs RebuildShapeCombination(obj, exprs), acc let rec buildLambda acc expr = match acc with | [] -> expr | var::acc -> Expr.Lambda(var, expr) |> buildLambda acc let expr, acc = iter [] expr let acc = acc |> List.sortWith (fun a b -> compare b a) let expr: Expr<'U> = Expr.Cast(buildLambda acc expr) expr.Compile() () //[/snippet] //[snippet: examples] L<@ _1 + _0 + _1 + _0 @> 1 2 |> printfn "%d" let tuple : int * int = L<@ (_1 + _3, _0 + _2) @> 0 1 2 3 printfn "%A" tuple [0..2] |> List.map (L<@ (_0 + 1).ToString() @>) |> List.reduce (+) |> printfn "%s" //[/snippet]