Imports y módulos
¿Por qué módulos?
En la Parte 1, cada programa era un solo archivo. Eso funciona bien para programas pequeños, pero imagina un programa con 50 funciones — encontrar cualquier cosa se vuelve una pesadilla. Los módulos te permiten dividir el código en archivos separados, cada uno enfocado en un tema.
Piensa en los módulos como capítulos de un libro. Cada capítulo cubre un tema, y puedes ir al capítulo que necesitas. En Nyx, cada archivo .nx puede ser un módulo.
Tu primer módulo
Creemos un módulo de ayudantes matemáticos. Crea un archivo llamado math_helpers.nx:
// math_helpers.nx export fn cuadrado(x: int) -> int { return x * x } export fn cubo(x: int) -> int { return x * x * x } export fn factorial(n: int) -> int { if n <= 1 { return 1 } return n * factorial(n - 1) }
La palabra clave export hace que una función esté disponible para otros archivos. Sin export, la función es privada — solo se puede usar dentro de su propio archivo.
Ahora crea tu programa principal que lo usa:
// main.nx import { cuadrado, cubo, factorial } from "math_helpers" fn main() { print(cuadrado(5)) // 25 print(cubo(3)) // 27 print(factorial(6)) // 720 }
La declaración import trae funciones específicas de otro módulo a tu archivo.
La sintaxis de import
import { nombre1, nombre2, nombre3 } from "nombre_modulo"
- Los nombres dentro de
{ }son las funciones (o structs) que quieres usar. - El string después de
fromes el nombre del módulo — el nombre del archivo sin.nx. - Solo importas lo que necesitas. Esto mantiene tu código limpio y hace claras las dependencias.
Exportar structs
También puedes exportar structs:
// formas.nx export struct Circulo { radio: int } export struct Rectangulo { ancho: int, alto: int } export fn area_circulo(c: Circulo) -> int { return 3 * c.radio * c.radio } export fn area_rectangulo(r: Rectangulo) -> int { return r.ancho * r.alto }
// main.nx import { Circulo, Rectangulo, area_circulo, area_rectangulo } from "formas" fn main() { let c: Circulo = Circulo { radio: 10 } let r: Rectangulo = Rectangulo { ancho: 5, alto: 8 } print(area_circulo(c)) // 300 print(area_rectangulo(r)) // 40 }
Dónde busca Nyx los módulos
Cuando escribes import "math_helpers", Nyx busca en este orden:
- Directorio del proyecto —
math_helpers.nxrelativo a la raiz del proyecto - Paquetes instalados —
packages/pkg-name/rest.nxpara dependencias agregadas vianyx add - Directorio local —
math_helpers.nxjunto a tu archivo - Biblioteca estándar —
std/math_helpers.nxen la instalacion de Nyx
Esto significa que puedes importar de la biblioteca estandar, tus propios archivos y paquetes instalados de la misma manera.
Usar la biblioteca estándar
Nyx viene con una biblioteca estándar de módulos útiles. Algunos ejemplos:
import { read_file, write_file } from "std/file" import { http_serve, http_response } from "std/http" import { json_parse, json_stringify } from "std/json"
El prefijo std/ le dice a Nyx que busque en el directorio de la biblioteca estándar.
Organizar un proyecto
Un proyecto típico de Nyx podría verse así:
mi_proyecto/ ├── main.nx # Punto de entrada ├── modelos.nx # Estructuras de datos ├── base_datos.nx # Operaciones de base de datos └── utilidades.nx # Funciones auxiliares
// modelos.nx export struct Usuario { nombre: String, email: String, edad: int } export struct Publicacion { titulo: String, cuerpo: String, autor: String }
// utilidades.nx export fn repetir_string(s: String, veces: int) -> String { var resultado: String = "" var i: int = 0 while i < veces { resultado = resultado + s i += 1 } return resultado } export fn limitar(valor: int, minimo: int, maximo: int) -> int { if valor < minimo { return minimo } if valor > maximo { return maximo } return valor }
// main.nx import { Usuario, Publicacion } from "modelos" import { repetir_string, limitar } from "utilidades" fn main() { let u: Usuario = Usuario { nombre: "Alice", email: "alice@example.com", edad: 30 } print(u.nombre) print(repetir_string("=-", 20)) // =-=-=-=-=-=-... print(limitar(150, 0, 100)) // 100 }
Qué significa export
Solo los elementos con export son visibles fuera del módulo. Esto es importante para ocultar detalles de implementación:
// password.nx // Privado — solo se puede usar dentro de este archivo fn hash_interno(s: String, rondas: int) -> String { var resultado: String = s var i: int = 0 while i < rondas { resultado = resultado + "*" i += 1 } return resultado } // Público — otros archivos pueden usar esto export fn hash_password(password: String) -> String { return hash_interno(password, 10) }
Si otro archivo intenta importar hash_interno, el compilador dará un error. Esto protege tu lógica interna.
Ejemplo práctico: una mini biblioteca
Construyamos una pequeña biblioteca de utilidades de strings:
// string_utils.nx export fn esta_vacio(s: String) -> bool { return s.length() == 0 } export fn empieza_con_mayuscula(s: String) -> bool { if s.length() == 0 { return false } let c: int = s.charAt(0) return c >= 65 and c <= 90 } export fn contar_palabras(s: String) -> int { if s.length() == 0 { return 0 } let partes: Array = s.split(" ") return partes.length() } export fn truncar(s: String, max_len: int) -> String { if s.length() <= max_len { return s } return s.substring(0, max_len) + "..." }
// main.nx import { esta_vacio, empieza_con_mayuscula, contar_palabras, truncar } from "string_utils" fn main() { print(esta_vacio("")) // true print(esta_vacio("hola")) // false print(empieza_con_mayuscula("Hola")) // true print(empieza_con_mayuscula("hola")) // false print(contar_palabras("Nyx es un lenguaje compilado")) // 5 print(truncar("Hola, Mundo!", 5)) // Hola,... }
Ejercicios
- Crea un módulo
math_utils.nxque exporte funcionesabs(n: int) -> int,max(a: int, b: int) -> int, ymin(a: int, b: int) -> int. Escribe un programa principal que las importe y use.
- Crea un módulo
validadores.nxque exportees_positivo(n: int) -> bool,es_par(n: int) -> bool, yen_rango(n: int, minimo: int, maximo: int) -> bool. Úsalos en un programa principal.
- Divide el seguimiento de notas del Capítulo 10 en módulos:
estudiante.nx(struct + creación),notas.nx(promedio, más alta, letra), ymain.nx(informe y punto de entrada).
- Crea un módulo
array_utils.nxque exportesuma(arr: Array) -> int,promedio(arr: Array) -> int, ycontiene(arr: Array, objetivo: int) -> bool. Pruébalo desde un archivo principal.
- Crea dos módulos que ambos exporten una función con la misma lógica pero nombres diferentes. Importa ambos en un archivo principal y verifica que funcionen juntos sin conflictos.
Resumen
- Usa
exportpara hacer funciones y structs disponibles a otros archivos. - Usa
import { nombres } from "modulo"para traer elementos a tu archivo. - Nyx busca: directorio local → biblioteca estándar → paquetes.
- Los módulos te ayudan a organizar el código en archivos enfocados y reutilizables.
- Solo exporta lo que otros archivos necesitan — mantén los detalles de implementación privados.
- La biblioteca estándar se importa igual:
from "std/modulo".
Siguiente capítulo: Archivos →