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 printCircleStats
anahtar 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:
- 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.
- (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.
- (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 IsReadOnly
olarak IsByRefLike
bildirmek mümkün değildir. ve IsReadOnly
anonim kayıtları için IsByRefLike
açık dil önerisi vardır.