Sdílet prostřednictvím


Kód nabídky (F#)

Toto téma popisuje Kód nabídky, funkce jazyka, která umožňuje generovat a pracovat s výrazy kódu F# programově.Tato funkce umožňuje generovat strom abstraktní syntaxe, která představuje kód F#.Strom abstraktní syntaxe lze potom vyčerpán a zpracované podle potřeb aplikace.Například stromu můžete generovat kód F# nebo generovat kód v jiný jazyk.

Nabízené výrazy

A kotované výraz je výraz F# ve svém kódu, který je vymezen tak, že není zkompilován jako součást programu, ale namísto toho je kompilován do objektu, který představuje výraz F#.Můžete označit výraz v uvozovkách dvěma způsoby: buď typ informací nebo bez informací o typu.Pokud chcete zahrnout typ informace, pomocí symbolů<@ a @> pro vymezení výrazu v uvozovkách.Pokud nepotřebujete typ informace, pomocí symbolů <@@ a @@>.Následující kód ukazuje zadali a bez typu nabídky.

open Microsoft.FSharp.Quotations
// A typed code quotation.
let expr : Expr<int> = <@ 1 + 1 @>
// An untyped code quotation.
let expr2 : Expr = <@@ 1 + 1 @@>

Procházení stromu velké výraz je rychlejší, pokud neobsahují informace o typu.Výsledný výraz zadaný symboly kotované typ je Expr<'T>, kde má parametr typu Typ výrazu se stanoví algoritmus odvození typu kompilátor F#.Při použití kódu kurzy bez informace o typu typ nabízené výraz je typu Obecné výraz.Můžete zavolat Raw zadanou vlastnost Expr třídy získat netypovou Expr objektu.

Existuje mnoho různých statické metody, které umožňují generovat F# výraz objekty programově v Expr bez použití třídy uvedené výrazy.

Všimněte si, že kód nabídky musí obsahovat celý výraz.Pro let vazbu, například potřebujete definice vázané název a další výraz, který používá vazba.V syntaxi verbose je výraz, který následuje in klíčové slovo.Na nejvyšší úrovni v modulu je to jen další výraz v modulu, ale do nabídky je výslovně požadovány.

Proto následující výraz není platný.

// Not valid:
// <@ let f x = x + 1 @>

Ale následující výrazy jsou platné.

// Valid:
<@ let f x = x + 10 in f 20 @>
// Valid:
<@ 
    let f x = x + 10
    f 20
@>

Kód nabídky použít, musíte přidat dovozní prohlášení (pomocí open klíčové slovo), otevře Microsoft.FSharp.Quotations oboru názvů.

F# PowerPack poskytuje podporu pro hodnocení a provádění výraz objekty F#.

Výraz typu

Instanci Expr typ představuje výraz F#.Obecného a neobecnou Expr typy jsou popsány v dokumentaci knihovny F#.Další informace naleznete v tématu Obor názvů Microsoft.FSharp.Quotations (F#) a Třída Quotations.Expr (F#).

Splétání operátory

Splétání umožňuje kombinovat literál kód nabídky s výrazy, které jste vytvořili pomocí programu nebo z nabídky jiný kód.% a %% operátory umožňují přidání objektu F# výraz do nabídky kód.Použití % operátor výraz zadaný objekt vložit do typové nabídky; použití %% operátor do netypovou nabídky Vložit objekt bez typu výrazu.Oba operátory jsou unární operátory předponu.Proto pokud expr je výraz bez typu typu Expr, následující kód je neplatný.

<@@ 1 + %%expr @@>

A pokud expr je zadaný nabídky typu Expr<int>, následující kód je neplatný.

<@ 1 + %expr @>

Příklad

Dd233212.collapse_all(cs-cz,VS.110).gifDescription

Následující příklad ukazuje kód kotace F# kód umístit do objektu výraz a potom vytisknout F# kód, který představuje výraz.Funkce println je definován rekurzivní funkci, která obsahuje print zobrazující výraz objekt F# (typu Expr) popisný formát.Existuje několik aktivních vzorky v Microsoft.FSharp.Quotations.Patterns a Microsoft.FSharp.Quotations.DerivedPatterns moduly, které lze použít k analýze výrazu objekty.V tomto příkladu neobsahuje možné vzorky, které se zobrazují ve výrazu F#.Žádné nerozpoznaná vzorek spustí odpovídající vzoru zástupné (_) a je vykreslen pomocí ToString metoda, který na Expr zadejte umožňuje zjistit aktivní vzorek přidat do výrazu shoda.

Dd233212.collapse_all(cs-cz,VS.110).gifKód

module Print
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
open Microsoft.FSharp.Quotations.DerivedPatterns

let println expr =
    let rec print expr =
        match expr with
        | Application(expr1, expr2) ->
            // Function application.
            print expr1
            printf " "
            print expr2
        | SpecificCall <@@ (+) @@> (_, _, exprList) ->
            // Matches a call to (+). Must appear before Call pattern.
            print exprList.Head
            printf " + "
            print exprList.Tail.Head
        | Call(exprOpt, methodInfo, exprList) ->
            // Method or module function call.
            match exprOpt with
            | Some expr -> print expr
            | None -> printf "%s" methodInfo.DeclaringType.Name
            printf ".%s(" methodInfo.Name
            if (exprList.IsEmpty) then printf ")" else
            print exprList.Head
            for expr in exprList.Tail do
                printf ","
                print expr
            printf ")"
        | Int32(n) ->
            printf "%d" n
        | Lambda(param, body) ->
            // Lambda expression.
            printf "fun (%s:%s) -> " param.Name (param.Type.ToString())
            print body
        | Let(var, expr1, expr2) ->
            // Let binding.
            if (var.IsMutable) then
                printf "let mutable %s = " var.Name
            else
                printf "let %s = " var.Name
            print expr1
            printf " in "
            print expr2
        | PropertyGet(_, propOrValInfo, _) ->
            printf "%s" propOrValInfo.Name
        | String(str) ->
            printf "%s" str
        | Value(value, typ) ->
            printf "%s" (value.ToString())
        | Var(var) ->
            printf "%s" var.Name
        | _ -> printf "%s" (expr.ToString())
    print expr
    printfn ""


let a = 2

// exprLambda has type "(int -> int)".
let exprLambda = <@ fun x -> x + 1 @>
// exprCall has type unit.
let exprCall = <@ a + 1 @>

println exprLambda
println exprCall
println <@@ let f x = x + 10 in f 10 @@>

Dd233212.collapse_all(cs-cz,VS.110).gifVýsledek

fun (x:System.Int32) -> x + 1
a + 1
let f = fun (x:System.Int32) -> x + 10 in f 10

Příklad

Dd233212.collapse_all(cs-cz,VS.110).gifDescription

Můžete také použít tři vzorky aktivní v ExprShape modulu procházet výraz stromů s méně aktivní vzorky.Tyto vzorky aktivní může být užitečné, když chcete procházet strom, ale všechny informace, které jsou ve většině uzlů není nutné.Při použití těchto vzorků libovolný výraz F# odpovídá jedné z následujících tří vzorků: ShapeVar Pokud výraz je proměnná, ShapeLambda Pokud lambda výraz, je výraz nebo ShapeCombination Pokud je výraz jiný.Pokud ve stromu výraz můžete procházet pomocí aktivní vzorky jako v předchozím příkladu kódu, je nutné použít mnoho další vzorky všech možných F# výraz typy a kód bude složitější.Další informace naleznete v tématu ExprShape.ShapeVar|ShapeLambda|ShapeCombination aktivní vzorek (F#).

Následující příklad kódu lze použít jako základ pro složitější znaky pro přechod na.V tomto kódu je vytvořen ve stromu výraz pro výraz, který vyžaduje volání funkce add.SpecificCall aktivní vzorek se používá k rozpoznání kterékoli volání add ve stromu výraz.Tento vzorek aktivní přiřadí argumenty volání exprList hodnotu.V tomto případě existují pouze dvě tyto jsou vyžádány a funkce tdidisconnect() na argumenty.Výsledky se vloží do nabídky kód představující volání mul pomocí operátoru uživatele programu splice (%%).println z předchozího příkladu funkce se používá k zobrazení výsledků.

Kód v jiných pobočkách aktivní vzorek pouze obnovuje stejném stromu výraz tak pouze změna výsledný výraz je změna z add na mul.

Dd233212.collapse_all(cs-cz,VS.110).gifKód

module Module1
open Print
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.DerivedPatterns
open Microsoft.FSharp.Quotations.ExprShape

let add x y = x + y
let mul x y = x * y

let rec substituteExpr expression =
    match expression with
    | SpecificCall <@@ add @@> (_, _, exprList) ->
        let lhs = substituteExpr exprList.Head
        let rhs = substituteExpr exprList.Tail.Head
        <@@ mul %%lhs %%rhs @@>
    | ShapeVar var -> Expr.Var var
    | ShapeLambda (var, expr) -> Expr.Lambda (var, substituteExpr expr)
    | ShapeCombination(shapeComboObject, exprList) ->
        RebuildShapeCombination(shapeComboObject, List.map substituteExpr exprList)

let expr1 = <@@ 1 + (add 2 (add 3 4)) @@>
println expr1
let expr2 = substituteExpr expr1
println expr2

Dd233212.collapse_all(cs-cz,VS.110).gifVýsledek

1 + Module1.add(2,Module1.add(3,4))
1 + Module1.mul(2,Module1.mul(3,4))

Viz také

Další zdroje

F# Language Reference