Anonim Kayıtlar

Anonim kayıtlar, kullanımdan önce bildirilmesi gerekmeyen adlandırılmış değerlerin basit toplamlarıdır. Bunları yapı veya başvuru türü olarak bildirebilirsiniz. Bunlar varsayılan olarak başvuru türleridir.

Sözdizimi

Aşağıdaki örneklerde anonim kayıt söz dizimi gösterilmektedir. Olarak [item] ayrılmış öğeler isteğe bağlıdır.

// Construct an anonymous record
let value-name = [struct] {| Label1: Type1; Label2: Type2; ...|}

// Use an anonymous record as a type parameter
let value-name = Type-Name<[struct] {| Label1: Type1; Label2: Type2; ...|}>

// Define a parameter with an anonymous record as input
let function-name (arg-name: [struct] {| Label1: Type1; Label2: Type2; ...|}) ...

Temel kullanım

Anonim kayıtlar en iyi örnek oluşturmadan önce bildirilmesi gerekmeyen F# kayıt türleri olarak düşünülmesidir.

Örneğin, anonim kayıt oluşturan bir işlevle nasıl etkileşim kurabileceğinizi burada bulabilirsiniz:

open System

let getCircleStats radius =
    let d = radius * 2.0
    let a = Math.PI * (radius ** 2.0)
    let c = 2.0 * Math.PI * radius

    {| Diameter = d; Area = a; Circumference = c |}

let r = 2.0
let stats = getCircleStats r
printfn "Circle with radius: %f has diameter %f, area %f, and circumference %f"
    r stats.Diameter stats.Area stats.Circumference

Aşağıdaki örnek, giriş olarak anonim bir kayıt alan bir printCircleStats işlevle öncekini genişletir:

open System

let getCircleStats radius =
    let d = radius * 2.0
    let a = Math.PI * (radius ** 2.0)
    let c = 2.0 * Math.PI * radius

    {| Diameter = d; Area = a; Circumference = c |}

let printCircleStats r (stats: {| Area: float; Circumference: float; Diameter: float |}) =
    printfn "Circle with radius: %f has diameter %f, area %f, and circumference %f"
        r stats.Diameter stats.Area stats.Circumference

let r = 2.0
let stats = getCircleStats r
printCircleStats r stats

Giriş türüyle aynı "şekle" sahip olmayan herhangi bir anonim kayıt türüyle çağrı printCircleStats yapılamıyor:

printCircleStats r {| Diameter = 2.0; Area = 4.0; MyCircumference = 12.566371 |}
// Two anonymous record types have mismatched sets of field names
// '["Area"; "Circumference"; "Diameter"]' and '["Area"; "Diameter"; "MyCircumference"]'

Anonim kayıtları yapılandırma

Anonim kayıtlar isteğe bağlı struct anahtar sözcükle yapı olarak da tanımlanabilir. Aşağıdaki örnek, bir yapı anonim kaydı oluşturup kullanarak öncekini genişletmektedir:

open System

let getCircleStats radius =
    let d = radius * 2.0
    let a = Math.PI * (radius ** 2.0)
    let c = 2.0 * Math.PI * radius

    // Note that the keyword comes before the '{| |}' brace pair
    struct {| Area = a; Circumference = c; Diameter = d |}

// the 'struct' keyword also comes before the '{| |}' brace pair when declaring the parameter type
let printCircleStats r (stats: struct {| Area: float; Circumference: float; Diameter: float |}) =
    printfn "Circle with radius: %f has diameter %f, area %f, and circumference %f"
        r stats.Diameter stats.Area stats.Circumference

let r = 2.0
let stats = getCircleStats r
printCircleStats r stats

Yapılık çıkarımı

Yapı anonim kayıtları, çağrı sitesinde anahtar sözcüğünü belirtmeniz struct gerekmeyen "yapılık çıkarımına" da olanak sağlar. Bu örnekte, çağrılırken printCircleStatsanahtar sözcüğünü ilerletmiş struct olacaksınız:


let printCircleStats r (stats: struct {| Area: float; Circumference: float; Diameter: float |}) =
    printfn "Circle with radius: %f has diameter %f, area %f, and circumference %f"
        r stats.Diameter stats.Area stats.Circumference

printCircleStats r {| Area = 4.0; Circumference = 12.6; Diameter = 12.6 |}

Giriş türünün bir yapı anonim kaydı olmadığını belirten struct ters desen derlenemiyor.

Anonim kayıtları diğer türlere ekleme

Olayları kayıt olan ayrımcı birleşimler bildirmek yararlı olur. Ancak kayıtlardaki veriler ayrımcı birleşimle aynı türdeyse, tüm türleri karşılıklı özyinelemeli olarak tanımlamanız gerekir. Anonim kayıtların kullanılması bu kısıtlamayı önler. Aşağıda desenin üzerinde eşleşen bir örnek tür ve işlev verilmiştir:

type FullName = { FirstName: string; LastName: string }

// Note that using a named record for Manager and Executive would require mutually recursive definitions.
type Employee =
    | Engineer of FullName
    | Manager of {| Name: FullName; Reports: Employee list |}
    | Executive of {| Name: FullName; Reports: Employee list; Assistant: Employee |}

let getFirstName e =
    match e with
    | Engineer fullName -> fullName.FirstName
    | Manager m -> m.Name.FirstName
    | Executive ex -> ex.Name.FirstName

İfadeleri kopyalama ve güncelleştirme

Anonim kayıtlar, kopyalama ve güncelleştirme ifadeleriyle derlemeyi destekler. Örneğin, mevcut bir kaydın verilerini kopyalayan anonim bir kaydın yeni bir örneğini şu şekilde oluşturabilirsiniz:

let data = {| X = 1; Y = 2 |}
let data' = {| data with Y = 3 |}

Ancak, adlandırılmış kayıtların aksine anonim kayıtlar, kopyalama ve güncelleştirme ifadeleriyle tamamen farklı formlar oluşturmanıza olanak sağlar. Aşağıdaki örnek, önceki örnekteki aynı anonim kaydı alır ve yeni bir anonim kayda genişletir:

let data = {| X = 1; Y = 2 |}
let expandedData = {| data with Z = 3 |} // Gives {| X=1; Y=2; Z=3 |}

Adlandırılmış kayıtların örneklerinden anonim kayıtlar oluşturmak da mümkündür:

type R = { X: int }
let data = { X = 1 }
let data' = {| data with Y = 2 |} // Gives {| X=1; Y=2 |}

Ayrıca, başvuru ve yapı anonim kayıtlarına veri kopyalayabilirsiniz:

// Copy data from a reference record into a struct anonymous record
type R1 = { X: int }
let r1 = { X = 1 }

let data1 = struct {| r1 with Y = 1 |}

// Copy data from a struct record into a reference anonymous record
[<Struct>]
type R2 = { X: int }
let r2 = { X = 1 }

let data2 = {| r1 with Y = 1 |}

// Copy the reference anonymous record data into a struct anonymous record
let data3 = struct {| data2 with Z = r2.X |}

Anonim kayıtların özellikleri

Anonim kayıtlar, nasıl kullanılabileceğini tam olarak anlamak için gerekli olan bir dizi özelliğe sahiptir.

Anonim kayıtlar nominaldir

Anonim kayıtlar nominal türlerdir. Bunlar, ön bildirim gerektirmeyen adlandırılmış kayıt türleri (aynı zamanda nominaldir) olarak düşünülebilir.

İki anonim kayıt bildirimiyle aşağıdaki örneği göz önünde bulundurun:

let x = {| X = 1 |}
let y = {| Y = 1 |}

x ve y değerleri farklı türlerdedir ve birbiriyle uyumlu değildir. Bunlar eşitlenebilir değildir ve karşılaştırılabilir değildir. Bunu göstermek için adlandırılmış bir kayıt eşdeğeri düşünün:

type X = { X: int }
type Y = { Y: int }

let x = { X = 1 }
let y = { Y = 1 }

Tür eşdeğerliği veya karşılaştırmasıyla ilgili olarak adlandırılmış kayıt eşdeğerleriyle karşılaştırıldığında anonim kayıtlarda doğası gereği farklı bir şey yoktur.

Anonim kayıtlar yapısal eşitlik ve karşılaştırma kullanır

Kayıt türleri gibi anonim kayıtlar da yapısal olarak eşitlenebilir ve karşılaştırılabilir. Bu, yalnızca tüm kurucu türler kayıt türleri gibi eşitliği ve karşılaştırmayı destekliyorsa geçerlidir. Eşitliği veya karşılaştırmayı desteklemek için iki anonim kaydın aynı "şekle" sahip olması gerekir.

{| a = 1+1 |} = {| a = 2 |} // true
{| a = 1+1 |} > {| a = 1 |} // true

// error FS0001: Two anonymous record types have mismatched sets of field names '["a"]' and '["a"; "b"]'
{| a = 1 + 1 |} = {| a = 2;  b = 1|}

Anonim kayıtlar serileştirilebilir

Anonim kayıtları, adlandırılmış kayıtlarda olduğu gibi seri hale getirebilirsiniz. Newtonsoft.Json'ı kullanan bir örnek aşağıda verilmiştir:

open Newtonsoft.Json

let phillip' = {| name="Phillip"; age=28 |}
let philStr = JsonConvert.SerializeObject(phillip')

let phillip = JsonConvert.DeserializeObject<{|name: string; age: int|}>(philStr)
printfn $"Name: {phillip.name} Age: %d{phillip.age}"

Anonim kayıtlar, serileştirilmiş/seri durumdan çıkarılmış türleriniz için bir etki alanı tanımlamaya gerek kalmadan ağ üzerinden basit veriler göndermek için kullanışlıdır.

Anonim kayıtlar C# anonim türleriyle birlikte çalışabilir

C# anonim türlerinin kullanılmasını gerektiren bir .NET API'si kullanmak mümkündür. C# anonim türleri, anonim kayıtlar kullanılarak birlikte çalışabilir. Aşağıdaki örnekte anonim bir tür gerektiren LINQ aşırı yüklemesini çağırmak için anonim kayıtların nasıl kullanılacağı gösterilmektedir:

open System.Linq

let names = [ "Ana"; "Felipe"; "Emilia"]
let nameGrouping = names.Select(fun n -> {| Name = n; FirstLetter = n[0] |})
for ng in nameGrouping do
    printfn $"{ng.Name} has first letter {ng.FirstLetter}"

.NET genelinde kullanılan ve anonim bir tür geçirmeyi gerektiren çok sayıda başka API vardır. Anonim kayıtlar, bu kayıtlarla çalışmak için aracınızdır.

Sınırlamalar

Anonim kayıtların kullanımlarında bazı kısıtlamalar vardır. Bazıları kendi tasarımına göre değişir, ancak bazıları değişebilir.

Desen eşleştirme ile ilgili sınırlamalar

Anonim kayıtlar, adlandırılmış kayıtların aksine desen eşleştirmeyi desteklemez. Bunun üç nedeni vardır:

  1. Adlandırılmış kayıt türlerinden farklı olarak, bir desenin anonim kaydın her alanını hesaba eklemesi gerekir. Bunun nedeni anonim kayıtların yapısal alt stili desteklememesidir; bunlar nominal türlerdir.
  2. (1) nedeniyle, her bir ayrı desen farklı bir anonim kayıt türü anlamına olacağından, desen eşleştirme ifadesinde ek desenlere sahip olma olanağı yoktur.
  3. (2) nedeniyle, herhangi bir anonim kayıt deseni "nokta" gösteriminden daha ayrıntılı olacaktır.

Sınırlı bağlamlarda desen eşleştirmeye izin vermek için bir açık dil önerisi vardır.

Mutability ile ilgili sınırlamalar

Şu anda verilerle mutable anonim kayıt tanımlamak mümkün değildir. Değiştirilebilir verilere izin vermek için açık bir dil önerisi vardır.

Yapı anonim kayıtlarıyla ilgili sınırlamalar

Yapı anonim kayıtlarını veya IsReadOnlyolarak IsByRefLike bildirmek mümkün değildir. ve IsReadOnly anonim kayıtları için IsByRefLike açık dil önerisi vardır.