Compartir vía


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 del programa F#. Normalmente, los espacios de nombres son elementos de nivel superior en archivos F#.

Sintaxis

namespace [rec] [parent-namespaces.]identifier

Observaciones

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 del archivo completo se convierte en parte del espacio de nombres, siempre que no exista ninguna otra declaración de espacios de nombres en el archivo. Si es así, todo el código hasta la siguiente declaración de espacio de nombres se considera que está 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 módulos y los módulos se incluyen en espacios de nombres. Los espacios de nombres pueden contener tipos y módulos.

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

Los espacios de nombres se pueden declarar explícitamente con la palabra clave de espacio de nombres o implícitamente al declarar un módulo. Para declarar explícitamente un espacio de nombres, use la palabra clave de espacio de nombres seguida del nombre del espacio de nombres. En el ejemplo siguiente se muestra un archivo de código que declara un espacio de nombres Widgets 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 espacios de nombres implícitamente mediante la module palabra clave y proporcionando el nuevo nombre de espacio de nombres en el nombre del módulo completo. En el ejemplo siguiente se muestra un archivo de código que declara un espacio de nombres Widgets y un módulo WidgetsModule, que contiene una función .

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 requiere 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 incluyen 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 do enlace, se encuentra en el espacio de nombres, pero no en los módulos internos, por lo que debe calificar al miembro widgetFunction del módulo mediante el nombre 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 Modules.

Espacios de nombres anidados

Al crear un espacio de nombres anidado, debe calificarlo por completo. De lo contrario, se crea 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 fragmento de espacio de nombres del término 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 System espacio de nombres incluye todo .NET Framework, que abarca muchos ensamblados y contiene muchos espacios de nombres anidados.

Espacio de nombres global

Use el espacio de nombres global predefinido para colocar nombres en el espacio de nombres de nivel superior 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 hace a través de namespace rec. El uso de namespace rec puede aliviar algunos problemas al no poder escribir código referencial mutuamente 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 (banana: Banana) =
        let flip (banana: Banana) =
            match banana.Orientation with
            | Up ->
                banana.Orientation <- Down
                banana
            | Down -> banana

        // Update the peel state for all sides of the banana.
        let peelSides (banana: Banana) =
            banana.Sides
            |> List.map (function
                         | Unpeeled -> Peeled
                         | Peeled -> Peeled)

        // Apply the flipping and peeling logic based on the orientation.
        match banana.Orientation with
        | Up ->   banana |> flip |> peelSides
        | Down -> banana |> peelSides

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

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

Consulte también