2012-04-14 24 views

回答

7

deepMacroExpandUntil功能是相當簡單的工具,只做了兩件事情:

  • 它取代了所有的方法與ReflectedDefinition屬性與方法的主體要求
  • 減少了IT拉姆達的應用,使(fun x -> x * x) (1+2)將成爲(1+2)*(1+2)

編寫一些報價處理代碼時這很有用,但是更新版本的F#包括ExprShape個活動模式,使得手動編寫報價處理變得非常容易。

要實現類似deepMacroExpandUntil,你會寫是這樣的:

open Microsoft.FSharp.Quotations 

/// The parameter 'vars' is an immutable map that assigns expressions to variables 
/// (as we recursively process the tree, we replace all known variables) 
let rec expand vars expr = 
    // First recursively process & replace variables 
    let expanded = 
    match expr with 
    // If the variable has an assignment, then replace it with the expression 
    | ExprShape.ShapeVar v when Map.containsKey v vars -> vars.[v] 
    // Apply 'expand' recursively on all sub-expressions 
    | ExprShape.ShapeVar v -> Expr.Var v 
    | Patterns.Call(body, DerivedPatterns.MethodWithReflectedDefinition meth, args) -> 
     let this = match body with Some b -> Expr.Application(meth, b) | _ -> meth 
     let res = Expr.Applications(this, [ for a in args -> [a]]) 
     expand vars res 
    | ExprShape.ShapeLambda(v, expr) -> 
     Expr.Lambda(v, expand vars expr) 
    | ExprShape.ShapeCombination(o, exprs) -> 
     ExprShape.RebuildShapeCombination(o, List.map (expand vars) exprs) 
    // After expanding, try reducing the expression - we can replace 'let' 
    // expressions and applications where the first argument is lambda 
    match expanded with 
    | Patterns.Application(ExprShape.ShapeLambda(v, body), assign) 
    | Patterns.Let(v, assign, body) -> 
     expand (Map.add v (expand vars assign) vars) body 
    | _ -> expanded 

下面的例子顯示功能的兩個方面 - 它取代了功能foo其身體,然後替換應用程序,所以你最終了(10 + 2) * (10 + 2)

[<ReflectedDefinition>] 
let foo a = a * a 

expand Map.empty <@ foo (10 + 2) @> 

編輯:我也貼樣品F# snippets