Descripción general del lenguaje Nim
Nim 2.2 — lenguaje de sistemas | Sintaxis similar a Python | Motores C/JS/LLVM | GC opcional | metaprogramación a través de macros
paradigma
Multiparadigma: imperativo, funcional, orientado a objetos (mediante sintaxis de llamada a método), metaprogramación. Tipificación estática con inferencia completa (tipo Hindley-Milner), equivalencia de tipo estructural. Compilación mediante C, C++, JavaScript o LLVM. Las macros basadas en AST se ejecutan en tiempo de compilación.
Tipos
| Categoría |
Tipos |
| Firmado entero |
int8 int16 int32 int64 int (dependiente de la plataforma) |
| entero sin firmar |
uint8 uint16 uint32 uint64 uint |
| flotador |
float32 float64 |
| booleano |
bool |
| carbón |
char (1 byte) |
| cuerda |
string (mutable, con prefijo de longitud) |
| cuerda do |
cstring (terminado en nulo) |
| matriz |
array[N, T] array[T] |
| secuencia |
seq[T] (matriz dinámica, administrada por GC) |
| tupla |
(T1, T2) / tuple[a: T1, b: T2] |
| Objeto |
object / ref object (montón + GC por defecto) |
| enumeración |
enum { variant, variant2 } |
| Rango |
range[0..100] (subrango) |
| conjunto |
set[T] (campo de bits, hasta 256 elementos) |
| puntero |
ptr T |
| Referencia |
ref T (rastreado por GC) |
| Opcional |
Option[T] (desde estándar) |
| Resultado |
Result[T, E] |
| Distinto |
distinct T (nuevo tipo de envoltorio) |
| Tipo de clase |
Concept/generic restricción |
| vacío |
void (tipo de retorno) |
| nunca |
never (divergente) |
Declaraciones
| construir |
Sintaxis |
Notas |
| Función |
proc name(params): Ret = body |
|
| Método |
proc name(self: T; params): Ret = body |
|
| Plantilla |
template name(params): untyped = body |
sustitución de AST |
| Macro |
macro name(params): untyped = body |
manipulación de AST |
| variable |
let x = expr |
inmutable |
| Mutable |
var x = expr |
|
| constante |
const NAME = expr |
tiempo de compilación |
| Dejar (tiempo de ejecución) |
let x: T = expr |
|
| Objeto |
type Name = object |
Tipo de valor |
| Objeto de referencia |
type Name = ref object |
Asignado en montón |
| tupla |
type Name = tuple[a: T, b: U] |
|
| enumeración |
type Name = enum { a, b, c } |
|
| unión |
type Name = object { case tag: T of ... } |
Variant/SUM tipo |
| Escriba alias |
type Name = T |
|
| Importar |
import module / from module import name |
|
| incluir |
include "file.nim" |
Inclusión textual |
| Tipo de proceso |
type Handler = proc(params): Ret |
|
Controlar el flujo
| construir |
Sintaxis |
Notas |
| si |
if cond: ... else: ... |
|
| Si (expresión) |
let x = if cond: a else: b |
|
| caso |
case expr: of val: ... else: ... |
exhaustivo |
| mientras |
while cond: ... |
|
| Para |
for x in iterable: ... |
|
| Para (rango) |
for i in 0..<n: ... |
|
| Para (contado) |
for i, x in enumerate(arr): ... |
|
| Para (pares) |
for k, v in pairs(table): ... |
|
| Bloquear |
block label: ... |
bloque con nombre |
| descanso |
break label |
|
| Continuar |
continue |
|
| Regresar |
return expr |
|
| rendimiento |
yield expr |
En iteradores |
| Pruebe |
try: ... except E: ... finally: ... |
|
| Aplazar |
defer: expr |
Ejecutar al salir del alcance |
| Descartar |
discard expr |
ignorar resultado |
Características del estuche (partido)
- Condiciones de rama:
of val:, of val1, val2:, of 0..10:
- Patrones de rango, membresía de conjuntos, coincidencia de tipos
of T(someField): — coincidencia de patrones con encuadernación
- Exhaustividad comprobada para enumeraciones.
Operadores
| Categoría |
Operadores |
| Aritmética |
+ - * / div mod ^ (xor) |
| Comparación |
== != < > <= >= |
| Lógico |
and or not xor |
| Bit a bit |
and or not xor shl shr asr |
| conjunto |
+ - * (intersección) < <= (subconjunto) |
| Identidad |
is (verificación de tipo) of (verificación de subtipo) |
| Varios |
.. (rango) ..< $ (stringify) @ (prefijo de secuencia) & (cadena concat) |
| Dirección |
addr x |
| Deref |
p[] |
| Flecha |
=> (rama de caso, lambda) |
Sobrecarga del operador
Cualquier operador puede sobrecargarse: `+`, `*`, `in`, etc. Los operadores personalizados se pueden definir con notación de acento grave.
Sintaxis de llamada al método
# Object-oriented style
echo "hello".len()
x.addr().repr()
# Uniform Function Call Syntax (UFCS)
# Any proc can be called as method:
proc greet(s: string): string = "Hello " & s
"world".greet() # "Hello world"
Genéricos
proc id[T](x: T): T = x
type
Pair[T, U] = object
first: T
second: U
# Concepts (type constraints)
proc sort[T: SomeOrdinal](arr: var seq[T]) = ...
proc hash[T: Hashable](x: T): int =
# T must implement Hashable concept
Memoria y GC
| Categoría |
Comportamiento |
| pila |
Tipos de valor (object, tuple, array) |
| Montón (GC) |
ref object, seq, string, pointer to ref |
| Montón (manual) |
ptr T vía alloc/dealloc |
| GC |
Opcional: --gc:arc, --gc:orc, --gc:markandsweep, --gc:boehm, --gc:none |
ARC/ORC (desde Nim 2.0)
--gc:arc: recuento de referencia determinista (sin colector de ciclo)
--gc:orc: ARC + colector de ciclo opcional
{.acyclic.} pragma para tipos sin ciclos
sink parámetros para la semántica de movimiento
cursor anotación para semántica tipo préstamo
Memoria manual
var p = alloc(sizeof(int))
p[] = 42
dealloc(p)
import macros
macro assert(cond: untyped): untyped =
# AST manipulation at compile time
result = quote do:
if not `cond`:
echo "assertion failed: ", astToStr(`cond`)
quit(1)
# Usage
assert(1 + 1 == 3)
# Template (simpler than macro)
template repeat(n: int, body: untyped): untyped =
for i in 0..<n:
body
repeat(3, echo "hello")
Funciones en tiempo de compilación
static[T] — forzar la evaluación en tiempo de compilación
when - condicional en tiempo de compilación (como #if en C)
const — constante de tiempo de compilación con semántica completa de Nim
macro — Transformación de código de nivel AST
template — sustitución a nivel de sintaxis
{.pragma.} — pragmas definibles por el usuario
compileTime - ejecutar código en tiempo de compilación
import macros — AST construction/manipulation
Biblioteca estándar (seleccionada)
| Módulo |
Contenidos |
system |
Procesos, operadores y tipos integrados |
strutils |
dividir cadena, unir, buscar, reemplazar, eliminar, formatear, parseInt, toUpper |
sequtils |
mapa, filtrar, doblar, zip, todo, cualquiera, concat, deduplicar |
tables |
Table OrderedTable CountTable TableRef |
sets |
HashSet OrderedSet BitSet |
math |
sqrt, sin, cos, log, pow, aleatorio, Pi, Tau, Euler |
os |
fileExists, dirExists, createDir, removeFile, getEnv, sleep, commandLineParams |
osproc |
execCmd, proceso exec, proceso de inicio |
net |
Socket, conectar, enviar, recibir, escuchar, aceptar |
asyncnet / asyncdispatch |
Asíncrono I/O con async/await |
json |
parseJson, %* (constructor), [] acceso, bonita |
xmltree / parsexml |
Análisis y construcción XML |
parseopt |
Análisis de opciones de línea de comandos |
critbits |
Árboles de bits críticos |
sha1 / md5 / base64 |
Primitivas criptográficas |
times |
DateTime, TimeInterval, ahora, formato, análisis |
streams |
StringStream, FileStream, MemoryStream |
logging |
Registrador con niveles y manejadores. |
macros |
Tipos AST, quoteDo, newStmtList, genSym |
pegs / re |
Coincidencia de PEG y Regex |
distros |
--os:, --cpu: detección |
endians |
Big-endian/little-endian conversión |
Manejo de errores
# Exceptions (runtime)
try:
let f = open("file.txt")
defer: f.close()
echo f.readAll()
except IOError as e:
echo "IO error: ", e.msg
finally:
echo "done"
# Result type (no exception, Nim 2.0+)
from std/result import Result, Ok, Err
func div(a, b: int): Result[int, string] =
if b == 0:
return Err("division by zero")
return Ok(a div b)
# Raise exceptions
raise newException(ValueError, "invalid input")
# Option type
import std/options
let x: Option[int] = some(42)
let y: Option[int] = none(int)
Compilación
nim c file.nim # compile with C backend
nim cpp file.nim # compile with C++ backend
nim js file.nim # compile to JavaScript
nim r file.nim # compile + run
nim build # compile project (newer)
nimble build # compile with Nimble package
nim check file.nim # type-check only
nim doc file.nim # generate documentation
nim pretty file.nim # format code
Banderas de compilación
--opt:speed --opt:size --opt:none -d:release --gc:orc --gc:arc --gc:markandsweep --cc:clang --cc:gcc --mm:arc --threads:on --stackTrace:on --lineTrace:on --checks:on
Administrador de paquetes ágil
nimble init # create package
nimble install <pkg> # install dependency
nimble build # build project
nimble test # run tests
nimble publish # publish to nimble registry
nimble.cfg configura los metadatos del paquete, las dependencias y las reglas de compilación.
Interoperabilidad C
# Declare C function
proc printf(fmt: cstring): cint {.importc, varargs.}
# Import C library
proc sqrt(x: float64): float64 {.importc: "sqrt", header: "math.h".}
# Export to C
proc myFunc(a: cint): cint {.exportc.} = a * 2
# Inline C code
{.emit: """
static int add(int a, int b) { return a + b; }
""".}
proc add(a, b: cint): cint {.importc: "add".}
# C type mappings
# int → cint, char → cchar, void → pointer
# char* → cstring, struct → object {.pure, inheritable.}
# size_t → csize, size_t → csize_t
Características de la interfaz de funciones externas
{.importc.} {.exportc.} {.header.} {.link.} {.nodecl.}
{.importcpp.} para interoperabilidad de C++
{.importobjc.} para Objective-C
{.importjs.} para interoperabilidad de JavaScript
{.packed.} para diseño de estructura compatible con ABI
{.union.} para uniones C
{.bitsize.} para campos de bits