تعليمات برمجية الاقتباسات (F#)

This موضوع describes تعليمات برمجية quotations, a اللغة ميزة that enables you إلى توليد و work مع F# تعليمات برمجية expressions programmatically. This ميزة lets you توليد an abstract بناء الجملة شجرة that represents F# تعليمات برمجية. The abstract بناء الجملة شجرة can then be traversed و processed according إلى the needs of your تطبيق. For مثال, you can استخدم the شجرة إلى توليد F# تعليمات برمجية أو توليد تعليمات برمجية في some غير ذلك اللغة.

Quoted Expressions

A quoted تعبير هو an F# تعبير in your تعليمات برمجية that هو delimited in such a way that it ليس compiled كـ part of your برنامج, but instead هو compiled في an كائن that represents an F# تعبير. You can mark a quoted تعبير في واحد of الثاني ways: أما مع اكتب معلومات نوع المعلومات أو مسح مع. إذا أردت أن إلى تتضمن نوع المعلومات، واستخدمت في رموز <@و @>إلى التحديد التعبير بين علامات الاقتباس. إذا كنت لا تحتاج نوع المعلومات، استخدمت في رموز <@@و @@>. يلي تعليمات برمجية كتابة العروض و untyped الاقتباسات.

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

العبور شجرة قطر أيمن متوسط تعبير هو أسرع في حالة عدم تضمين معلومات النوع. نوع التعبير تطبق علامات الاقتباس مع رموز مكتوب الناتج هو Expr<'T>، الموقع h معلمة نوع كـ نوع التعبير كـ يفرضها المترجم F# استنتاج النوع خوارزمية. عند استخدام رمز اقتباس بدون معلومات النوع، ونوع التعبير بين علامات الاقتباس هو العام-غير اكتب تعبير. يمكنك استدعاء خاصية الخام تشغيل مكتوب Exprالفئة إلى الحصول تشغيل مصنف Exprالكائن.

هناك العديد من الأساليب الثابتة التي تسمح لك إلى إنشاء الكائنات التعبير F# برمجياً في Exprتطبق علامات الاقتباس الفئة بدون استخدام التعبيرات.

لاحظ أن تعليمات برمجية يجب أن يتضمن الاقتباس تعبير بكامل. ل letربط، على سبيل المثال، تحتاج كل من تعريف الاسم المنضم وإضافى تعبير الذي يستخدم ربط. في بناء جملة المطول، هذا هو تعبير الذي يلي inكلمة أساسية. في المستوى الأعلى في وحدة نمطية th هو هو فقط التعبير التالي في وحدة نمطية?، ولكن اقتباس، فإنه هو المطلوبة بشكل صريح.

ولذلك، التعبير التالي هو غير صالح.

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

ولكن التعابير التالية صالح.

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

لاستخدام تعليمات برمجية اقتباس، يجب عليك إضافة إعلان استيراد (باستخدام openالكلمة الأساسية) الذي يفتح مساحة الاسم Microsoft.FSharp.Quotations .

PowerPack F# بتوفير الدعم لتقييم وتنفيذ F# تعبير الكائنات.

تعبير نوع

مثيل Exprيمثل نوع F رقم تعبير. كلاهما في العام وعام غير Exprأنواع موثقة في F# مكتبة الوثائق. للمزيد من المعلومات، راجع مساحة الاسم Microsoft.FSharp.Quotations (F #) وفئة Quotations.Expr (F #).

عوامل تشغيل splicing

splicing إمكانية يجمع حرفية تعليمات برمجية الاقتباسات بالتعبيرات التي قمت بإنشائها برمجياً أو من آخر تعليمات برمجية اقتباس. %و %%العوامل تتيح لك إضافة F# تعبير كائن في تعليمات برمجية اقتباس. استخدام %operaإلىr إلى إدراج كائن تعبير مكتوب في إلى اقتباس مكتوب؛ واستخدام %%operaإلىr إلى إدراج كائن مصنف تعبير في إلى على اقتباس مصنف. تكون كلا العوامل الأحادية بادئة عوامل. وبالتالي إذا exprهو تعبير مصنف من النوع Expr، التعليمة البرمجية التالية هو صالح.

<@@ 1 + %%expr @@>

وإذا كان exprهو اقتباس مكتوب من النوع Expr<int>، التعليمة البرمجية التالية هو صالح.

<@ 1 + %expr @>

المثال

الوصف

يوضح المثال التالي استخدام تعليمات برمجية الاقتباسات إلى وضع الرمز F# في إلى تعبير الكائن، ثم الطباعة ب # رمز يمثل التعبير. تعمل A printlnهو المعرف الذي يحتوي على دالة العودية printذلك الكائن التعبير dهوplays ب # (من نوع Expr) في تنسيق مألوف. هناك عدة نماذج النشطة في Microsoft.FSharp.Quotations.أنماط ووحدات Microsoft.FSharp.Quotations.Derivedأنماط "التي يمكن استخدامها إلى تحليل التعبير الكائنات. لا يتضمن هذا المثال الجميع الممكنة أنماط التي قد تظهر في تعبير ب #. أي غير معروف تحث نقش مطابقة لنمط أحرف البدل ( _) و هو تقديمها باستخدام ToStringالأسلوب، أي، تشغيل Exprاكتب، تسمح لك بمعرفة النمط النشط لإضافة إلى تعبير مطابق.

الرمز

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 @@>

الإخراج

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

المثال

الوصف

يمكنك أيضا استخدام أنماط النشطة الثلاثة في وحدة نمطية? ExprShape إلى تجاوز أشجار التعبير ذات أنماط النشطة أقل. هذه الأنماط النشط يكون مفيداً عندما تريد إلى تجاوز شجرة ولكن لا تحتاج الجميع المعلومات الموجودة في معظم العقد. عندما كنت استخدم هذه النقوش، أي تعبير F# يطابق واحد النقوش الثلاثة التالية: ShapeVarإذا كان التعبير هو متغير ما،ShapeLambdaإذا كان التعبير هو تعبير lambda، أوShapeCombinationإذا كان التعبير هو شئ. إذا تجاوز في شجرة تعبير باستخدام أنماط النشطة كما في السابق تعليمات برمجية المثال، يجب عليك استخدام العديد من الأنماط أكثر لمعالجة الجميع المحتملة ب # التعبير أنواع، وكان تعليمات برمجية ستكون أكثر تعقيداً. لمزيد من المعلومات، راجع نقش ExprShape.ShapeVar|ShapeLambda|ShapeCombination Active Directory (F #).

يمكن استخدام مثال التعليمة البرمجية التالية كأساس ل traversals أكثر تعقيداً. في ترتيب هو تعليمات برمجية، في شجرة تعبير هو تاريخ الإنشاء لتعبير يتضمن استدعاء دالة، add. SpecificCall النشطة نقش الذي يستخدم للكشف عن أي استدعاء addفي شجرة التعبيرات. هذه النشطة نقش يقوم بتعيين وسيطات للاستدعاء إلى exprListالقيمة. في ترتيب هو الحالة، هناك فقط الثاني، حتى تلك يتم سحبها ودالة هو تسمى بصورة متكررة تشغيل الوسيطات. يتم إدراج نتائج في تعليمات برمجية اقتباس الذي يمثل استدعاء mulباستخدام عامل التشغيل splice ( %%). printlnالدالة من المثال السابق هو استخدام dهوplay نتائج.

يعيد تعليمات برمجية في فروع نقش النشطة الأخرى فقط إنشاء شجرة التعبير نفسه، لذلك تغيير فقط في التعبير الناتج هو تغيير من addإلى mul.

الرمز

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

الإخراج

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

راجع أيضًا:

موارد أخرى

مرجع لغة ب #