6 people like it.
Like the snippet!
Clojure-like lambda function syntax
This snippet implements a Clojure-like lambda function syntax using Code Quotations. However, this implementation is slow and, moreover, not type-safe. So I'm looking for a way to solve the issues.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
|
//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() ()
|
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
|
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"
|
namespace Microsoft
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Quotations
module DerivedPatterns
from Microsoft.FSharp.Quotations
module ExprShape
from Microsoft.FSharp.Quotations
namespace Microsoft.FSharp.Linq
val failwith : message:string -> 'T
Full name: Microsoft.FSharp.Core.Operators.failwith
val L : expr:Expr<'T> -> 'U
Full name: Script.L
val expr : Expr<'T>
Multiple items
type Expr =
override Equals : obj:obj -> bool
member GetFreeVars : unit -> seq<Var>
member Substitute : substitution:(Var -> Expr option) -> Expr
member ToString : full:bool -> string
member CustomAttributes : Expr list
member Type : Type
static member AddressOf : target:Expr -> Expr
static member AddressSet : target:Expr * value:Expr -> Expr
static member Application : functionExpr:Expr * argument:Expr -> Expr
static member Applications : functionExpr:Expr * arguments:Expr list list -> Expr
...
Full name: Microsoft.FSharp.Quotations.Expr
--------------------
type Expr<'T> =
inherit Expr
member Raw : Expr
Full name: Microsoft.FSharp.Quotations.Expr<_>
val iter : (Var list -> Expr -> Expr * Var list)
val acc : Var list
val expr : Expr
val f : (Var list -> string -> System.Type -> Expr * Var list)
val name : string
val ty : System.Type
val var : Var
Multiple items
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list
Full name: Microsoft.FSharp.Collections.List<_>
val tryFind : predicate:('T -> bool) -> list:'T list -> 'T option
Full name: Microsoft.FSharp.Collections.List.tryFind
val v : Var
Multiple items
type Var =
interface IComparable
new : name:string * typ:Type * ?isMutable:bool -> Var
member IsMutable : bool
member Name : string
member Type : Type
static member Global : name:string * typ:Type -> Var
Full name: Microsoft.FSharp.Quotations.Var
--------------------
new : name:string * typ:System.Type * ?isMutable:bool -> Var
property Var.Name: string
union case Option.Some: Value: 'T -> Option<'T>
union case Option.None: Option<'T>
static member Expr.Var : variable:Var -> Expr
active recognizer ShapeVar: Expr -> Choice<Var,(Var * Expr),(obj * Expr list)>
Full name: Microsoft.FSharp.Quotations.ExprShape.( |ShapeVar|ShapeLambda|ShapeCombination| )
val v : Expr
active recognizer ShapeLambda: Expr -> Choice<Var,(Var * Expr),(obj * Expr list)>
Full name: Microsoft.FSharp.Quotations.ExprShape.( |ShapeVar|ShapeLambda|ShapeCombination| )
static member Expr.Lambda : parameter:Var * body:Expr -> Expr
active recognizer SpecificCall: Expr -> Expr -> (Expr option * System.Type list * Expr list) option
Full name: Microsoft.FSharp.Quotations.DerivedPatterns.( |SpecificCall|_| )
val _0<'T> : 'T
Full name: Script._0
val _1<'T> : 'T
Full name: Script._1
val _2<'T> : 'T
Full name: Script._2
val _3<'T> : 'T
Full name: Script._3
val _4<'T> : 'T
Full name: Script._4
val _5<'T> : 'T
Full name: Script._5
val _6<'T> : 'T
Full name: Script._6
val _7<'T> : 'T
Full name: Script._7
val _8<'T> : 'T
Full name: Script._8
val _9<'T> : 'T
Full name: Script._9
active recognizer ShapeCombination: Expr -> Choice<Var,(Var * Expr),(obj * Expr list)>
Full name: Microsoft.FSharp.Quotations.ExprShape.( |ShapeVar|ShapeLambda|ShapeCombination| )
Multiple items
val obj : obj
--------------------
type obj = System.Object
Full name: Microsoft.FSharp.Core.obj
val RebuildShapeCombination : shape:obj * arguments:Expr list -> Expr
Full name: Microsoft.FSharp.Quotations.ExprShape.RebuildShapeCombination
val exprs : Expr list
val e : Expr
val a : Var list
val head : list:'T list -> 'T
Full name: Microsoft.FSharp.Collections.List.head
val tail : list:'T list -> 'T list
Full name: Microsoft.FSharp.Collections.List.tail
val fold : folder:('State -> 'T -> 'State) -> state:'State -> list:'T list -> 'State
Full name: Microsoft.FSharp.Collections.List.fold
val es : Expr list
val rev : list:'T list -> 'T list
Full name: Microsoft.FSharp.Collections.List.rev
val buildLambda : (Var list -> Expr -> Expr)
val sortWith : comparer:('T -> 'T -> int) -> list:'T list -> 'T list
Full name: Microsoft.FSharp.Collections.List.sortWith
val a : Var
val b : Var
val compare : e1:'T -> e2:'T -> int (requires comparison)
Full name: Microsoft.FSharp.Core.Operators.compare
val expr : Expr<'U>
static member Expr.Cast : source:Expr -> Expr<'T>
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val tuple : int * int
Full name: Script.tuple
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
val map : mapping:('T -> 'U) -> list:'T list -> 'U list
Full name: Microsoft.FSharp.Collections.List.map
val reduce : reduction:('T -> 'T -> 'T) -> list:'T list -> 'T
Full name: Microsoft.FSharp.Collections.List.reduce
More information