5 people like it.

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.

Clojure-like syntax sugar

 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() ()

examples

 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

Link:http://fssnip.net/8i
Posted:5 years ago
Author:einblicker
Tags: quotations