Bagikan melalui


Modul

Dalam konteks F#, modul adalah pengelompokan kode F#, seperti nilai, jenis, dan nilai fungsi, dalam program F#. Mengelompokkan kode dalam modul membantu menyatukan kode terkait dan membantu menghindari konflik nama dalam program Anda.

Sintaksis

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

Komentar

Modul F# adalah pengelompokan konstruksi kode F# seperti jenis, nilai, nilai fungsi, dan kode dalam do pengikatan. Ini diimplementasikan sebagai kelas runtime bahasa umum (CLR) yang hanya memiliki anggota statis. Ada dua jenis deklarasi modul, tergantung pada apakah seluruh file disertakan dalam modul: deklarasi modul tingkat atas dan deklarasi modul lokal. Deklarasi modul tingkat atas mencakup seluruh file dalam modul. Deklarasi modul tingkat atas hanya dapat muncul sebagai deklarasi pertama dalam file.

Dalam sintaks untuk deklarasi modul tingkat atas, namespace layanan yang memenuhi syarat opsional adalah urutan nama namespace berlapis yang berisi modul. Namespace layanan yang memenuhi syarat tidak harus dideklarasikan sebelumnya.

Anda tidak perlu mengindentasi deklarasi dalam modul tingkat atas. Anda harus mengindentasi semua deklarasi dalam modul lokal. Dalam deklarasi modul lokal, hanya deklarasi yang diindentasi di bawah deklarasi modul tersebut yang merupakan bagian dari modul.

Jika file kode tidak dimulai dengan deklarasi modul tingkat atas atau deklarasi namespace, seluruh konten file, termasuk modul lokal apa pun, menjadi bagian dari modul tingkat atas yang dibuat secara implisit yang memiliki nama yang sama dengan file, tanpa ekstensi, dengan huruf pertama dikonversi ke huruf besar. Misalnya, pertimbangkan file berikut.

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

File ini akan dikompilasi seolah-olah ditulis dengan cara ini:

module Program
let x = 40

Jika Anda memiliki beberapa modul dalam file, Anda harus menggunakan deklarasi modul lokal untuk setiap modul. Jika namespace enclosing dideklarasikan, modul ini adalah bagian dari namespace enclosing. Jika namespace enclosing tidak dideklarasikan, modul menjadi bagian dari modul tingkat atas yang dibuat secara implisit. Contoh kode berikut menunjukkan file kode yang berisi beberapa modul. Kompilator secara implisit membuat modul tingkat atas bernama Multiplemodules, dan dan MyModule1MyModule2 ditumpuk dalam modul tingkat atas tersebut.

// 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)

Jika Anda memiliki beberapa file dalam proyek atau dalam satu kompilasi, atau jika Anda membangun pustaka, Anda harus menyertakan deklarasi namespace layanan atau deklarasi modul di bagian atas file. Pengkompilasi F# hanya menentukan nama modul secara implisit ketika hanya ada satu file dalam proyek atau baris perintah kompilasi, dan Anda membuat aplikasi.

Pengubah aksesibilitas dapat berupa salah satu hal berikut: public, , privateinternal. Untuk informasi selengkapnya, lihat Access Control. Defaultnya adalah publik.

Mereferensikan Kode dalam Modul

Saat mereferensikan fungsi, jenis, dan nilai dari modul lain, Anda harus menggunakan nama yang memenuhi syarat atau membuka modul. Jika Anda menggunakan nama yang memenuhi syarat, Anda harus menentukan namespace, modul, dan pengidentifikasi untuk elemen program yang Anda inginkan. Anda memisahkan setiap bagian dari jalur yang memenuhi syarat dengan titik (.), sebagai berikut.

Namespace1.Namespace2.ModuleName.Identifier

Anda dapat membuka modul atau satu atau beberapa namespace layanan untuk menyederhanakan kode. Untuk informasi selengkapnya tentang membuka namespace layanan dan modul, lihat Mengimpor Deklarasi: Kata open Kunci.

Contoh kode berikut menunjukkan modul tingkat atas yang berisi semua kode hingga akhir file.

module Arithmetic

let add x y =
    x + y

let sub x y =
    x - y

Untuk menggunakan kode ini dari file lain dalam proyek yang sama, Anda menggunakan nama yang memenuhi syarat atau Anda membuka modul sebelum menggunakan fungsi, seperti yang ditunjukkan dalam contoh berikut.

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

Modul Berlapis

Modul dapat ditumpuk. Modul dalam harus diindentasi sejauh deklarasi modul luar untuk menunjukkan bahwa modul dalamnya, bukan modul baru. Misalnya, bandingkan dua contoh berikut. Modul Z adalah modul dalam dalam dalam kode berikut.

module Y =
    let x = 1

    module Z =
        let z = 5

Tetapi modul Z adalah saudara kandung untuk modul Y dalam kode berikut.

module Y =
    let x = 1

module Z =
    let z = 5

Modul Z juga merupakan modul saudara dalam kode berikut, karena tidak diindentasikan sejauh deklarasi lain dalam modul Y.

module Y =
        let x = 1

    module Z =
        let z = 5

Akhirnya, jika modul luar tidak memiliki deklarasi dan diikuti segera oleh deklarasi modul lain, deklarasi modul baru diasumsikan sebagai modul dalam, tetapi pengkompilasi akan memperingatkan Anda jika definisi modul kedua tidak diindentasikan lebih jauh dari yang pertama.

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

Untuk menghilangkan peringatan, inden modul dalam.

module Y =
    module Z =
        let z = 5

Jika Anda ingin semua kode dalam file berada dalam satu modul luar dan Anda ingin modul dalam, modul luar tidak memerlukan tanda sama dengan, dan deklarasi, termasuk deklarasi modul dalam apa pun, yang akan masuk ke modul luar tidak harus diinden. Deklarasi di dalam deklarasi modul dalam memang harus diindentasi. Kode berikut menunjukkan kasus ini.

// 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

Modul rekursif

F# 4.1 memperkenalkan gagasan modul yang memungkinkan semua kode yang terkandung saling rekursif. Ini dilakukan melalui module rec. Penggunaan dapat meringankan module rec beberapa rasa sakit karena tidak dapat menulis kode referensial bersama antara jenis dan modul. Berikut ini adalah contohnya:

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 Orientation = orientation with get, set
        member val Sides: PeelState list = [ Unpeeled; Unpeeled; Unpeeled; Unpeeled ] with get, set

        member self.IsPeeled =
            self.Sides |> List.forall ((=) Peeled)

        member self.Peel() =
            BananaHelpers.peel self
            |> fun peeledSides -> self.Sides <- peeledSides

        member self.SqueezeJuiceOut() =
            raise (DontSqueezeTheBananaException self)

    module BananaHelpers =
        let peel (banana: 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)

            banana |> flip |> peelSides

Perhatikan bahwa pengecualian DontSqueezeTheBananaException dan kelas Banana keduanya saling merujuk. Selain itu, modul BananaHelpers dan kelas Banana juga saling merujuk. Ini tidak akan dimungkinkan untuk diekspresikan dalam F# jika Anda menghapus rec kata kunci dari RecursiveModule modul.

Kemampuan ini juga dimungkinkan di Namespace dengan F# 4.1.

Lihat juga