F # organizacja kodu: typy i moduły
Jak zdecydować, czy pisać funkcję wewnątrz modułu, czy jako statyczny element jakiegoś typu?
Na przykład, w kodzie źródłowym F#, istnieje wiele typów, które są zdefiniowane wraz z równie nazwanym modułem, w następujący sposób:
type MyType = // ...
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module MyType = // ...
Dlaczego po prostu nie zdefiniujesz operacji jako statycznych członków typu MyType?
4 answers
Oto kilka uwag na temat technicznych rozróżnień.
Moduły mogą być "otwarte" (o ile nie wymagają wymaganego dostępu). Oznacza to, że jeśli umieścisz funkcje (F
i G
) w module (M
), możesz napisać
open M
... F x ... G x ...
Podczas gdy metodą statyczną zawsze piszesz
... M.F x ... M.G x ...
Funkcje modułu nie mogą być przeciążone . Funkcje w module są let-bound, a funkcje let-bound nie pozwalają na przeciążenie. Jeśli chcesz być możliwość wywołania obu
X.F(someInt)
X.F(someInt, someString)
Musisz użyć member
s typu, które działają tylko z wywołaniami "kwalifikowanymi" (np. type.StaticMember(...)
lub object.InstanceMember(...)
).
(czy są inne różnice? Nie pamiętam.)
Są to główne różnice techniczne, które wpływają na wybór jednego nad drugim.Dodatkowo istnieje pewna tendencja w środowisku uruchomieniowym F # (FSharp.Rdzeń.dll) używać modułów tylko dla typów specyficznych dla F#(które zazwyczaj nie są używane podczas współpracy z innymi językami. Net) i statyczne metody dla interfejsów API, które są bardziej neutralne językowo. Na przykład wszystkie funkcje z parametrami Currie pojawiają się w modułach (funkcje Currie są nietrywialne do wywołania z innych języków).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-06 19:18:47
W F# wolę statyczny element na typie niż funkcję w module if ...
- muszę zdefiniować typ niezależnie od członu
- Element jest funkcjonalnie powiązany z typem, który definiuję
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-06 18:40:34
Oprócz innych odpowiedzi istnieje jeszcze jeden przypadek użycia modułów:
Dla typów wartości mogą one pomóc zdefiniować właściwości statyczne, które nie są poddawane ponownej ocenie za każdym razem, gdy są dostępne. na przykład:
type [<Struct>] Point =
val x:float
val y:float
new (x,y) = {x=x;y=y}
static member specialPoint1 = // sqrt is computed every time the property is accessed
Point (sqrt 0.5 , sqrt 0.5 )
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Point =
let specialPoint2 = // sqrt is computed only once when the Module is opened
Point (sqrt 0.5 , sqrt 0.5 )
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-30 15:02:00
Niektóre duże wyróżnienia, które nie były pierwotnie wymienione:
Funkcje są wartościami pierwszej klasy W F#, ale statycznymi członkami nie są. Więc możesz pisać
objs |> Seq.map Obj.func
, ale nie możesz pisaćobjs |> Seq.map Obj.Member
.Funkcje mogą być zwijane, ale członkowie nie mogą.
Kompilator wywnioskuje typy automatycznie po wywołaniu funkcji, ale nie po wywołaniu członka. Więc możesz pisać
let func obj = obj |> Obj.otherFunc
, ale nie możesz pisaćlet func obj = obj.Member
.
Ponieważ członkowie są bardziej ograniczone, zwykle używam funkcji, chyba że wyraźnie chcę wspierać OOP / C#.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-14 21:26:42