Nim demuestra que "parecerse a Python" y "compilar como C" no son incompatibles. Tiene sangría significativa, inferencia de tipos y una sintaxis ligera — y produce un binario nativo sin tiempo de ejecución pesado, con macros que operan sobre el árbol sintáctico.
🎯 Por qué está en este programa
Nim es un primo de la familia C / llaves (Atlas) en el eje de sistemas, junto a Zig y D.
Aporta al programa una comparación muy útil: es la prueba de que la sintaxis y el modelo de ejecución son decisiones independientes. Quien crea que un lenguaje "de guion" es lento por su aspecto, aquí ve lo contrario. Y aporta macros higiénicas sobre el árbol sintáctico en un lenguaje de tipado estático (clase 122), que es una combinación poco frecuente.
| Año | 2008 (como Nimrod); 1.0 en 2019; 2.0 en 2023 |
| Autoría | Andreas Rumpf, con una comunidad pequeña y activa |
| Familia | Sistemas; sintaxis de Python, semántica de Pascal/Modula y C |
| Paradigma | Multiparadigma: imperativo, orientado a objetos, funcional y metaprogramación |
| Tipado | Estático y fuerte, con inferencia; genéricos y conceptos |
| Memoria | ARC/ORC: conteo de referencias con detección de ciclos, en compilación |
| Ejecución | Compila a C, C++ o JavaScript, y de ahí a nativo |
| Estado | 🟡 Estable y minoritario: excelente y con poca adopción industrial |
Andreas Rumpf empezó Nimrod en 2008 con un objetivo poco común: un lenguaje tan expresivo como Python, tan rápido como C y tan seguro como Ada. La estrategia para conseguirlo fue pragmática y muy eficaz: no generar código máquina, sino generar C.
Esa decisión —la misma que tomó GnuCOBOL y que en su día tomó C++ con cfront— le dio
gratis lo que a un lenguaje nuevo le cuesta años: portabilidad a cualquier plataforma con un
compilador de C, incluidos microcontroladores, y acceso directo a todas las bibliotecas de C
(clase 156).
El cambio de nombre a Nim llegó en 2014 —Nimrod tiene connotaciones desafortunadas en inglés—, la 1.0 en 2019, y la 2.0 en 2023 con ORC por defecto: gestión de memoria determinista, sin recolector con pausas.
Y ahí está su posición actual: un lenguaje técnicamente muy logrado con una comunidad pequeña — que es, como la clase 164 explica, un factor que pesa más que casi cualquier característica.
nimpy (clase 158).hts-nim y varias herramientas de genómica.import std/[strutils, sequtils]
let numeros = "1 2 3 4".splitWhitespace().map(parseInt)
echo numeros.sum()
Eso podría ser Python, y compila a un binario nativo sin intérprete. Es la demostración más directa de una idea que este curso repite (clases 123 y 164): el aspecto de un lenguaje y su modelo de ejecución son decisiones separadas.
Y Nim tiene tres características que merecen conocerse:
Uno, la identificación de nombres es insensible al estilo:
proc miFuncion() = discard
mifuncion() # ✓ lo mismo
mi_funcion() # ✓ también: se ignoran los guiones bajos y las mayúsculas (menos la primera)
Es una decisión discutida —y muy práctica— para acabar con las guerras de estilo de nombres (clase 146): cada quien escribe como quiera y el compilador los une.
Dos, la notación uniforme de llamada:
len(cadena) # y
cadena.len # son EXACTAMENTE lo mismo
No hace falta que la función sea un método para escribirla con punto. Eso permite encadenar sin que la biblioteca lo haya previsto, y es lo que D también tiene.
Y tres, las macros, que son lo más potente del lenguaje:
macro miDsl(cuerpo: untyped): untyped =
# recibe el ÁRBOL SINTÁCTICO y devuelve otro árbol
Son macros sobre el AST, higiénicas y con tipos — la potencia de Lisp (clase 122) en un lenguaje estático. Con ellas se construyen los generadores de HTML, los ORM y los DSL del ecosistema, sin coste en ejecución.
nimble como gestor de paquetes con fichero de bloqueo (clase 143).nim c -r main.nim < entrada.txt # compilar y ejecutar
nim c -d:release --opt:speed main.nim # binario optimizado
nim js main.nim # ← el mismo código, a JavaScript
nimble install && nimble test # dependencias y pruebas
import std/[strutils, sequtils, strformat]
let v = stdin.readLine().splitWhitespace().map(parseFloat)
let total = v[0] * v[1] * (1 - v[2])
echo &"Total: {total:.2f}"
Lo que hay que ver.
let es inmutable, como en Rust; para poder reasignar hay que escribir var
(clase 102).&"..." es una macro de interpolación con formato comprobado en compilación: si el formato
no encaja con el tipo, no compila (clase 142). Es la macro del punto anterior aplicada a algo
cotidiano.v está inferido y comprobado,
y v[0] * v[1] es aritmética de coma flotante nativa, sin objetos ni despacho.⏮️ Volver al Atlas · 🗂️ Todas las fichas · 🔗 Relacionadas: Python · C · D · Zig · Pascal