Módulos y Scripts
Move tiene dos tipos diferentes de programas: Módulos y Scripts. Los módulos son bibliotecas que definen tipos struct junto con funciones que operan sobre estos tipos. Los tipos struct definen el esquema del almacenamiento global de Move, y las funciones del módulo definen las reglas para actualizar el almacenamiento. Los módulos en sí también se almacenan en el almacenamiento global. Un script es un punto de entrada ejecutable similar a una función main
en un lenguaje convencional. Un script típicamente llama funciones de un módulo publicado que realizan actualizaciones al almacenamiento global. Los scripts son fragmentos de código efímeros que no se publican en el almacenamiento global.
Un archivo fuente de Move (o unidad de compilación) puede contener múltiples módulos y scripts. Sin embargo, publicar un módulo o ejecutar un script son operaciones separadas de la VM.
Sintaxis
Sección titulada «Sintaxis»Scripts
Sección titulada «Scripts»Un script tiene la siguiente estructura:
script { <use>* <constants>* fun <identifier><[type parameters: constraint]*>([identifier: type]*) <function_body>}
Un bloque script
debe comenzar con todas sus declaraciones use
, seguido por cualquier constante y (finalmente) la declaración de la función principal.
La función principal puede tener cualquier nombre (es decir, no necesita llamarse main
), es la única función en un bloque script, puede tener cualquier número de argumentos, y no debe devolver un valor. Aquí hay un ejemplo con cada uno de estos componentes:
script { // Importar el módulo debug publicado en la dirección de cuenta nombrada std. use std::debug;
const ONE: u64 = 1;
fun main(x: u64) { let sum = x + ONE; debug::print(&sum) }}
Los scripts tienen poder muy limitado: no pueden declarar friends, tipos struct o acceder al almacenamiento global. Su propósito principal es invocar funciones de módulos.
Módulos
Sección titulada «Módulos»Un módulo tiene la siguiente sintaxis:
module <address>::<identifier> { (<use> | <friend> | <type> | <function> | <constant>)*}
donde <address>
es una dirección nombrada o literal válida.
Por ejemplo:
module 0x42::example { struct Example has copy, drop { i: u64 }
use std::debug; friend 0x42::another_example;
const ONE: u64 = 1;
public fun print(x: u64) { let sum = x + ONE; let example = Example { i: sum }; debug::print(&sum) }}
El module 0x42::example
parte especifica que el módulo example
se publicará bajo la dirección de cuenta 0x42
en el almacenamiento global.
Los módulos también pueden usar direcciones nombradas. Por ejemplo:
module my_addr::example { struct Example has copy, drop { a: address }
use std::debug; friend my_addr::another_example;
public fun print() { let example = Example { a: @my_addr }; debug::print(&example) }}
Debido a que las direcciones nombradas solo existen en el nivel de compilación y durante la compilación, las direcciones nombradas se sustituirán completamente por su valor.
Los módulos no tienen una función main
. En su lugar, las funciones del módulo se invocan por scripts o por otros módulos.
Nombres
Sección titulada «Nombres»Los módulos y scripts son ambos tipos de unidades de nivel superior, y ambos se ubican en el nivel superior de un archivo fuente. Un módulo también define el espacio de nombres para los tipos y funciones que declara.
Los nombres de módulos y scripts deben comenzar con una letra minúscula a
a z
o una letra mayúscula A
a Z
. Después del primer carácter, los nombres de módulos y scripts pueden contener guiones bajos _
, letras a
a z
, letras A
a Z
, o dígitos 0
a 9
.
module my_module {}module foo_bar_42 {}
Típicamente, los nombres de módulos comienzan con una letra minúscula. Un módulo nombrado my_module
debe ser almacenado en un archivo fuente nombrado my_module.move
.
Todos los elementos dentro de un módulo pueden referirse entre sí sin ningún calificación. En particular, los tipos declarados dentro de un módulo no necesitan ser prefijados con el nombre del módulo.
module 0x42::example { struct Example has copy, drop { i: u64 }
fun make_example(): Example { Example { i: 1 } // Note: no hay necesidad de 0x42::example::Example }}
En el ejemplo anterior, make_example
puede referirse al tipo Example
sin calificación ya que ambos están en el mismo módulo.
Direcciones de Módulos
Sección titulada «Direcciones de Módulos»Cuando un módulo se publica, se publica bajo una cuenta específica en el almacenamiento global a una dirección.
La dirección donde se publica un módulo es llamada la dirección del módulo. Por ejemplo, el módulo estándar vector
se publica bajo la dirección 0x1
. Si quisieras usar el módulo vector
fuera del módulo std
(la biblioteca estándar), necesitarías accederlo a través de esa dirección: 0x1::vector
.
Sin embargo, esto puede volverse verboso. Las declaraciones use
permiten un acceso más corto a módulos sin tener que deletrear la dirección completa cada vez.
Convenciones de Nomenclatura
Sección titulada «Convenciones de Nomenclatura»Si bien puedes nombrar un módulo cualquier cosa que quieras, aquí hay algunas convenciones comunes:
- Los nombres de módulos deben estar en snake_case:
my_module
,user_account
- Los nombres de módulos deben usar sustantivos que describan lo que contiene el módulo
- Si un módulo define un único tipo principal, el módulo generalmente se nombra igual que ese tipo:
module coin
parastruct Coin