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


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

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

Синтаксис

namespace [rec] [parent-namespaces.]identifier

Замечания

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

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

Комментарии к XML-документам можно объявить над пространством имен, но они игнорируются. Директивы компилятора также можно объявить над пространством имен.

Пространства имен можно объявлять явно с помощью пространства имен ключевое слово или неявно при объявлении модуля. Чтобы явно объявить пространство имен, используйте пространство имен ключевое слово за именем пространства имен. В следующем примере показан файл кода, объявляющий пространство Widgets имен с типом и модулем, включенным в это пространство имен.

namespace Widgets

type MyWidget1 =
    member this.WidgetName = "Widget1"

module WidgetsModule =
    let widgetName = "Widget2"

Если все содержимое файла в одном модуле, можно также объявить пространства имен неявно с помощью module ключевое слово и предоставления нового имени пространства имен в полном имени модуля. В следующем примере показан файл кода, который объявляет пространство Widgets имен и модуль WidgetsModule, содержащий функцию.

module Widgets.WidgetModule

let widgetFunction x y =
   printfn "%A %A" x y

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

namespace Widgets

module WidgetModule =

    let widgetFunction x y =
        printfn "%A %A" x y

Если в одном или нескольких пространствах имен требуется несколько модулей, необходимо использовать объявления локального модуля. При использовании объявлений локального модуля нельзя использовать полное пространство имен в объявлениях модуля. В следующем коде показан файл с объявлением пространства имен и двумя объявлениями локального модуля. В этом случае модули содержатся непосредственно в пространстве имен; Неявно создан модуль, имеющий то же имя, что и файл. Любой другой код в файле, например do привязка, находится в пространстве имен, но не во внутренних модулях, поэтому необходимо указать член widgetFunction модуля с помощью имени модуля.

namespace Widgets

module WidgetModule1 =
   let widgetFunction x y =
      printfn "Module1 %A %A" x y
module WidgetModule2 =
   let widgetFunction x y =
      printfn "Module2 %A %A" x y

module useWidgets =

  do
     WidgetModule1.widgetFunction 10 20
     WidgetModule2.widgetFunction 5 6

Выходные данные этого примера приведены следующим образом.

Module1 10 20
Module2 5 6

Дополнительные сведения см. в разделе "Модули".

Вложенные пространства имен

При создании вложенного пространства имен необходимо полностью указать его. В противном случае создается новое пространство имен верхнего уровня. Отступ игнорируется в объявлениях пространства имен.

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

namespace Outer

    // Full name: Outer.MyClass
    type MyClass() =
       member this.X(x) = x + 1

// Fully qualify any nested namespaces.
namespace Outer.Inner

    // Full name: Outer.Inner.MyClass
    type MyClass() =
       member this.Prop1 = "X"

Пространства имен в файлах и сборках

Пространства имен могут охватывать несколько файлов в одном проекте или компиляции. Фрагмент пространства имен терминов описывает часть пространства имен, включенного в один файл. Пространства имен также могут охватывать несколько сборок. Например, System пространство имен включает всю платформа .NET Framework, которая охватывает множество сборок и содержит множество вложенных пространств имен.

Глобальное пространство имен

Вы используете предопределенное пространство global имен, чтобы поместить имена в пространство имен верхнего уровня .NET.

namespace global

type SomeType() =
    member this.SomeMember = 0

Вы также можете использовать глобальную ссылку на пространство имен .NET верхнего уровня, например для разрешения конфликтов имен с другими пространствами имен.

global.System.Console.WriteLine("Hello World!")

Рекурсивные пространства имен

Пространства имен также можно объявить рекурсивным, чтобы разрешить всем содержащимся коду взаимно рекурсивным. Это делается с помощью namespace rec. namespace rec Использование может облегчить некоторые проблемы в том, что не удается писать взаимонаправленный код между типами и модулями. Ниже приведен пример:

namespace rec MutualReferences

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

Обратите внимание, что исключение DontSqueezeTheBananaException и класс Banana ссылаются друг на друга. Кроме того, модуль BananaHelpers и класс Banana также ссылаются друг на друга. Это не удастся выразить в F#, если вы удалили rec ключевое слово из MutualReferences пространства имен.

Эта функция также доступна для модулей верхнего уровня.

См. также