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)

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)

Memoria manual

var p = alloc(sizeof(int))
p[] = 42
dealloc(p)

Macros y metaprogramación

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

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