Aracılığıyla paylaş


Hesaplama ifadeleri (F#)

F# hesaplama ifadeleri sıralı ve Birleşik denetim akışı yapıları ve bağlar kullanarak hesaplamaları yazma için kullanışlı bir sözdizimi sağlar. Sağlamak için uygun sözdizimi için kullanılabilir monads, veri, Denetim ve işlevsel programlarda yan etkileri yönetmek için kullanılan bir işlevsel programlama özelliği.

Yerleşik iş akışı

Zaman uyumsuz iş akışları ve sorgu ifadeleri gibi sıra bir hesaplama ifadesi örneği deyimleridir. Daha fazla bilgi için bkz: sıralarını, Zaman uyumsuz iş akışları, ve Sorgu ifadelerini.

Belirli özellikleri sıra ifadeleri ile zaman uyumsuz iş akışları ortak ve hesaplama ifadesi için temel sözdizimi gösterilmektedir:

builder-name { expression }

Önceki sözdizimi verilen deyim tarafından belirtilen türde hesaplama ifadesi olduğunu belirtir builder-name. Hesaplama ifadesi bir yerleşik iş akışı gibi olabilir seq veya async, ya da tanımladığınız bir şey olabilir. builder-name Tanımlayıcısı olarak bilinen özel bir türü örneği için builder türü. Oluşturucu, bu denetimleri nasıl deyimi yürütür hesaplaması ifadenin parçalarını, yani kod birleştirilme şeklini yöneten özel yöntemleri tanımlayan bir sınıf türü türüdür. Builder sınıfı açıklamak için başka bir döngüler ve bağlar gibi birçok F# yapılar, işlemi özelleştirmek sağlar olduğunu söylemek yoludur.

Hesaplama ifadelerde iki bazı ortak dil yapıları için kullanılabilir. Varyant yapıları kullanarak başlatabileceğiniz bir! (bang) gibi bazı anahtar sözcükler soneki let!, do!ve benzeri. Bu özel formlar bu işlemleri sıradan yerleşik davranışını değiştirmek için Oluşturucu sınıfında tanımlanan belirli işlevleri neden. Bu formlar benzer yield! şeklinde yield sıra deyimlerde kullanılan anahtar sözcüğü. Daha fazla bilgi için bkz: sıralarını.

Yeni bir hesaplama ifadesi türü oluşturma

Builder sınıfı oluşturma ve bazı özel yöntemler sınıfını tanımlayan kendi hesaplama ifadeleri özellikleri tanımlayabilirsiniz. Builder sınıfı, isteğe bağlı olarak aşağıdaki tabloda listelenen yöntemleri tanımlayabilir.

Aşağıdaki tabloda, iş akışı builder sınıfında kullanılan yöntemleri açıklar.

Method

Tipik imza(lar)

Description

Bind

M<'T> * ('T -> M<'U>) -> M<'U>

İçin adlı let! ve do! hesaplaması ifadelerde.

Delay

(unit -> M<'T>) -> M<'T>

Bir hesaplama ifadesi bir işlev olarak kaydırılır.

Return

'T -> M<'T>

İçin adlı return hesaplaması ifadelerde.

ReturnFrom

M<'T> -> M<'T>

İçin adlı return! hesaplaması ifadelerde.

Run

M<'T> -> M<'T>veya

M<'T> -> 'T

Hesaplama deyimi yürütür.

Combine

M<'T> * M<'T> -> M<'T>veya

M<unit> * M<'T> -> M<'T>

Hesaplama ifadelerde sıralaması için denir.

For

seq<'T> * ('T -> M<'U>) -> M<'U>veya

seq<'T> * ('T -> M<'U>) -> seq<M<'U>>

İçin adlı for...do hesaplaması ifadelerde ifadeler.

TryFinally

M<'T> * (unit -> unit) -> M<'T>

İçin adlı try...finally hesaplaması ifadelerde ifadeler.

TryWith

M<'T> * (exn -> M<'T>) -> M<'T>

İçin adlı try...with hesaplaması ifadelerde ifadeler.

Using

'T * ('T -> M<'U>) -> M<'U> when 'U :> IDisposable

İçin adlı use hesaplaması ifadelerde bağlar.

While

(unit -> bool) * M<'T> -> M<'T>

İçin adlı while...do hesaplaması ifadelerde ifadeler.

Yield

'T -> M<'T>

İçin adlı yield hesaplaması ifadelerde ifadeler.

YieldFrom

M<'T> -> M<'T>

İçin adlı yield! hesaplaması ifadelerde ifadeler.

Zero

unit -> M<'T>

İçin boş olarak adlandırılan else , dalları if...then hesaplaması ifadelerde ifadeler.

Birçok builder sınıfı yöntemleri kullanın ve dönüş bir M<'T> genellikle, örneğin birleştirilmiş hesaplamaları türünü belirtir bir ayrı ayrı tanımlanmış türüdür, yapı Async<'T> zaman uyumsuz iş akışları ve Seq<'T> sequence iş akışları. İleri bir yapı iş akışı nesnesi iletilmesi, bu yöntemlerin imza birleştirilir ve birbirleriyle iç içe etkinleştirin. Bir hesaplama ifadesi ayrıştırdığında, ifade bir dizi yuvalanmış işlev çağrılarının önceki tabloda yöntemleri ve hesaplama ifadesi kodu kullanarak derleyicisi.

İç içe ifade şu biçimde olabilir:

builder.Run(builder.Delay(fun () -> {| cexpr |}))

Yukarıdaki kodda yapılan Run ve Delay hesaplaması Deyim Oluşturucusu'nu sınıfta tanımlanmazsa atlanır. Gövde metni olarak burada belirtilen hesaplama ifadesi {| cexpr |}, Oluşturucu sınıfının yöntemlerini kapsayan çağrılarını aşağıdaki tabloda açıklanan çevirileri tarafından çevrilmiştir. Hesaplama ifadesi {| cexpr |} bu çevirileri tanımlı özyinelemeli olduğunu burada expr F# ifade edilir ve cexpr hesaplaması ifadesidir.

İfade

Çeviri

{| let binding in cexpr |}

let binding in {| cexpr |}

{| let! pattern = expr in cexpr |}

builder.Bind(expr, (fun pattern -> {| cexpr |}))

{| do! expr in cexpr |}

builder.Bind(expr1, (fun () -> {| cexpr |}))

{| yield expr |}

builder.Yield(expr)

{| yield! expr |}

builder.YieldFrom(expr)

{| return expr |}

builder.Return(expr)

{| return! expr |}

builder.ReturnFrom(expr)

{| use pattern = expr in cexpr |}

builder.Using(expr, (fun pattern -> {| cexpr |}))

{| use! value = expr in cexpr |}

builder.Bind(expr, (fun value -> builder.Using(value, (fun value -> {| cexpr |}))))

{| if expr then cexpr0 |}

if expr then {| cexpr0 |} else binder.Zero()

{| if expr then cexpr0 else cexpr1 |}

if expr then {| cexpr0 |} else {| cexpr1 |}

{| match expr with | pattern_i -> cexpr_i |}

match expr with | pattern_i -> {| cexpr_i |}

{| for pattern in expr do cexpr |}

builder.For(enumeration, (fun pattern -> {| cexpr }|))

{| for identifier = expr1 to expr2 do cexpr |}

builder.For(enumeration, (fun identifier -> {| cexpr }|))

{| while expr do cexpr |}

builder.While(fun () -> expr), builder.Delay({|cexpr |})

{| try cexpr with | pattern_i -> expr_i |}

builder.TryWith(builder.Delay({| cexpr |}), (fun value -> match value with | pattern_i -> expr_i | exn -> reraise exn)))

{| try cexpr finally expr |}

builder.TryFinally(builder.Delay( {| cexpr |}), (fun () -> expr))

{| cexpr1; cexpr2 |}

builder.Combine({|cexpr1 |}, {| cexpr2 |})

{| other-expr; cexpr |}

expr; {| cexpr |}

{| other-expr |}

expr; builder.Zero()

Önceki tablodaki other-expr aksi tabloda listelenmeyen bir ifade açıklar. Builder sınıfı tüm yöntemleri uygulayan ve destekleyen tüm önceki tabloda listelenen çevirileri gerek yoktur. Not implemented bu yapıları hesaplaması bu tür ifadelerde kullanılamaz. Desteklemek istemiyorsanız, örneğin, use anahtar sözcüğünü kendi hesaplaması ifadelerde kullanmayabilir tanımını Use builder sınıfınızın içinde.

Aşağıdaki kod örneği gibi bir dizi olabilir adımları tek adımda bir anda değerlendirilen hesaplayarak saklar bir hesaplama ifadesi gösterilir. Birleşim türü, a discriminated OkOrException, ifade hata durumunu şimdiye değerlendirilmesi olarak kodlar. Bu kod Oluşturucu yöntemlerden bazıları demirbaş uygulamaları gibi hesaplama ifadelerde kullanabileceğiniz birkaç tipik desenleri göstermektedir.

// Computations that can be run step by step
type Eventually<'T> =
    | Done of 'T
    | NotYetDone of (unit -> Eventually<'T>)

module Eventually =
    // The bind for the computations. Append 'func' to the
    // computation.
    let rec bind func expr =
        match expr with
        | Done value -> NotYetDone (fun () -> func value)
        | NotYetDone work -> NotYetDone (fun () -> bind func (work()))

    // Return the final value wrapped in the Eventually type.
    let result value = Done value

    type OkOrException<'T> =
    | Ok of 'T
    | Exception of System.Exception

    // The catch for the computations. Stitch try/with throughout
    // the computation, and return the overall result as an OkOrException.
    let rec catch expr =
        match expr with
        | Done value -> result (Ok value)
        | NotYetDone work ->
            NotYetDone (fun () ->
            let res = try Ok(work()) with | exn -> Exception exn
            match res with
            | Ok cont -> catch cont // note, a tailcall
            | Exception exn -> result (Exception exn))

    // The delay operator.
    let delay func = NotYetDone (fun () -> func())

    // The stepping action for the computations.
    let step expr =
        match expr with
        | Done _ -> expr
        | NotYetDone func -> func ()

    // The rest of the operations are boilerplate.
    // The tryFinally operator.
    // This is boilerplate in terms of "result", "catch", and "bind".
    let tryFinally expr compensation =
        catch (expr)
        |> bind (fun res -> compensation();
                            match res with
                            | Ok value -> result value
                            | Exception exn -> raise exn)

    // The tryWith operator.
    // This is boilerplate in terms of "result", "catch", and "bind".
    let tryWith exn handler =
        catch exn
        |> bind (function Ok value -> result value | Exception exn -> handler exn)

    // The whileLoop operator.
    // This is boilerplate in terms of "result" and "bind".
    let rec whileLoop pred body =
        if pred() then body |> bind (fun _ -> whileLoop pred body)
        else result ()

    // The sequential composition operator.
    // This is boilerplate in terms of "result" and "bind".
    let combine expr1 expr2 =
        expr1 |> bind (fun () -> expr2)
    
    // The using operator.
    let using (resource: #System.IDisposable) func =
        tryFinally (func resource) (fun () -> resource.Dispose())

    // The forLoop operator.
    // This is boilerplate in terms of "catch", "result", and "bind".
    let forLoop (collection:seq<_>) func =
        let ie = collection.GetEnumerator()
        tryFinally (whileLoop (fun () -> ie.MoveNext())
                     (delay (fun () -> let value = ie.Current in func value)))
                     (fun () -> ie.Dispose())

// The builder class.
type EventuallyBuilder() =
    member x.Bind(comp, func) = Eventually.bind func comp
    member x.Return(value) = Eventually.result value
    member x.ReturnFrom(value) = value
    member x.Combine(expr1, expr2) = Eventually.combine expr1 expr2
    member x.Delay(func) = Eventually.delay func
    member x.Zero() = Eventually.result ()
    member x.TryWith(expr, handler) = Eventually.tryWith expr handler
    member x.TryFinally(expr, compensation) = Eventually.tryFinally expr compensation
    member x.For(coll:seq<_>, func) = Eventually.forLoop coll func
    member x.Using(resource, expr) = Eventually.using resource expr

let eventually = new EventuallyBuilder()
    
let comp =
    eventually { for x in 1 .. 2 do
                    printfn " x = %d" x
                 return 3 + 4 }

// Try the remaining lines in F# interactive to see how this 
// computation expression works in practice.
let step x = Eventually.step x


// returns "NotYetDone <closure>"
comp |> step

// prints "x = 1"
// returns "NotYetDone <closure>"
comp |> step |> step


// prints "x = 1"
// prints "x = 2"
// returns "NotYetDone <closure>"
comp |> step |> step |> step |> step |> step |> step



// prints "x = 1"
// prints "x = 2"
// returns "Done 7"
comp |> step |> step |> step |> step |> step |> step |> step |> step

Bir hesaplama ifadesi deyim döndürür bir temel türü vardır. Temel türü hesaplanan sonucun ya da gerçekleştirilebilir gecikmiş bir hesaplama gösterebilir veya bazı koleksiyon türü yineleme yapmak için bir yol sağlayabilir. Önceki örnekte, temel alınan tür olan Eventually.Bir sıra için temel alınan tür ifadesidir IEnumerable<T>. Temel türü için bir sorgu ifadesi olan IQueryable<T>. Asychronous iş akışı için temel alınan tür olan zaman uyumsuz. Async Nesnesi, sonucu hesaplamak için gerçekleştirilecek çalışma gösterir. Örneğin, arama Async.RunSynchronously bir hesaplama yürütün ve sonuç.

Özel işlemler

Özel bir hesaplama ifadesi işlemi tanımlamak ve özel işlem hesaplaması ifade bir işleç olarak kullanın. Örneğin, bir sorgu ifadesinde sorgu işlecini ekleyebilirsiniz. Özel bir işlem tanımladığınızda, verim tanımlamak ve hesaplama ifadesi yöntemleri. Özel bir işlem tanımlamak için hesaplama ifadesi builder sınıfı koymak ve uygulayın CustomOperationAttribute. Bu öznitelik adı özel bir işlemde kullanılacak bir bağımsız değişken olarak bir dize alır. Baþýndaki açýlýþ küme parantezine hesaplaması ifade kapsam içine bu adı gelir. Bu nedenle, bu bloğu içinde özel bir işlem aynı ada sahip tanımlayıcıları kullanmamalısınız. Örneğin, tanımlayıcılar gibi kaçının all veya last sorgu ifadelerde.

Ayrıca bkz.

Başvuru

Zaman uyumsuz iş akışları (F#)

Sýralar (F#)

sorgu ifadelerini (F#)

Diğer Kaynaklar

F# dil başvurusu