Espacios de nombres (F#)

Un espacio de nombres le permite organizar el código en áreas de funcionalidad relacionada al permitirle adjuntar un nombre a una agrupación de elementos de programa de F#. Los espacios de nombres suelen ser elementos de nivel superior en archivos de F#.

Sintaxis

namespace [rec] [parent-namespaces.]identifier

Comentarios

Si desea colocar código en un espacio de nombres, la primera declaración del archivo debe declarar el espacio de nombres . A continuación, el contenido de todo el archivo se convierte en parte del espacio de nombres, siempre que no exista ninguna otra declaración de espacios de nombres en el archivo. Si ese es el caso, todo el código hasta la siguiente declaración de espacio de nombres se considera dentro del primer espacio de nombres.

Los espacios de nombres no pueden contener directamente valores y funciones. En su lugar, los valores y las funciones deben incluirse en los módulos y los módulos se incluyen en los espacios de nombres. Los espacios de nombres pueden contener tipos y módulos.

Los comentarios de documentos XML se pueden declarar encima de un espacio de nombres, pero se omiten. Las directivas del compilador también se pueden declarar encima de un espacio de nombres.

Los espacios de nombres se pueden declarar explícitamente con la palabra clave namespace o implícitamente al declarar un módulo. Para declarar un espacio de nombres explícitamente, use la palabra clave namespace seguida del nombre del espacio de nombres. En el ejemplo siguiente se muestra un archivo de código que declara un espacio de Widgets nombres con un tipo y un módulo incluido en ese espacio de nombres.

namespace Widgets

type MyWidget1 =
    member this.WidgetName = "Widget1"

module WidgetsModule =
    let widgetName = "Widget2"

Si todo el contenido del archivo está en un módulo, también puede declarar los espacios de nombres implícitamente mediante la palabra clave y proporcionando el nuevo nombre de espacio de nombres en el nombre completo module del módulo. En el ejemplo siguiente se muestra un archivo de código que declara un espacio de Widgets nombres y un módulo , que contiene una función WidgetsModule .

module Widgets.WidgetModule

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

El código siguiente es equivalente al código anterior, pero el módulo es una declaración de módulo local. En ese caso, el espacio de nombres debe aparecer en su propia línea.

namespace Widgets

module WidgetModule =

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

Si se necesita más de un módulo en el mismo archivo en uno o varios espacios de nombres, debe usar declaraciones de módulo local. Cuando se usan declaraciones de módulo local, no se puede usar el espacio de nombres completo en las declaraciones del módulo. El código siguiente muestra un archivo que tiene una declaración de espacio de nombres y dos declaraciones de módulo local. En este caso, los módulos se encuentran directamente en el espacio de nombres ; no hay ningún módulo creado implícitamente que tenga el mismo nombre que el archivo. Cualquier otro código del archivo, como un enlace, está en el espacio de nombres, pero no en los módulos internos, por lo que debe calificar el miembro del módulo mediante el nombre do widgetFunction del módulo.

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

La salida de este ejemplo es la siguiente.

Module1 10 20
Module2 5 6

Para obtener más información, vea Módulos.

Espacios de nombres anidados

Al crear un espacio de nombres anidado, debe calificarlo por completo. De lo contrario, cree un nuevo espacio de nombres de nivel superior. La sangría se omite en las declaraciones de espacio de nombres.

En el ejemplo siguiente se muestra cómo declarar un espacio de nombres anidado.

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"

Espacios de nombres en archivos y ensamblados

Los espacios de nombres pueden abarcar varios archivos en un solo proyecto o compilación. El término fragmento de espacio de nombres describe la parte de un espacio de nombres que se incluye en un archivo. Los espacios de nombres también pueden abarcar varios ensamblados. Por ejemplo, el espacio de nombres incluye toda la .NET Framework, que abarca System muchos ensamblados y contiene muchos espacios de nombres anidados.

Espacio de nombres global

El espacio de nombres predefinido se usa para colocar nombres en el espacio de nombres de nivel superior global de .NET.

namespace global

type SomeType() =
    member this.SomeMember = 0

También puede usar global para hacer referencia al espacio de nombres de .NET de nivel superior, por ejemplo, para resolver conflictos de nombres con otros espacios de nombres.

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

Espacios de nombres recursivos

Los espacios de nombres también se pueden declarar como recursivos para permitir que todo el código contenido sea mutuamente recursivo. Esto se realiza a través de namespace rec . El uso de puede mitigar algunos problemas al no poder escribir código referencial mutuamente namespace rec entre tipos y módulos. A continuación se muestra un ejemplo de esto:

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

Tenga en cuenta que la DontSqueezeTheBananaException excepción y la Banana clase hacen referencia entre sí. Además, el módulo BananaHelpers y la clase también hacen referencia entre Banana sí. Esto no sería posible expresar en F# si quita la palabra rec clave del espacio de nombres MutualReferences .

Esta característica también está disponible para los módulos de nivel superior.

Vea también