Megosztás a következőn keresztül:


Modulok

Az F# kontextusában a modul egy F#-kód, például értékek, típusok és függvényértékek csoportosítása egy F#-programban. A modulokban lévő kód csoportosításával együtt tarthatja a kapcsolódó kódot, és elkerülheti a névütközéseket a programban.

Syntax

// Top-level module declaration.
module [accessibility-modifier] [qualified-namespace.]module-name
declarations
// Local module declaration.
module [accessibility-modifier] module-name =
    declarations

Megjegyzések

Az F#-modul olyan F#-kódszerkezetek csoportosítása, mint például a típusok, értékek, függvényértékek és kötésekben lévő do kód. Általános nyelvi futtatókörnyezeti (CLR) osztályként van implementálva, amelynek csak statikus tagjai vannak. A moduldeklarációknak két típusa van, attól függően, hogy a teljes fájl szerepel-e a modulban: egy legfelső szintű moduldeklaráció és egy helyi moduldeklaráció. A legfelső szintű moduldeklaráció tartalmazza a modul teljes fájljának tartalmát. A legfelső szintű moduldeklaráció csak a fájl első deklarációjaként jelenhet meg.

A legfelső szintű moduldeklaráció szintaxisában az opcionális minősített névtér a modult tartalmazó beágyazott névtérnevek sorozata. A minősített névteret korábban nem kell deklarálni.

Nem kell behúznia a deklarációkat egy legfelső szintű modulban. Minden deklarációt be kell húznia a helyi modulokba. Egy helyi moduldeklarációban csak a modul deklarációja alatt behúzott deklarációk részei a modulnak.

Ha egy kódfájl nem legfelső szintű moduldeklarációval vagy névtérdeklarációval kezdődik, a fájl teljes tartalma, beleértve a helyi modulokat is, egy implicit módon létrehozott legfelső szintű modul részévé válik, amelynek neve megegyezik a fájl nevével, a kiterjesztés nélkül, az első betű nagybetűssé alakítva. Vegyük például az alábbi fájlt.

// In the file program.fs.
let x = 40

Ez a fájl úgy lesz lefordítva, mintha az így lett volna megírva:

module Program
let x = 40

Ha egy fájlban több modul is található, minden modulhoz helyi moduldeklarációt kell használnia. Ha egy beágyazó névteret deklarál, ezek a modulok a beágyazó névtér részét képezik. Ha a rendszer nem deklarál egy burkoló névteret, a modulok az implicit módon létrehozott legfelső szintű modul részévé válnak. Az alábbi példakód egy több modult tartalmazó kódfájlt mutat be. A fordító implicit módon létrehoz egy legfelső szintű modult, amely MyModule1MyModule2 a Multiplemoduleslegfelső szintű modulba van ágyazva.

// In the file multiplemodules.fs.
// MyModule1
module MyModule1 =
    // Indent all program elements within modules that are declared with an equal sign.
    let module1Value = 100

    let module1Function x =
        x + 10

// MyModule2
module MyModule2 =

    let module2Value = 121

    // Use a qualified name to access the function.
    // from MyModule1.
    let module2Function x =
        x * (MyModule1.module1Function module2Value)

Ha több fájllal rendelkezik egy projektben vagy egy fordításban, vagy ha tárat készít, a fájl tetején egy névtérdeklarációt vagy moduldeklarációt kell tartalmaznia. Az F# fordító csak akkor határozza meg implicit módon a modul nevét, ha egy projektben vagy fordítási parancssorban csak egy fájl található, és ön egy alkalmazást hoz létre.

Az akadálymentesség-módosító a következők egyike lehet: public, private, internal. Ezzel kapcsolatos további információt a Hozzáférés-vezérléscímű témakörben talál. Az alapértelmezett érték nyilvános.

Hivatkozási kód modulokban

Ha egy másik modul függvényeire, típusaira és értékeire hivatkozik, minősített nevet kell használnia, vagy meg kell nyitnia a modult. Minősített név használata esetén meg kell adnia a kívánt programelem névtereit, moduljait és azonosítóit. A minősített elérési út egyes részeit ponttal (.) kell elválasztani az alábbiak szerint.

Namespace1.Namespace2.ModuleName.Identifier

A kód egyszerűsítése érdekében megnyithatja a modult vagy egy vagy több névteret. További információ a névterek és modulok megnyitásáról: Import Deklarációk: A open kulcsszó.

Az alábbi példakód egy legfelső szintű modult mutat be, amely a fájl végéig tartalmazza az összes kódot.

module Arithmetic

let add x y =
    x + y

let sub x y =
    x - y

Ha ezt a kódot egy másik fájlból szeretné használni ugyanabban a projektben, akkor vagy minősített neveket használ, vagy a függvények használata előtt megnyitja a modult, ahogy az alábbi példákban is látható.

// Fully qualify the function name.
let result1 = Arithmetic.add 5 9
// Open the module.
open Arithmetic
let result2 = add 5 9

Beágyazott modulok

A modulok beágyazhatók. A belső modulokat a külső moduldeklarációkig be kell húzni, hogy jelezzék, hogy belső modulok, nem pedig új modulok. Hasonlítsa össze például a következő két példát. A modul Z egy belső modul az alábbi kódban.

module Y =
    let x = 1

    module Z =
        let z = 5

A modul Z azonban a következő kódban szereplő modul Y testvére.

module Y =
    let x = 1

module Z =
    let z = 5

A modul Z a következő kód testvérmodulja is, mivel a modul Ymás deklarációihoz képest nincs behúzva.

module Y =
        let x = 1

    module Z =
        let z = 5

Végül, ha a külső modul nem rendelkezik deklarációkkal, és azonnal egy másik moduldeklaráció követi, az új moduldeklaráció belső modulnak minősül, de a fordító figyelmezteti, ha a második moduldefiníció nincs az elsőnél távolabb behúzva.

// This code produces a warning, but treats Z as a inner module.
module Y =
module Z =
    let z = 5

A figyelmeztetés eltávolításához behúzhatja a belső modult.

module Y =
    module Z =
        let z = 5

Ha azt szeretné, hogy egy fájl összes kódja egyetlen külső modulban legyen, és belső modulokat szeretne, a külső modulhoz nem szükséges az egyenlőségjel, és a külső modulban lévő deklarációkat, beleértve a belső modul deklarációit, nem kell behúzni. A belső modul deklarációiban lévő deklarációkat be kell húzni. Az alábbi kód ezt az esetet mutatja be.

// The top-level module declaration can be omitted if the file is named
// TopLevel.fs or topLevel.fs, and the file is the only file in an
// application.
module TopLevel

let topLevelX = 5

module Inner1 =
    let inner1X = 1
module Inner2 =
    let inner2X = 5

Rekurzív modulok

Az F# 4.1 bemutatja a modulok fogalmát, amelyek lehetővé teszik, hogy minden tartalmazott kód kölcsönösen rekurzív legyen. Ez a művelet a . használatával module rectörténik. module rec A használat enyhítheti néhány fájdalmat, ha nem tud kölcsönösen hivatkozó kódot írni a típusok és modulok között. Az alábbiakban egy példa látható erre:

module rec RecursiveModule =
    type Orientation = Up | Down
    type PeelState = Peeled | Unpeeled

    // This exception depends on the type below.
    exception DontSqueezeTheBananaException of Banana

    type Banana(orientation : Orientation) =
        member val IsPeeled = false with get, set
        member val Orientation = orientation with get, set
        member val Sides: PeelState list = [ Unpeeled; Unpeeled; Unpeeled; Unpeeled] with get, set

        member self.Peel() = BananaHelpers.peel self // Note the dependency on the BananaHelpers module.
        member self.SqueezeJuiceOut() = raise (DontSqueezeTheBananaException self) // This member depends on the exception above.

    module BananaHelpers =
        let peel (b: Banana) =
            let flip (banana: Banana) =
                match banana.Orientation with
                | Up ->
                    banana.Orientation <- Down
                    banana
                | Down -> banana

            let peelSides (banana: Banana) =
                banana.Sides
                |> List.map (function
                             | Unpeeled -> Peeled
                             | Peeled -> Peeled)

            match b.Orientation with
            | Up ->   b |> flip |> peelSides
            | Down -> b |> peelSides

Vegye figyelembe, hogy a kivétel DontSqueezeTheBananaException és az osztály Banana egyaránt egymásra hivatkozik. Emellett a modul BananaHelpers és az osztály Banana is hivatkozik egymásra. Ez nem fejezhető ki F# nyelven, ha eltávolította a kulcsszót rec a RecursiveModule modulból.

Ez a képesség az F# 4.1 névterekben is lehetséges.

Lásd még