V gestiona dependencias con vpm, su gestor de paquetes, y un fichero v.mod en la raíz del proyecto que cumple el mismo papel que go.mod en Go o Cargo.toml en Rust: identifica el proyecto, fija metadatos y marca desde dónde arranca la resolución de módulos internos.
El fichero v.mod
Module {
name: 'mipaquete'
description: 'Mi paquete estupendo.'
version: '0.0.1'
license: 'MIT'
dependencies: []
}
Es más escueto que un go.mod o un Cargo.toml: no hay bloques anidados de configuración de build, solo los metadatos esenciales. v.mod también actúa como ancla del proyecto: V antepone la carpeta que contiene ese fichero a la ruta de búsqueda de módulos, así que cualquier subcarpeta puede importar a sus hermanas como si fueran módulos independientes.
mipaquete/ ??? v.mod ??? main.v ??? mipaquete/comun/estructuras.v
Módulos: uno por carpeta
Cada fichero .v declara su módulo en la primera línea, y todos los ficheros de una misma carpeta pertenecen automáticamente al mismo módulo:
module mimodulo
pub fn saludar() {
println('hola desde mimodulo!')
}
import mimodulo mimodulo.saludar()
Solo lo que marcas con pub es visible fuera del módulo; el resto queda accesible entre ficheros de la misma carpeta pero invisible desde fuera, un modelo de visibilidad más explícito que el de Go, donde la mayúscula inicial del identificador ya hace ese trabajo.
Instalar paquetes de terceros
v install ui # desde el registro oficial de vpm v install --git https://github.com/vlang/markdown v install --once ui # solo si no está ya instalado v remove ui v update ui # actualizar uno concreto v update # actualizar todos v outdated # ver qué paquetes tienen versión más nueva v list # paquetes instalados
El registro oficial vive en vpm.vlang.io, con paquetes buscables desde ahí o directamente con v install nombre. Es un ecosistema todavía pequeño comparado con el de Go o Rust, así que no es raro que para librerías más específicas termines instalando directamente desde un repositorio git en vez de desde el registro central.
Inicialización y limpieza automáticas
fn init() {
// se ejecuta una vez, cuando se importa el módulo
}
fn cleanup() {
// se ejecuta cuando el programa termina
}
Estas dos funciones no pueden marcarse como pub y V las reconoce por nombre, sin necesidad de registrarlas en ningún sitio: si existen en un módulo importado, se ejecutan automáticamente.
Todo se compila en un único binario
A diferencia de lenguajes con carga dinámica de módulos, en V todos los módulos (los tuyos y los de terceros) se compilan de forma estática en un único ejecutable, y no se permiten importaciones circulares entre módulos. Es una restricción que simplifica el modelo de compilación a cambio de obligarte a pensar la arquitectura del proyecto sin dependencias en círculo, la misma disciplina que exige el compilador de Go.
Si quieres comparar con el sistema de módulos de Go, que ha ido ganando funciones avanzadas como workspaces y replace en los últimos años, tenemos esta introducción a Go Modules y esta guía avanzada. En el próximo y penúltimo artículo de la serie entramos en los backends del compilador de V: de la transpilación clásica a C hasta los nuevos backends nativos SSA de la versión 0.5.1.
Imagen: Pexels / Myburgh Roux
