Поделиться через


Модули (F#)

В контексте языка F# модуль представляет собой способ группирования кода F#, например значений, типов и значений функций, в программе F#. Группирование кода в модулях помогает не разрывать связанный код и избегать конфликтов имен в программе.

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

Заметки

Модуль F# — это группирование конструкций кода F#, например типов, значений, значений функций и кода в привязках do. Он реализуется в виде класса среды CLR, имеющего только статические члены. Имеется два типа объявлений модулей, которые применяются в зависимости от того, включается ли в модуль файл целиком: объявление модуля верхнего уровня и объявление локального модуля. При объявлении модуля верхнего уровня в модуль включается целый файл. Объявление модуля верхнего уровня может использоваться только в качестве первого объявления в файле.

В синтаксисе объявления модуля верхнего уровня необязательное qualified-namespace представляет собой последовательность вложенных имен пространств имен, содержащую модуль. Предварительно объявлять полное имя пространства имен не обязательно.

Использовать отступы при объявлении модуля верхнего уровня не требуется. Использовать отступы при объявлении всех локальных модулей обязательно. При объявлении локального модуля частью модуля являются только объявления, размещенные с отступом внутри объявления самого модуля.

Если файл с кодом не начинается с объявления модуля верхнего уровня или с объявления пространства имен, все содержимое файла, включая все локальные модули, становится частью неявно созданного модуля верхнего уровня, имя которого совпадает с именем файла без расширения и записанным с прописной буквы. Например, рассмотрим следующий файл.

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

Этот файл будет скомпилирован, как если бы он был записан в следующем виде.

module Program
let x = 40

Если в файле имеется несколько модулей, необходимо использовать для каждого из них объявление локального модуля. Если объявлено пространство имен более высокого уровня, эти модули будут частью такого пространства имен. Если пространство имен более высокого уровня не объявлено, эти модули становятся частью неявно созданного модуля верхнего уровня. В следующем примере показан файл с кодом, содержащий несколько модулей. Компилятор неявным образом создает модуль верхнего уровня с именем Multiplemodules, а модули MyModule1 и MyModule2 помещаются внутрь этого модуля.

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

При наличии в проекте или одной компиляции нескольких файлов или при построении библиотеки необходимо включать в начало файла объявление пространства имен или модуля. Компилятор F# неявно определяет имя модуля только в том случае, если в проекте имеется только один файл или командная строка компиляции и при этом создается приложение.

Можно использовать следующий accessibility-modifier: public, private или internal. Дополнительные сведения см. в разделе Управление доступом (F#). Значение по умолчанию — "public" (открытый).

Ссылки на код в модулях

При упоминании в модуле функций, типов и значений из другого модуля необходимо использовать полное имя или открыть модуль. При использовании полного имени следует указать пространства имен, модуль и идентификатор требуемого элемента программы. Части полного пути разделяются точками (.), как показано ниже.

Namespace1.Namespace2.ModuleName.Identifier

Чтобы упростить код, можно открыть модуль или одно или несколько пространств имен. Дополнительные сведения об открытии пространств имен и модулей см. в разделе Объявления импорта: ключевое слово open (F#).

В следующем примере кода показан модуль верхнего уровня, содержащий весь код файла.

module Arithmetic

let add x y =
    x + y

let sub x y =
    x - y

Для использования кода из другого файла того же проекта следует воспользоваться полными именами или открыть модуль перед использованием соответствующих функций, как показано в следующих примерах.

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

Вложенные модули

Модули можно помещать друг в друга. Внутренние модули необходимо выделять отступами относительно внешних модулей, чтобы показать, что это вложенные, а не новые модули. Сравните следующие два примера. Модуль Z является внутренним модулем в следующем фрагменте кода.

module Y =
    let x = 1 

    module Z =
        let z = 5

Но модуль Z находится на одном уровне с модулем Y в следующем фрагменте кода.

module Y =
    let x = 1 

module Z =
    let z = 5

В следующем примере кода модуль Z также находится на одном уровне, поскольку у него нет отступа по сравнению с другими объявлениями в модуле Y.

module Y =
        let x = 1

    module Z =
        let z = 5

Наконец, если внешний модуль не содержит объявлений, и сразу после него следует объявление другого модуля, новый модуль считается внутренним, но компилятор выдает предупреждение, если второй модуль не имеет отступа относительно первого модуля.

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

Чтобы избежать предупреждения, объявите внутренний модуль с отступом.

module Y =
    module Z =
        let z = 5

Если весь код в файле должен принадлежать к одному внешнему модулю и необходимо использовать внутренние модули, внешний модуль не требует знака равенства, а объявления, включая объявления внутренних модулей, которые помещаются во внешний модуль не должны иметь отступа. Объявления внутри внутренних модулей должны иметь отступы. Это показано в следующем примере.

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

См. также

Ссылки

Пространства имен (F#)

Другие ресурсы

Справочник по языку F#