Do modelowania w domenie polecam używanie typów o nazwach o nazwie elementy:; Oznacza to, że rekordy, dyskryminowany związek i być może sporadyczna klasa lub interfejs.
Strukturalnie rekordy i krotki są podobne; w algebraicznym typie danych, oba typy to typy produktów.
Różnica polega na tym, że w przypadku krotek liczy się kolejność wartości, a rola każdego elementu jest niejawna.
> (2016, 1, 2) = (2016, 1, 2);;
val it : bool = true
> (2016, 1, 2) = (2016, 2, 1);;
val it : bool = false
W powyższym przykładzie możesz zgadnąć, że te krotki są datami modelu, ale które dokładnie? Czy to drugi stycznia 2016? Czy jest to pierwszy lutego 2016?
Z zapisów, z drugiej strony, kolejność elementów nie ma znaczenia, bo je związać, a dostęp do nich, o nazwie:
> type Date = { Year : int; Month : int; Day : int };;
type Date =
{Year: int;
Month: int;
Day: int;}
> { Year = 2016; Month = 1; Day = 2 } = { Year = 2016; Day = 2; Month = 1 };;
val it : bool = true
To także wyraźniejsze, gdy chcemy wysunąć wartości składowe. Można łatwo uzyskać lat od wartości rekordu:
> let d = { Year = 2016; Month = 1; Day = 2 };;
val d : Date = {Year = 2016;
Month = 1;
Day = 2;}
> d.Year;;
val it : int = 2016
To znacznie trudniej wyciągnąć wartości z krotka:
> let d = (2016, 1, 2);;
val d : int * int * int = (2016, 1, 2)
> let (y, _, _) = d;;
val y : int = 2016
pewnik, dla par, można użyć wbudowanych funkcji fst
i snd
, aby uzyskać dostęp do elementów, ale w przypadku krotek z trzema lub więcej elementami, nie można łatwo uzyskać wartości, chyba że dopasujesz wzorzec.
Nawet jeśli zdefiniujesz funkcje niestandardowe, rola każdego elementu jest nadal niejawnie zdefiniowana przez jego porządek porządkowy. Łatwo uzyskać kolejność wartości błędnych, jeśli są tego samego typu.
Jeśli chodzi o modelowanie domen, zawsze preferuję typy jawne, aby było jasne, co się dzieje.
Czy krotki nigdy nie są odpowiednie?
Krotki są przydatne w innych kontekstach. Aby użyć funkcji typu ad-hoc typu ad-hoc, są one bardziej odpowiednie niż rekordy.
Weźmy jako przykład, Seq.zip
, która pozwala połączyć dwie sekwencje:
let alphalues = Seq.zip ['A'..'Z'] (Seq.initInfinite ((+) 1)) |> Map.ofSeq;;
val alphalues : Map<char,int> =
map
[('A', 1); ('B', 2); ('C', 3); ('D', 4); ('E', 5); ('F', 6); ('G', 7);
('H', 8); ('I', 9); ...]
> alphalues |> Map.find 'B';;
val it : int = 2
Jak widać na tym przykładzie, krotki to tylko krok w kierunku rzeczywistego celu, jakim jest mapa wartości alfabetyczne. Byłoby niezręcznie, gdybyśmy musieli zdefiniować typ rekordu, gdybyśmy chcieli komponować wartości razem wewnątrz wyrażenia. Krotki są odpowiednie do tego zadania.
Chciałbym odpowiedzieć, ale wiem, że Tomas będzie lepiej. IIRC ma więcej wspólnego z pracą z C# i .NET. Jeśli jesteś wyłącznie w F #, idź z krotką. Jeśli pracujesz z innym kodem .NET, przejdź do rekordu. Są też inne czynniki, takie jak duże rozmiary z rekordem, jeśli nie są publiczne z krotką, itd. Przed pytaniem zobacz także [Kiedy używać klas, związków, rekordów i struktur] (https: // msdn.microsoft.com/en-us/library/dd233205.aspx) na końcu łącza. –
Czy widziałeś wszystkie informacje w tagu [F #] (http://stackoverflow.com/tags/f%23/info)? –
[Wytyczne dotyczące projektowania komponentów F #] (http://fsharp.org/specs/component-design-guidelines/) –