Ayrılmış Birleşimler
Ayrımlı birleştiriciler, her biri farklı değerlere ve türlere sahip olan bir dizi adlandırılmış durumdan biri olan değerler için destek sağlar. Ayrımlı union'lar heterojen veriler için yararlıdır; geçerli ve hata örnekleri de dahil olmak üzere özel durumlara sahip olan veriler; bir örnekten diğerine türe göre değişiklik silen veriler; ve küçük nesne hiyerarşileri için alternatif olarak kullanılır. Ayrıca, ağaç veri yapılarını temsil etmek için yineleyici ayrımlı unions kullanılır.
Syntax
[ attributes ]
type [accessibility-modifier] type-name =
| case-identifier1 [of [ fieldname1 : ] type1 [ * [ fieldname2 : ] type2 ...]
| case-identifier2 [of [fieldname3 : ]type3 [ * [ fieldname4 : ]type4 ...]
[ member-list ]
Açıklamalar
Ayrımlı union'lar diğer dillerdeki union türlerine benzer, ancak farklar vardır. C++ içinde bir union türünde veya Visual Basic değişken türünde olduğu gibi, değerde depolanan veriler sabit değildir; Birkaç farklı seçenek arasında yer alan bir seçenek olabilir. Ancak, bu diğer dillerdeki birliğin aksine, olası seçeneklerin her biri için bir durum tanımlayıcısı verilir. Durum tanımlayıcıları, bu tür nesnelerin sahip olduğu çeşitli olası değer türlerinin adlarıdır; değerler isteğe bağlıdır. Değerler yoksa, büyük/büyük/büyük harf bir sabit değere eşdeğerdir. Değerler varsa, her değer belirli bir türün tek bir değeri veya aynı ya da farklı türlerde birden çok alanı topan bir tuple olabilir. Tek bir alana bir ad veabilirsiniz, ancak aynı durumdaki diğer alanlar adlandırılmış olsa bile ad isteğe bağlıdır.
Ayrımlı unions için erişilebilirlik varsayılan olarak olarak public kullanılır.
Örneğin, şekil türünün aşağıdaki bildirimini göz önünde bulundurarak.
type Shape =
| Rectangle of width : float * length : float
| Circle of radius : float
| Prism of width : float * float * height : float
Yukarıdaki kod, üç durumdan herhangi birini (Rectangle, Circle ve Prism) değerlerine sahip olan ayrımlı bir Şekil'i bildirmektedir. Her büyük/küçük harf farklı bir alan kümesine sahiptir. Dikdörtgen büyük/alt yazı tipinde, ad genişliğine ve float uzunluğuna sahip iki adlandırılmış alan vardır. Circle büyük/küçük harf, radius adlı tek bir adlandırılmış alana sahiptir. Prism örneğinde üç alan vardır ve ikisi (genişlik ve yükseklik) adlandırılmış alandır. Adsız alanlar anonim alanlar olarak adlandırılır.
Nesneleri oluşturmak için aşağıdaki örneklere göre adlandırılmış ve anonim alanlar için değerler sağlarsınız.
let rect = Rectangle(length = 1.3, width = 10.0)
let circ = Circle (1.0)
let prism = Prism(5., 2.0, height = 3.0)
Bu kod, başlatmada adlandırılmış alanları kullanabileceğiniz veya bildirimde alanların sırasına güvenerek yalnızca sırayla her alanın değerlerini sağlayabilirsiniz. Önceki kodda rect için oluşturucu çağrısı adlandırılmış alanları kullanır, ancak oluşturucu çağrısı circ sıralamayı kullanır. yapısında olduğu gibi, sıralı alanları ve adlandırılmış alanları prism karıştırabilirsiniz.
Türü option F# çekirdek kitaplığında basit bir ayrımlı bir birlikteliktir. optionTür aşağıdaki gibi bildirildi.
// The option type is a discriminated union.
type Option<'a> =
| Some of 'a
| None
Önceki kod, türün iki Option örneği olan ayrımlı bir birliktelik olduğunu Some belirtir: ve None . Durum, türü tür parametresiyle temsil edilen bir anonim alandan Some oluşan ilişkili bir değere 'a sahip. Durum None ilişkili bir değere sahip değildir. Bu nedenle option tür, herhangi bir türde değere sahip olan veya değer olmayan genel bir türü belirtir. OptionTürün, daha yaygın olarak kullanılan küçük option harfli bir diğer adı vardır.
Durum tanımlayıcıları, ayrımlı union türü için oluşturucular olarak kullanılabilir. Örneğin, türün değerlerini oluşturmak için aşağıdaki kod option kullanılır.
let myOption1 = Some(10.0)
let myOption2 = Some("string")
let myOption3 = None
Durum tanımlayıcıları desen eşleştirme ifadelerinde de kullanılır. Desen eşleştirme ifadesinde, tek tek durumlarla ilişkili değerler için tanımlayıcılar sağlanır. Örneğin, aşağıdaki x kodda, türün büyük/büyük/büyük harfle ilişkili değeri Some verilen option tanımlayıcıdır.
let printValue opt =
match opt with
| Some x -> printfn "%A" x
| None -> printfn "No value."
Desen eşleştirme ifadelerinde, ayrımlı union eşleşmelerini belirtmek için adlandırılmış alanları kullanabilirsiniz. Daha önce bildirilen Şekil türü için, aşağıdaki kodda olduğu gibi adlandırılmış alanları kullanarak alanların değerlerini ayıkabilirsiniz.
let getShapeWidth shape =
match shape with
| Rectangle(width = w) -> w
| Circle(radius = r) -> 2. * r
| Prism(width = w) -> w
Normalde, durum tanımlayıcıları, bunları birliğin adıyla nitelendirmeden kullanılabilir. Adın her zaman birliğin adıyla tam olarak belirtilsin, union türü tanımına RequireQualifiedAccess özniteliğini uygulayabilirsiniz.
Ayrımsız Union'ları Ayırma
F# Ayrımlı Unions içinde genellikle tek bir türü sarmalama için etki alanı modellemede kullanılır. Desen eşleştirme yoluyla temel alınan değeri ayıklamak da kolaydır. Tek bir durum için eşleşme ifadesi kullanmana gerek yok:
let ([UnionCaseIdentifier] [values]) = [UnionValue]
Aşağıdaki örnek bunu gösteriyor:
type ShaderProgram = | ShaderProgram of id:int
let someFunctionUsingShaderProgram shaderProgram =
let (ShaderProgram id) = shaderProgram
// Use the unwrapped value
...
Desen eşleştirmeye doğrudan işlev parametrelerinde de izin verilir, bu nedenle burada tek bir büyük/küçük harf kaydırmayı açabilirsiniz:
let someFunctionUsingShaderProgram (ShaderProgram id) =
// Use the unwrapped value
...
Yapı Ayrımlı Unions
Ayrıca Ayrımlı Union'ları yapı olarak da temsil etme. Bu, özniteliğiyle [<Struct>] yapılır.
[<Struct>]
type SingleCase = Case of string
[<Struct>]
type Multicase =
| Case1 of Case1 : string
| Case2 of Case2 : int
| Case3 of Case3 : double
Bunlar başvuru türleri değil değer türleri olduğundan, başvuru ayrımlı unions ile karşılaştırıldığında dikkat edilmesi gereken ek noktalar vardır:
- Bunlar değer türleri olarak kopyalanır ve değer türü semantiğine sahip olur.
- Çok harfli yapı Ayrımlı Birliği ile bircursive tür tanımı kullanılamaz.
- Çok harfli bir yapı Için benzersiz büyük/küçük harf adları sağlamış olması gerekir.
Nesne Hiyerarşileri Yerine Ayrımlı Union'ları Kullanma
Genellikle küçük bir nesne hiyerarşisinin daha basit bir alternatifi olarak ayrımlı bir birliktelik kullanabilirsiniz. Örneğin, daire, kare gibi türler türetilen bir temel sınıf yerine aşağıdaki ayrımlı Shape birliktelik kullanılabilir.
type Shape =
// The value here is the radius.
| Circle of float
// The value here is the side length.
| EquilateralTriangle of double
// The value here is the side length.
| Square of double
// The values here are the height and width.
| Rectangle of double * double
Nesne odaklı bir uygulamada olduğu gibi bir alanı veya çevreyi hesaplamak için sanal bir yöntem yerine, bu miktarları hesaplamak için uygun formüllerle dal eşleştirme desenini kullanabilirsiniz. Aşağıdaki örnekte, şekline bağlı olarak alanı hesaplamak için farklı formüller kullanılır.
let pi = 3.141592654
let area myShape =
match myShape with
| Circle radius -> pi * radius * radius
| EquilateralTriangle s -> (sqrt 3.0) / 4.0 * s * s
| Square s -> s * s
| Rectangle (h, w) -> h * w
let radius = 15.0
let myCircle = Circle(radius)
printfn "Area of circle that has radius %f: %f" radius (area myCircle)
let squareSide = 10.0
let mySquare = Square(squareSide)
printfn "Area of square that has side %f: %f" squareSide (area mySquare)
let height, width = 5.0, 10.0
let myRectangle = Rectangle(height, width)
printfn "Area of rectangle that has height %f and width %f is %f" height width (area myRectangle)
Çıktı aşağıdaki şekilde olacaktır:
Area of circle that has radius 15.000000: 706.858347
Area of square that has side 10.000000: 100.000000
Area of rectangle that has height 5.000000 and width 10.000000 is 50.000000
Ağaç Veri Yapıları için Ayrımlı Unions Kullanma
Ayrımlı union'lar, bir veya daha fazla durum türüne dahil olduğu anlamına gelir. Programlama dillerinde ifadeleri modellemek için kullanılan ağaç yapıları oluşturmak için, ayrımlı ayrımlı ifadeler kullanılabilir. Aşağıdaki kodda, ikili ağaç veri yapısı oluşturmak için bir otomatik olarak ayrımlı bir birliktelik kullanılır. Birlikte, tamsayı değerine ve sol ve sağ alt ağacına sahip bir düğüm olan ve ağacı sonlandıran Node Tip iki durumdan oluşur.
type Tree =
| Tip
| Node of int * Tree * Tree
let rec sumTree tree =
match tree with
| Tip -> 0
| Node(value, left, right) ->
value + sumTree(left) + sumTree(right)
let myTree = Node(0, Node(1, Node(2, Tip, Tip), Node(3, Tip, Tip)), Node(4, Tip, Tip))
let resultSumTree = sumTree myTree
Önceki kodda resultSumTree değeri 10'dur. Aşağıdaki çizimde için ağaç yapısı myTree gösterilmiştir.

Ağaçtaki düğümler heterojense, ayrımlı union'lar iyi çalışır. Aşağıdaki kodda tür, sayıların ve değişkenlerin ekleyip çarpımlarını destekleyen basit bir programlama dilindeki ifadenin soyut söz Expression dizimi ağacını temsil eder. Bazı union örnekleri, tekrarlayıcı değildir ve sayıları ( ) veya Number değişkenleri ( ) temsil Variable eder. Diğer durumlar, yinelemelidir ve işlenenlerin de ifade olduğu işlemleri ( ve Add Multiply ) temsil ediyor. İşlev, Evaluate söz dizimi ağacını tekrar tekrar işlemesi için bir eşleşme ifadesi kullanır.
type Expression =
| Number of int
| Add of Expression * Expression
| Multiply of Expression * Expression
| Variable of string
let rec Evaluate (env:Map<string,int>) exp =
match exp with
| Number n -> n
| Add (x, y) -> Evaluate env x + Evaluate env y
| Multiply (x, y) -> Evaluate env x * Evaluate env y
| Variable id -> env[id]
let environment = Map [ "a", 1; "b", 2; "c", 3 ]
// Create an expression tree that represents
// the expression: a + 2 * b.
let expressionTree1 = Add(Variable "a", Multiply(Number 2, Variable "b"))
// Evaluate the expression a + 2 * b, given the
// table of values for the variables.
let result = Evaluate environment expressionTree1
Bu kod yürütülürken değeri result 5'tir.
Üyeler
Ayrımlı union'larda üyeleri tanımlamak mümkündür. Aşağıdaki örnekte bir özelliğin nasıl tanımladığınız ve bir arabirimin nasıl uygulandığını gösterir:
open System
type IPrintable =
abstract Print: unit -> unit
type Shape =
| Circle of float
| EquilateralTriangle of float
| Square of float
| Rectangle of float * float
member this.Area =
match this with
| Circle r -> Math.PI * (r ** 2.0)
| EquilateralTriangle s -> s * s * sqrt 3.0 / 4.0
| Square s -> s * s
| Rectangle(l, w) -> l * w
interface IPrintable with
member this.Print () =
match this with
| Circle r -> printfn $"Circle with radius %f{r}"
| EquilateralTriangle s -> printfn $"Equilateral Triangle of side %f{s}"
| Square s -> printfn $"Square with side %f{s}"
| Rectangle(l, w) -> printfn $"Rectangle with length %f{l} and width %f{w}"
Ortak öznitelikler
Aşağıdaki öznitelikler genellikle ayrımlı union'larda görülür:
[<RequireQualifiedAccess>][<NoEquality>][<NoComparison>][<Struct>]