MódulosModules

En F# el contexto del lenguaje, un módulo es una agrupación de F# código, como valores, tipos y valores de función, en un F# programa.In the context of the F# language, a module is a grouping of F# code, such as values, types, and function values, in an F# program. Agrupar el código en módulos ayuda a mantener junto el código relacionado y a evitar conflictos de nombres en los programas.Grouping code in modules helps keep related code together and helps avoid name conflicts in your program.

SintaxisSyntax

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

ComentariosRemarks

Un F# módulo es una agrupación de F# construcciones de código como tipos, valores, valores de función y código en do enlaces.An F# module is a grouping of F# code constructs such as types, values, function values, and code in do bindings. Se implementa como una clase de Common Language Runtime (CLR) que solo tiene miembros estáticos.It is implemented as a common language runtime (CLR) class that has only static members. Hay dos tipos de declaraciones de módulo, dependiendo de si el archivo completo está incluido en el módulo: una declaración de módulo de nivel superior y una declaración de módulo local.There are two types of module declarations, depending on whether the whole file is included in the module: a top-level module declaration and a local module declaration. Una declaración de módulo de nivel superior incluye el archivo completo en el módulo.A top-level module declaration includes the whole file in the module. Una declaración de módulo de nivel superior solo puede aparecer como la primera declaración de un archivo.A top-level module declaration can appear only as the first declaration in a file.

En la sintaxis de la declaración de módulo de nivel superior, el espacio de nombres completo opcional es la secuencia de nombres de espacios de nombres anidados que contiene el módulo.In the syntax for the top-level module declaration, the optional qualified-namespace is the sequence of nested namespace names that contains the module. El espacio de nombres completo no tiene que declararse previamente.The qualified namespace does not have to be previously declared.

No es necesario aplicar sangría a las declaraciones en un módulo de nivel superior.You do not have to indent declarations in a top-level module. Tiene que aplicar sangría a todas las declaraciones en los módulos locales.You do have to indent all declarations in local modules. En una declaración de módulo local, solo las declaraciones a las que se aplica la sangría en la declaración de módulo forman parte del módulo.In a local module declaration, only the declarations that are indented under that module declaration are part of the module.

Si un archivo de código no comienza con una declaración de módulo de nivel superior o una declaración de espacio de nombres, todo el contenido del archivo, incluidos los módulos locales, pasa a formar parte de un módulo de nivel superior creado implícitamente que tiene el mismo nombre que el archivo, sin la extensión. con la primera letra convertida en mayúsculas.If a code file does not begin with a top-level module declaration or a namespace declaration, the whole contents of the file, including any local modules, becomes part of an implicitly created top-level module that has the same name as the file, without the extension, with the first letter converted to uppercase. Por ejemplo, considere el siguiente archivo.For example, consider the following file.

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

Este archivo se compilaría como si estuviera escrito de esta manera:This file would be compiled as if it were written in this manner:

module Program
let x = 40

Si tiene varios módulos en un archivo, debe usar una declaración de módulo local para cada módulo.If you have multiple modules in a file, you must use a local module declaration for each module. Si se declara un espacio de nombres envolvente, estos módulos forman parte del espacio de nombres envolvente.If an enclosing namespace is declared, these modules are part of the enclosing namespace. Si no se declara un espacio de nombres envolvente, los módulos forman parte del módulo de nivel superior creado implícitamente.If an enclosing namespace is not declared, the modules become part of the implicitly created top-level module. En el ejemplo de código siguiente se muestra un archivo de código que contiene varios módulos.The following code example shows a code file that contains multiple modules. El compilador crea implícitamente un módulo de nivel Multiplemodulessuperior denominado MyModule1 y MyModule2 y se anidan en ese módulo de nivel superior.The compiler implicitly creates a top-level module named Multiplemodules, and MyModule1 and MyModule2 are nested in that top-level module.

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

Si tiene varios archivos en un proyecto o en una única compilación, o si está compilando una biblioteca, debe incluir una declaración de espacio de nombres o una declaración de módulo en la parte superior del archivo.If you have multiple files in a project or in a single compilation, or if you are building a library, you must include a namespace declaration or module declaration at the top of the file. El F# compilador solo determina un nombre de módulo implícitamente cuando solo hay un archivo en un proyecto o una línea de comandos de compilación, y se crea una aplicación.The F# compiler only determines a module name implicitly when there is only one file in a project or compilation command line, and you are creating an application.

El modificador Accessibility puede ser uno de los siguientes: public, private, internal.The accessibility-modifier can be one of the following: public, private, internal. Para más información, vea Access Control (Control de acceso).For more information, see Access Control. El valor predeterminado es que sea pública.The default is public.

Referencia al código en módulosReferencing Code in Modules

Al hacer referencia a funciones, tipos y valores de otro módulo, debe usar un nombre completo o abrir el módulo.When you reference functions, types, and values from another module, you must either use a qualified name or open the module. Si usa un nombre completo, debe especificar los espacios de nombres, el módulo y el identificador del elemento de programa que desee.If you use a qualified name, you must specify the namespaces, the module, and the identifier for the program element you want. Cada parte de la ruta de acceso calificada se separa con un punto (.), como se indica a continuación.You separate each part of the qualified path with a dot (.), as follows.

Namespace1.Namespace2.ModuleName.Identifier

Puede abrir el módulo o uno o varios de los espacios de nombres para simplificar el código.You can open the module or one or more of the namespaces to simplify the code. Para obtener más información sobre cómo abrir los espacios de nombres y los módulos, vea importar declaraciones: open Palabra clave.For more information about opening namespaces and modules, see Import Declarations: The open Keyword.

En el ejemplo de código siguiente se muestra un módulo de nivel superior que contiene todo el código hasta el final del archivo.The following code example shows a top-level module that contains all the code up to the end of the file.

module Arithmetic

let add x y =
    x + y

let sub x y =
    x - y

Para usar este código desde otro archivo en el mismo proyecto, use nombres completos o abra el módulo antes de usar las funciones, como se muestra en los ejemplos siguientes.To use this code from another file in the same project, you either use qualified names or you open the module before you use the functions, as shown in the following examples.

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

Módulos anidadosNested Modules

Los módulos se pueden anidar.Modules can be nested. Se debe aplicar sangría a los módulos internos en lo que se refiere a las declaraciones de módulos externos para indicar que son módulos internos, no módulos nuevos.Inner modules must be indented as far as outer module declarations to indicate that they are inner modules, not new modules. Por ejemplo, compare los dos ejemplos siguientes.For example, compare the following two examples. Module Z es un módulo interno en el código siguiente.Module Z is an inner module in the following code.

module Y =
    let x = 1

    module Z =
        let z = 5

Pero el Z módulo es un elemento relacionado Y con el módulo en el código siguiente.But module Z is a sibling to module Y in the following code.

module Y =
    let x = 1

module Z =
    let z = 5

El Z módulo también es un módulo relacionado en el código siguiente, ya que no tiene ninguna sangría en lo que se refiere a otras Ydeclaraciones del módulo.Module Z is also a sibling module in the following code, because it is not indented as far as other declarations in module Y.

module Y =
        let x = 1

    module Z =
        let z = 5

Por último, si el módulo externo no tiene ninguna declaración y va seguido inmediatamente de otra declaración de módulo, se supone que la nueva declaración de módulo es un módulo interno, pero el compilador le advierte si la segunda definición de módulo no tiene sangría más allá de la lugar.Finally, if the outer module has no declarations and is followed immediately by another module declaration, the new module declaration is assumed to be an inner module, but the compiler will warn you if the second module definition is not indented farther than the first.

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

Para eliminar la advertencia, aplique una sangría al módulo interno.To eliminate the warning, indent the inner module.

module Y =
    module Z =
        let z = 5

Si desea que todo el código de un archivo esté en un módulo externo único y desea que los módulos internos, el módulo externo no requiera el signo igual y no se tenga que aplicar sangría a las declaraciones, incluidas las declaraciones de módulo internas, que Irán en el módulo externo.If you want all the code in a file to be in a single outer module and you want inner modules, the outer module does not require the equal sign, and the declarations, including any inner module declarations, that will go in the outer module do not have to be indented. Es necesario aplicar sangría a las declaraciones dentro de las declaraciones del módulo interno.Declarations inside the inner module declarations do have to be indented. En el código siguiente se muestra este caso.The following code shows this case.

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

Módulos recursivosRecursive modules

F#4,1 presenta la noción de módulos que permiten que todo el código contenido sea recursivo mutuamente.F# 4.1 introduces the notion of modules which allow for all contained code to be mutually recursive. Esto se hace a module rectravés de.This is done via module rec. El uso module rec de puede aliviar algunos problemas al no poder escribir código referencial mutuamente entre tipos y módulos.Use of module rec can alleviate some pains in not being able to write mutually referential code between types and modules. El siguiente es un ejemplo de esto:The following is an example of this:

module rec RecursiveModule =
    type Orientation = Up | Down
    type PeelState = Peeled | Unpeeled

    // This exception depends on the type below.
    exception DontSqueezeTheBananaException of Banana

    type BananaPeel() = class end

    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 DontSqueezeTheBananaException la excepción y Banana la clase hacen referencia entre sí.Note that the exception DontSqueezeTheBananaException and the class Banana both refer to each other. Además, el módulo BananaHelpers y la clase Banana también hacen referencia entre sí.Additionally, the module BananaHelpers and the class Banana also refer to each other. Esto no sería posible F# si se quitara la rec palabra clave del RecursiveModule módulo.This would not be possible to express in F# if you removed the rec keyword from the RecursiveModule module.

Esta capacidad también es posible en los espacios de F# nombres con 4,1.This capability is also possible in Namespaces with F# 4.1.

Vea tambiénSee also