Nim es un lenguaje de programación de sistemas de alto nivel compilado , de propósito general , multiparadigma , tipado estáticamente , [9] diseñado y desarrollado por un equipo en torno a Andreas Rumpf. Nim está diseñado para ser "eficiente, expresivo y elegante", [10] admitiendo metaprogramación , funcional , paso de mensajes , [11] procedimental y estilos de programación orientada a objetos al proporcionar varias características como generación de código en tiempo de compilación , tipos de datos algebraicos , una interfaz de función externa (FFI) con C , C++ , Objective-C y JavaScript , y admitiendo la compilación a esos mismos lenguajes como representaciones intermedias .
Descripción
Nim está tipado estáticamente. [12] Admite funciones de metaprogramación en tiempo de compilación, como macros sintácticas y macros de reescritura de términos . [13] Las macros de reescritura de términos permiten que las implementaciones de bibliotecas de estructuras de datos comunes, como bignums y matrices, se implementen de manera eficiente y con integración sintáctica, como si fueran funciones integradas en el lenguaje. [14] Los iteradores son compatibles y se pueden usar como entidades de primera clase, [13] al igual que las funciones, lo que permite el uso de métodos de programación funcional . La programación orientada a objetos es compatible con la herencia y el envío múltiple . Las funciones pueden ser genéricas y sobrecargadas, y los genéricos se mejoran aún más con el soporte de Nim para clases de tipo . También se admite la sobrecarga de operadores . [13] Nim incluye múltiples estrategias de administración de memoria ajustables, que incluyen recolección de basura de rastreo , conteo de referencias y sistemas completamente manuales , siendo el valor predeterminado el conteo de referencias determinista con optimizaciones a través de semántica de movimiento y recolección de ciclos a través de eliminación de prueba. [15]
[Nim] ... presenta un diseño muy original que combina Pascal y Python y se compila en código C o JavaScript. [16]
—Andrew Binstock, redactor jefe de la revista Dr. Dobb's Journal , 2014
A partir de agosto de 2023 [actualizar], Nim se compila en C, C++, JavaScript, Objective-C, [17] y LLVM. [18]
Historia
El desarrollo inicial de Nim fue iniciado en 2005 por Andreas Rumpf. Originalmente se lo llamó Nimrod cuando el proyecto se hizo público en 2008. [20] : 4–11
La primera versión del compilador Nim fue escrita en Pascal usando el compilador Free Pascal . [21] En 2008, se lanzó una versión del compilador escrita en Nim. [22] El compilador es software libre y de código abierto , y está siendo desarrollado por una comunidad de voluntarios que trabajan con Andreas Rumpf. [23] El lenguaje fue renombrado oficialmente de Nimrod a Nim con el lanzamiento de la versión 0.10.2 en diciembre de 2014. [24] El 23 de septiembre de 2019, se lanzó la versión 1.0 de Nim, lo que significa la maduración del lenguaje y su cadena de herramientas. El 1 de agosto de 2023, se lanzó la versión 2.0 de Nim, lo que significa la finalización, estabilización y cambio al modelo de memoria ARC/ORC. [25]
Diseño del lenguaje
Sintaxis
La sintaxis de Nim se parece a la de Python . [26] Los bloques de código y las declaraciones anidadas se identifican mediante el uso de espacios en blanco , de acuerdo con la regla offside-rule . Muchas palabras clave son idénticas a sus equivalentes de Python, que son en su mayoría palabras clave en inglés, mientras que otros lenguajes de programación suelen utilizar puntuación. Con el objetivo de mejorar sus lenguajes de influencia, aunque Nim admite una sintaxis basada en sangría como Python, introdujo flexibilidad adicional. Por ejemplo, una sola declaración puede abarcar varias líneas si hay una coma o un operador binario al final de cada línea. Nim también admite operadores definidos por el usuario.
A diferencia de Python, Nim implementa tipado estático (nativo). El sistema de tipos de Nim permite una conversión de tipos sencilla y proporciona sintaxis para programación genérica. Nim proporciona clases de tipos que pueden sustituir a varios tipos y proporciona varias de estas clases de tipos "listas para usar". Las clases de tipos permiten trabajar con varios tipos como si fueran un solo tipo. Por ejemplo:
openarray– Representa matrices de diferentes tamaños, secuencias y cadenas.SomeSignedInt– Representa todos los tipos de enteros con signoSomeInteger– Representa todos los tipos de enteros, con signo o sin él.SomeOrdinal– Representa todos los tipos contables y ordenados básicos, excepto los números no enteros
Este ejemplo de código demuestra el uso de clases de tipos en Nim]
# Declaremos una función que toma cualquier tipo de número y muestra su doble
# En Nim las funciones con efectos secundarios se llaman "proc"
proc timesTwo ( i : SomeNumber ) = echo i * 2
# Escribamos otra función que tome cualquier tipo ordinal, y devuelva
# el doble de la entrada en su tipo original, si es un número;
# o devuelva la entrada misma en caso contrario.
# Usamos un Type(T) genérico, y precisamos que solo puede ser un Ordinal
func twiceIfIsNumber [ T : SomeOrdinal ] ( i : T ): T = when T is SomeNumber : # Un `when` es un `if` evaluado durante el tiempo de compilación result = i * 2 # También puedes escribir `return i * 2` else : # Si el Ordinal no es un número se convierte a int, # se multiplica por dos y se reconvierte a su tipo base result = ( i . int * 2 ). T
echo twiceIfIsNumber(67) # Passes an int to the functioneco dos vecesSiEsNumero(67u8) # Passes an uint8echo twiceIfIsNumber(true) # Passes a bool (Which is also an Ordinal)
Influencia
Según el creador del lenguaje, Nim fue concebido para combinar las mejores partes del sistema de tipado Ada, la flexibilidad de Python y el potente sistema de macros Lisp . [27]
El Nim fue influenciado por características específicas de los idiomas existentes, entre ellas las siguientes:
- Modula-3 : punteros trazados y no trazados
- Object Pascal : conjuntos de bits seguros para tipos ( conjunto de char ), sintaxis de instrucciones case, varios nombres de tipos y nombres de archivos en la biblioteca estándar
- Ada : tipos de subrango, tipos distintos, variantes seguras – objetos de caso
- C++ : sobrecarga de operadores , programación genérica
- Python : Regla del fuera de juego
- Lisp : Sistema de macros , manipulación de AST , homoiconicidad
- Oberon : marcador de exportación
- C# : async/await , macros lambda
- ParaSail : programación sin punteros [8]
Sintaxis de llamada de función uniforme
Nim admite la sintaxis de llamada de función uniforme (UFCS) [28] y la igualdad de identificadores, lo que proporciona un gran grado de flexibilidad en su uso.
Por ejemplo, cada una de estas líneas imprime "hola mundo" , sólo que con una sintaxis diferente:
echo "hola mundo" echo ( "hola mundo" ) "hola mundo" . echo () "hola mundo" . echo echo ( "hola" , " mundo" ) "hola" . echo ( " mundo" ) "hola" . echo " mundo"
Igualdad de identificadores
Nim es casi totalmente insensible al estilo; dos identificadores se consideran iguales si solo difieren en mayúsculas y guiones bajos, siempre que los primeros caracteres sean idénticos. Esto es para permitir una mezcla de estilos en las bibliotecas: un usuario puede escribir una biblioteca usando snake_case como convención, y puede ser utilizada por un usuario diferente en un estilo camelCase sin problemas. [29]
const useHttps = true afirmar useHttps == useHttps afirmar useHTTPS == useHttps afirmar use_https == useHttps
Afilado
La función de stropping permite el uso de cualquier nombre para variables o funciones, incluso cuando los nombres son palabras reservadas para palabras clave. Un ejemplo de stropping es la capacidad de definir una variable llamada if, sin entrar en conflicto con la palabra clave if. La implementación de esto por parte de Nim se logra mediante comillas invertidas, lo que permite que cualquier palabra reservada se use como identificador. [30]
tipo Tipo = objeto ` int `: int
deje que ` objeto ` = Tipo (` int `: 9 ) afirme que ` objeto ` es Tipo afirme que ` objeto `.` int ` == 9
var ` var ` = 42 let ` let ` = 8 afirmar ` var ` + ` let ` == 50
const ` assert ` = true assert ` assert `
Compilador
El compilador Nim emite código C rápido y optimizado de forma predeterminada. Aplaza la compilación del código a objeto a un compilador C externo [31] para aprovechar la optimización y portabilidad del compilador existente. Se admiten muchos compiladores de C, incluidos Clang , Microsoft Visual C++ (MSVC), MinGW y GNU Compiler Collection (GCC). El compilador Nim también puede emitir código C++ , Objective-C y JavaScript para permitir una fácil interacción con las interfaces de programación de aplicaciones ( API ) escritas en esos lenguajes; [9] los desarrolladores pueden simplemente escribir en Nim y luego compilar en cualquier lenguaje compatible. Esto también permite escribir aplicaciones para iOS y Android . También hay un backend LLVM no oficial , que permite el uso del compilador Nim de forma independiente. [18]
El compilador Nim es autohospedado , lo que significa que está escrito en el lenguaje Nim. [32] El compilador admite la compilación cruzada, por lo que puede compilar software para cualquiera de los sistemas operativos compatibles, sin importar la máquina de desarrollo. Esto es útil para compilar aplicaciones para sistemas integrados y para arquitecturas informáticas poco comunes y poco conocidas. [ cita requerida ]
Opciones del compilador
De forma predeterminada, el compilador Nim crea una compilación de depuración . [33]
Con la opción se puede crear -d:releaseuna compilación de lanzamiento , que está optimizada para la velocidad y contiene menos comprobaciones en tiempo de ejecución. [33]
Con la opción -d:dangerse pueden deshabilitar todas las comprobaciones en tiempo de ejecución, si se desea la máxima velocidad. [33]
Gestión de la memoria
Nim admite múltiples estrategias de gestión de memoria, incluidas las siguientes: [34]
--mm:arc– El conteo automático de referencias (ARC) con optimizaciones de semántica de movimiento ofrece un montón compartido. Ofrece un rendimiento totalmente determinista para sistemas de tiempo real estrictos. [35] Los ciclos de referencia pueden causar fugas de memoria: se pueden solucionar anotando pragmas manualmente{.acyclic.}o utilizando--mm:orc.--mm:orc– Igual que--mm:arcpero agrega un recolector de ciclos (el "O") basado en la "eliminación de prueba". [36] El recolector de ciclos solo analiza los tipos si son potencialmente cíclicos.--mm:refc– Recolector de basura basado en recuento de referencias diferidas estándar con un simple recolector de basura de respaldo de marcado y barrido para recolectar ciclos. Los montones son locales para cada subproceso.--mm:markAndSweep– Recolector de basura simple basado en marcado y barrido . Los montones son locales para cada subproceso.--mm:boehm– Recolector de basura basado en Boehm , ofrece un montón compartido.--mm:go– Recolector de basura de Go , útil para la interoperabilidad con Go . Ofrece un montón compartido.--mm:none– No existe una estrategia de gestión de memoria ni un recolector de basura . La memoria asignada simplemente nunca se libera, a menos que el código del desarrollador la libere manualmente.
A partir de Nim 2.0, ORC es el GC predeterminado. [37]
Herramientas de desarrollo
Agrupado
El paquete de instalación de Nim incluye muchas herramientas, entre ellas:
Ágil
Nimble es el gestor de paquetes estándar que utiliza Nim para empaquetar módulos de Nim. [38] Fue desarrollado inicialmente por Dominik Picheta, quien también es un desarrollador principal de Nim. Nimble ha sido incluido como el gestor de paquetes oficial de Nim desde el 27 de octubre de 2015, la versión v0.12.0. [39]
Los paquetes de Nimble se definen mediante .nimblearchivos que contienen información sobre la versión del paquete, el autor, la licencia, la descripción, las dependencias y más. [20] : 132 Estos archivos admiten un subconjunto limitado de la sintaxis de Nim llamado NimScript, cuya principal limitación es el acceso a la FFI. Estos scripts permiten cambiar el procedimiento de prueba o escribir tareas personalizadas.
La lista de paquetes se almacena en un archivo de notación de objetos JavaScript ( JSON ) al que se puede acceder libremente en el repositorio nim-lang/packages en GitHub. Este archivo JSON proporciona a Nimble una correlación entre los nombres de los paquetes y las URL de sus repositorios de Git o Mercurial.
Nimble viene con el compilador Nim. Por lo tanto, es posible probar el entorno Nimble ejecutando:
nimble -v. Este comando revelará el número de versión, la fecha y hora de compilación y el hash Git de Nimble. Nimble utiliza el paquete Git, que debe estar disponible para que Nimble funcione correctamente. La línea de comandos de Nimble se utiliza como interfaz para instalar, eliminar (desinstalar) y actualizar o aplicar parches a los paquetes de módulos. [20] : 130–131
c2nim
c2nim es un compilador de código fuente a código fuente (transcompilador o transpilador) diseñado para usarse en encabezados C / C++ para ayudar a generar nuevos enlaces Nim. [40] El resultado es un código Nim legible por humanos que debe editarse a mano después del proceso de traducción.
cocinar
Koch es un script de mantenimiento que se utiliza para crear Nim y proporcionar documentación HTML. [41]
negrita
nimgrep es una herramienta genérica para manipular texto. Se utiliza para buscar expresiones regulares, patrones de clavijas y contenidos de directorios, y se puede utilizar para reemplazar tareas. Se incluye para ayudar con la búsqueda de identificadores insensibles al estilo de Nim. [42]
nimsugerir
nimsuggest es una herramienta que ayuda a cualquier editor de código fuente a consultar un .nimarchivo fuente para obtener información útil como la definición de símbolos o sugerencias para completarlos. [43]
nimiedad
niminst es una herramienta para generar un instalador para un programa Nim. [44] Crea instaladores .msi para Windows a través de Inno Setup y scripts de instalación y desinstalación para Linux , macOS y Berkeley Software Distribution (BSD).
Ligeramente despreocupado
nimpretty es un embellecedor de código fuente, utilizado para formatear el código de acuerdo con la guía de estilo oficial de Nim. [45]
Testamento
Testament es un ejecutor automático avanzado de pruebas unitarias para pruebas de Nim. Se utiliza en el desarrollo de Nim y ofrece pruebas de aislamiento de procesos, genera estadísticas sobre casos de prueba, admite múltiples objetivos y simulaciones de ejecución en seco, tiene registro, puede generar informes HTML, puede omitir pruebas desde un archivo y más.
Otras herramientas destacables
Algunas herramientas notables que no están incluidas en la distribución de Nim incluyen:
elegirnim
choosenim fue desarrollado por Dominik Picheta, creador del gestor de paquetes Nimble, como una herramienta que permite instalar y utilizar múltiples versiones del compilador Nim. Descarga cualquier versión estable o de desarrollo del compilador Nim desde la línea de comandos, lo que permite cambiar fácilmente entre ellas. [46]
Nimbio
nimpy es una biblioteca que permite una integración conveniente de Python en programas Nim. [47]
duendecito
Pixie es una biblioteca de gráficos 2D con muchas funciones, similar a Cairo o Skia . Utiliza aceleración SIMD para acelerar drásticamente la manipulación de imágenes. Admite muchos formatos de imagen, fusión, enmascaramiento y desenfoque, y se puede combinar con la biblioteca Boxy para realizar renderizado acelerado por hardware.
nimterop
nimterop es una herramienta enfocada en automatizar la creación de envoltorios C/C++ necesarios para la interfaz de funciones externas de Nim. [48]
Bibliotecas
Bibliotecas puras/impuras
Las bibliotecas puras son módulos escritos únicamente en Nim. No incluyen contenedores para acceder a bibliotecas escritas en otros lenguajes de programación.
Las bibliotecas impuras son módulos de código Nim que dependen de bibliotecas externas escritas en otros lenguajes de programación como C.
Biblioteca estándar
La biblioteca estándar de Nim incluye módulos para todas las tareas básicas, entre ellas: [49]
- Módulos del sistema y del núcleo
- Colecciones y algoritmos
- Manejo de cadenas
- Manejo del tiempo
- Servicios genéricos del sistema operativo
- Bibliotecas de matemáticas
- Protocolos y soporte de Internet
- Enhebrado
- Analizadores sintácticos
- Docutils
- Procesamiento XML
- Generador de código XML y HTML
- Hash (hash)
- Soporte de bases de datos (PostgreSQL, MySQL y SQLite)
- Envoltorios (API Win32, POSIX)
Uso de otras bibliotecas
Un programa Nim puede utilizar cualquier biblioteca que pueda utilizarse en un programa C, C++ o JavaScript. Existen enlaces de lenguaje para muchas bibliotecas, incluidas GTK , [50] [51] Qt QML, [52] wxWidgets , [53] SDL 2 , [54] [55] Raylib , [56] Godot , [57] UE5 , [58] Cairo , [59] OpenGL , [60] Vulkan , [61] WinAPI , [62] zlib , libzip , OpenSSL y cURL . [63] Nim funciona con bases de datos PostgreSQL , MySQL y SQLite .
Existen herramientas de código abierto con diversos grados de soporte que pueden usarse para interconectar Nim con los lenguajes de programación Lua , [64] Julia , [65] Rust , [66] C# , [67] y Python [68] o transpilar Nim a TypeScript . [69]
Ejemplos
Hola Mundo
El programa "¡Hola, mundo!" en Nim:
echo ( "Hola, mundo!" )
# Los procedimientos pueden ser llamados sin paréntesis
echo "Hola, mundo!"
Se puede lograr otra versión de "Hola mundo" llamando a la writefunción con el stdoutflujo:
stdout .write ( "¡Hola, mundo! \n " ) write ( stdout , "¡Hola, mundo ! \n " )
Fibonacci
Varias implementaciones de la función Fibonacci , que muestran retornos implícitos, parámetros predeterminados, iteradores, recursión y bucles while:
proc fib ( n : Natural ): Natural = si n < 2 : devuelve n de lo contrario : devuelve fib ( n - 1 ) + fib ( n - 2 ) func fib2 ( n : int , a = 0 , b = 1 ): int = si n == 0 : a de lo contrario : fib2 ( n - 1 , b , a + b ) iterador fib3 : int = var a = 0 var b = 1 mientras sea verdadero : produce a intercambia a , b b += a
Factorial
Programa para calcular el factorial de un entero positivo utilizando el enfoque iterativo, mostrando el manejo de errores try/catch y bucles for:
importar std / strutils
var n = 0 try : stdout . write "Ingrese un número entero positivo: " n = stdin . readline . parseInt except ValueError : raise newException ( ValueError , "Debe ingresar un número positivo" )
var fact = 1 para i en 2 .. n : fact = fact * i
eco de hecho
Usando el módulo matemático de la biblioteca estándar de Nim:
importar std / math echo fac ( x )
Invertir una cadena
Una demostración simple que muestra la variable de resultado implícita y el uso de iteradores.
proc reverse ( s : string ): string = for i in countdown ( s . high , 0 ): resultado . add s [ i ]
deja que str1 = "¡Invierta esto!" echo "Invertido: " , reverse ( str1 )
Una de las características más exóticas de Nim es la resultvariable implícita. Cada procedimiento en Nim con un tipo de retorno distinto de void tiene una variable de resultado implícita que representa el valor que se devolverá. En el bucle for vemos una invocación de countdownwhich is a iterator. Si se omite un iterador, el compilador intentará utilizar un itemsiterador, si hay uno definido para el tipo especificado.
Interfaz gráfica de usuario
Uso de GTK 3 con introspección de GObject a través del módulo gintro:
importar gintro /[ gtk , glib , gobject , gio ]
proc appActivate ( app : Application ) = let window = newApplicationWindow ( app ) window.title = " Aplicación GTK3 con introspección de gobject" window.defaultSize = ( 400 , 400 ) showAll ( window )
proc main = let app = newApplication ( "org.gtk.example" ) connect ( app , "activate" , appActivate ) discard run ( app )
principal ()
Este código requiere el módulo gintro para funcionar, el cual no forma parte de la biblioteca estándar. Para instalar el módulo gintro y muchos otros, puedes utilizar la herramienta nimble, que viene como parte de Nim. Para instalar el módulo gintro con nimble, haz lo siguiente:
Instalación ágil de gintro
Paradigmas de programación
Programación funcional
La programación funcional está respaldada en Nim a través de funciones de primera clase y código sin efectos secundarios a través del noSideEffectpragma o la funcpalabra clave. [70] Nim realizará un análisis de efectos secundarios y generará errores de compilación para el código que no obedezca el contrato de no producir efectos secundarios cuando se compila con la característica experimental strictFuncs, que se planea que se convierta en la predeterminada en versiones posteriores. [71]
A diferencia de los lenguajes de programación puramente funcionales , Nim es un lenguaje de programación multiparadigma , por lo que las restricciones de programación funcional se implementan función por función.
Funciones de primera clase
Nim admite funciones de primera clase al permitir que las funciones se almacenen en variables o se pasen de forma anónima como parámetros para ser invocados por otras funciones. [72] El std/sugarmódulo proporciona sintaxis simplificada para funciones anónimas en declaraciones de tipo e instancias.
importar std /[ secutils , azúcar ]
sea potenciasDeDos = @[ 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 , 256 ]
proc filter [ T ] ( s : openArray [ T ] , pred : T - > bool ) : seq [ T ] = resultado = newSeq [ T ] ( ) para i en 0 ... < s.len : if pred ( s [ i ] ) : resultado.add ( s [ i ] )
echo powersOfTwo . filter ( proc ( x : int ): bool = x > 32 ) # sintaxis simplificada para lo anterior, proporcionada como una macro desde std/sugar echo powersOfTwo . filter ( x => x > 32 )
proc mayorQue32 ( x : int ) : bool = x > 32 echo powersOfTwo.filter ( mayorQue32 )
Efectos secundarios
Se comprueban los efectos secundarios de las funciones anotadas con el noSideEffectpragma y el compilador se negará a compilar funciones que no cumplan con estos requisitos. Los efectos secundarios en Nim incluyen mutación, acceso o modificación de estado global, código asincrónico, código enhebrado y IO. La mutación de parámetros puede ocurrir para funciones que toman parámetros de tipo varo ref: se espera que esto no se compile con el actualmente experimental strictFuncsen el futuro. [73] La funcpalabra clave introduce un atajo para un noSideEffectpragma. [74]
func binarySearch[T](a: openArray[T]; elem: T): int# es la abreviatura de...proc binarySearch[T](a: openArray[T]; elem: T): int{.sin efecto secundario.} {.experimental: "FuncionesEstrictas".}typeNode = ref objectle, ri: Nodedata: stringfunc len(n: Node): int =# válido: len no tiene efectos secundariosvar it = nwhile it != nil:inc resultit = it.rifunc mut(n: Node) =let m = n # is the statement that connected the mutation to the parameterm.data = "yeah" # the mutation is here# Error: 'mut' can have side effects# an object reachable from 'n' is potentially mutated
Composición de funciones
La sintaxis de llamada de función uniforme permite el encadenamiento de funciones arbitrarias , tal vez mejor ejemplificada con la std/sequtilsbiblioteca. [75]
importar std /[ secutils , azúcar ]
let numbers = @[ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 ] # a y b son identificadores especiales en la macro foldr echo numbers . filter ( x => x > 3 ). deduplicate . foldr ( a + b ) # 30
Tipos de datos algebraicos y coincidencia de patrones
Nim admite tipos de productos a través del objecttipo y tipos de suma a través de variantes de objeto : representaciones sin procesar de uniones etiquetadas , con una etiqueta de tipo enumerada que debe coincidir de forma segura antes de poder acceder a los campos de variantes. [76] Estos tipos se pueden componer algebraicamente . La coincidencia de patrones estructurales está disponible, pero regulada a macros en varias bibliotecas de terceros. [77]
importar std / tablas
tipo
Valor = uint64 Ident = cadena ExprKind = enumeración Literal , Variable , Abstracción , Aplicación Expr = objeto de referencia caso tipo : ExprKind de Literal : litIdent : Valor de Variable : varIdent : Ident de Abstracción : paramAbs : Ident funcAbs : Expr de Aplicación : funcApp , argApp : Expr
func eval ( expr : Expr , contexto : var Tabla [ Ident , Valor ] ) : Valor = caso expr.tipo de Literal : return expr.litIdent de Variable : return contexto [ expr.varIdent ] de Aplicación : caso expr.funcApp.tipo de Abstracción : contexto [ expr.funcApp.paramAbs ] = expr.argApp.eval ( contexto ) return expr.funcAbs.eval ( contexto ) de lo contrario : generar newException ( ValueError , " ¡ Expresión no válida ! " ) de lo contrario : generar newException ( ValueError , " ¡ Expresión no válida ! " )
Programación orientada a objetos
A pesar de ser principalmente un lenguaje imperativo y funcional, Nim admite varias características para habilitar paradigmas orientados a objetos. [78] [79]
Subtipificación y herencia
Nim admite la herencia limitada mediante el uso de ref objectsla palabra clave y of. [79] Para habilitar la herencia, cualquier objeto inicial ("raíz") debe heredar de RootObj. La herencia tiene un uso limitado dentro del código idiomático de Nim: con la notable excepción de Excepciones. [80]
tipo Animal = objeto de referencia de RootObj nombre : cadena edad : int tipo Perro = objeto de referencia de Animal tipo Gato = objeto de referencia de Animal
var animales : seq [ Animal ] = @[] animales . add ( Perro ( nombre : "Sparky" , edad : 10 )) animales . add ( Gato ( nombre : "Mitten" , edad : 10 ))
para un en animales : afirmar un de Animal
Las relaciones de subtipificación también se pueden consultar con la ofpalabra clave. [79]
Llamadas a métodos y encapsulamiento
La sintaxis de llamada de función uniforme de Nim permite llamar a funciones ordinarias con una sintaxis similar a la de las invocaciones de llamadas a métodos en otros lenguajes de programación. Esto es funcional para los "getters": Nim también proporciona sintaxis para la creación de dichos "setters". Los objetos pueden hacerse públicos en función de cada campo, lo que permite la encapsulación.
tipo Socket * = ref objeto host : int # privado, carece de marcador de exportación
# captador de la dirección del host
proc host * ( s : Socket ): int = s . host
# establecedor de la dirección del host
proc `host=` * ( s : var Socket , value : int ) = s . host = value
var s : Socket new s assert s . host == 0 # igual que host(s), s.host() s . host = 34 # igual que `host=`(s, 34)
Despacho dinámico
Se prefiere el envío estático , tiene mayor rendimiento y es estándar incluso entre las rutinas que parecen métodos. [79] No obstante, si se desea el envío dinámico, Nim proporciona la methodpalabra clave para habilitar el envío dinámico en tipos de referencia.
importar std / strformat
tipo
Persona = objeto de referencia de RootObj nombre : cadena Estudiante = objeto de referencia de Persona Profesor = objeto de referencia de Persona
método introducir ( a : Persona ) = generar newException ( CatchableError , "Método sin anulación de implementación" )
método introducir ( a : Estudiante ) = echo & "¡Soy un estudiante llamado {a.nombre}!"
método introducir ( a : Profesor ) = echo & "¡Soy un profesor llamado {a.nombre}!" let personas : seq [ Persona ] = @[ Profesor ( nombre : "Alice" ) , Estudiante ( nombre : "Bob" ) ] for persona in personas : persona.introducir ( )
Metaprogramación
Plantillas
Nim admite la sustitución simple en el árbol de sintaxis abstracta a través de sus plantillas.
plantilla genType ( nombre , nombre de campo : sin tipo , tipo de campo : typedesc ) = tipo nombre = objeto nombre de campo : tipo de campo
genType ( Prueba , foo , int )
var x = Prueba ( foo : 4566 ) echo ( x . foo ) # 4566
Se genTypeinvoca en tiempo de compilación y Testse crea un tipo.
Genéricos
Nim admite programación genérica con y sin restricciones. Los genéricos se pueden utilizar en procedimientos, plantillas y macros. Los identificadores genéricos sin restricciones ( Ten este ejemplo) se definen después del nombre de la rutina entre corchetes. Los genéricos con restricciones se pueden colocar en identificadores genéricos o directamente en parámetros.
proc addThese [ T ] ( a , b : T ): T = a + b echo addThese ( 1 , 2 ) # 3 (de tipo int) echo addThese ( uint8 1 , uint8 2 ) # 3 (de tipo uint8)
# ¡No queremos correr el riesgo de restar números sin signo!
proc subtractThese [ T : SomeSignedInt | float ] ( a , b : T ): T = a - b echo subtractThese ( 1 , 2 ) # -1 (de tipo int)
importar std / sequtils
# Los genéricos restringidos también pueden estar directamente en los parámetros
proc compareThese [ T ] ( a , b : string | seq [ T ] ): bool = for ( i , j ) in zip ( a , b ): if i != j : return false
Se pueden aclarar aún más qué tipos aceptará el procedimiento especificando una clase de tipo (en el ejemplo anterior, SomeSignedInt). [81]
Macros
Las macros pueden reescribir partes del código en tiempo de compilación. Las macros de Nim son potentes y pueden operar en el árbol de sintaxis abstracta antes o después de la verificación semántica. [82]
A continuación se muestra un ejemplo simple que crea una macro para llamar al código dos veces:
importar std / macros
macro dos veces ( arg : sin tipo ): sin tipo = resultado = cita hacer : ` arg ` ` arg `
repite dos veces "¡Hola mundo!"
La twicemacro de este ejemplo toma la sentencia echo en forma de un árbol de sintaxis abstracta como entrada. En este ejemplo, decidimos devolver este árbol de sintaxis sin aplicarle ninguna manipulación, pero lo hacemos dos veces, de ahí el nombre de la macro. El resultado es que la macro reescribe el código para que se parezca al siguiente código en tiempo de compilación:
echo "¡Hola mundo!" echo "¡Hola mundo!"
Interfaz de función externa (FFI)
La FFI de Nim se utiliza para llamar a funciones escritas en otros lenguajes de programación con los que se puede compilar. Esto significa que las bibliotecas escritas en C, C++, Objective-C y JavaScript se pueden utilizar en el código fuente de Nim. Hay que tener en cuenta que tanto JavaScript como las bibliotecas de C, C++ u Objective-C no se pueden combinar en el mismo programa, ya que no son tan compatibles con JavaScript como entre sí. Tanto C++ como Objective-C se basan en C y son compatibles con él, pero JavaScript es incompatible, como lenguaje dinámico basado en la web del lado del cliente. [20] : 226
El siguiente programa muestra la facilidad con la que se puede utilizar código C externo directamente en Nim.
proc printf ( formatostr : cstring ) {.header : "<stdio.h>", varargs.}
printf ( "%s %d \n " , "foo" , 5 )
En este código, la printffunción se importa a Nim y luego se utiliza.
Ejemplo básico que utiliza 'console.log' directamente para el objetivo de compilación de JavaScript :
proc log ( args : cualquiera ) {.importjs : "console.log(@)", varargs.} log ( 42 , "z" , verdadero , 3.14 )
El código JavaScript producido por el compilador Nim se puede ejecutar con Node.js o un navegador web.
Paralelismo
Para activar la compatibilidad con subprocesos en Nim, se debe compilar un programa con --threads:onun argumento de línea de comandos. Cada subproceso tiene un montón de recolección de basura independiente y el uso compartido de la memoria está restringido, lo que mejora la eficiencia y evita las condiciones de carrera de los subprocesos.
importar std / bloqueos
var
thr : matriz [ 0 .. 4 , Hilo [ tupla [ a , b : int ]]] L : Bloqueo
proc threadFunc ( intervalo : tupla [ a , b : int ] ) { .thread. } = for i in intervalo.a .. intervalo.b : adquirir ( L ) # bloquear stdout echo i liberar ( L )
Bloqueo de inicio ( L )
para i en 0 .. alto ( thr ): createThread ( thr [ i ] , threadFunc , ( i * 10 , i * 10 + 5 )) joinThreads ( thr )
Nim también tiene un channelsmódulo que simplifica el paso de datos entre subprocesos.
importar std / os
tipo
CalculationTask = objeto id * : int datos * : int
CalculationResult = id del objeto * : int resultado * : int
var task_queue : Canal [ TareaDeCálculo ] var result_queue : Canal [ ResultadoDeCálculo ]
proc workerFunc () { .thread .} = result_queue.open ()
mientras sea verdadero : var tarea = cola_de_tareas.recv ( ) cola_de_resultados.send ( CalculationResult ( id : tarea.id , resultado : tarea.datos * 2 ) )
var workerThread : Hilo [ void ] createThread ( workerThread , workerFunc )
task_queue . open ()
task_queue . send ( CalculationTask ( id : 1 , datos : 13 )) task_queue . send ( CalculationTask ( id : 2 , datos : 37 ))
mientras sea verdadero : echo "obtuvo el resultado: " , repr ( result_queue . recv ())
Concurrencia
La E/S asincrónica se admite a través del asyncdispatchmódulo en la biblioteca estándar o la biblioteca externa chronos. [83] Ambas bibliotecas agregan la sintaxis async/await a través del sistema de macros, sin necesidad de compatibilidad con lenguajes especiales. Un ejemplo de un servidor HTTP asincrónico :
import std /[ asynchttpserver , asyncdispatch ] # chronos también podría usarse alternativamente en lugar de asyncdispatch, # sin otros cambios.
var servidor = newAsyncHttpServer () proc cb ( req : Solicitud ) { .async.} = await req.respond ( Http200 , " Hola mundo" )
esperarPara servidor .servir ( Puerto ( 8080 ) , cb )
Comunidad
En línea
Nim tiene una comunidad activa en el foro oficial autoalojado y desarrollado por él mismo. [84] Además, el proyecto utiliza un repositorio Git, un rastreador de errores, un rastreador de RFC y una wiki alojada en GitHub , donde la comunidad interactúa con el lenguaje. [85] También hay salas de chat oficiales en línea, conectadas entre IRC , Matrix , Discord , Gitter y Telegram . [86]
Convenciones
La primera conferencia de Nim, NimConf, tuvo lugar el 20 de junio de 2020. Se llevó a cabo de forma digital debido al COVID-19 , con una convocatoria abierta para charlas de colaboradores en forma de videos de YouTube . [87] La conferencia comenzó con descripciones generales del lenguaje por parte de los desarrolladores de Nim, Andreas Rumpf y Dominik Picheta. Los temas de presentación incluyeron charlas sobre marcos web, desarrollo móvil , dispositivos de Internet de las cosas (IoT) y desarrollo de juegos , incluida una charla sobre cómo escribir Nim para Game Boy Advance . [88] NimConf 2020 está disponible como una lista de reproducción de YouTube. [89] NimConf 2021 se llevó a cabo al año siguiente, también se llevó a cabo de forma digital e incluyó charlas sobre desarrollo de juegos , REPL , sistemas operativos en tiempo real , Nim en la industria, mapeo relacional de objetos (ORM), fuzzing , diseño de lenguajes y bibliotecas de gráficos . [90]
Además de las conferencias oficiales, Nim ha aparecido en varias otras convenciones. Se realizó una presentación sobre Nim en la Convención de Código Abierto O'Reilly (OSCON) en 2015. [91] [92] [93] Cuatro oradores representaron a Nim en FOSDEM 2020, incluido el creador del lenguaje, Andreas Rumpf. [94] En FOSDEM 2022, Nim organizó su propia sala de desarrolladores de forma virtual debido a la pandemia de COVID-19 . [95] Se llevaron a cabo charlas sobre concurrencia , programación integrada , programación para GPU , sistemas de entidad-componente , desarrollo de juegos , motores de reglas , interoperabilidad de Python y metaprogramación . [96]
Véase también
- C (lenguaje de programación)
- C++ (lenguaje de programación)
- Crystal (lenguaje de programación)
- D (lenguaje de programación)
- Go (lenguaje de programación)
- Rust (lenguaje de programación)
- Puntero gordo
Referencias
- ^ "Colaboradores de nim-lang/Nim". GitHub . Consultado el 23 de marzo de 2022 .
- ^ https://github.com/nim-lang/Nim/releases/tag/v2.2.0.
{{cite web}}: Falta o está vacío|title=( ayuda ) - ^ "Nim con el ejemplo". GitHub . Consultado el 20 de julio de 2014 .
- ^ Караджов, Захари; Станимиров, Borislav (2014). Metaprograma de Nimrod. VarnaConf (en búlgaro) . Consultado el 27 de julio de 2014 .
- ^ "Embalaje Nim" . Consultado el 23 de marzo de 2022 .
- ^ "Instalar Nim" . Consultado el 12 de octubre de 2018 .
- ^ "copiando.txt". GitHub .
- ^ ab Rumpf, Andreas (19 de octubre de 2017). "Nim sin GC". Reflexiones de Araq . Consultado el 1 de septiembre de 2020 .
- ^ ab Rumpf, Andreas (11 de febrero de 2014). "Nimrod: un nuevo lenguaje de programación de sistemas". Diario del Dr. Dobb . Consultado el 20 de julio de 2014 .
- ^ "El lenguaje de programación Nim". Nim-lang.org . Consultado el 20 de julio de 2014 .
- ^ "Preguntas frecuentes". nim-lang.org . Consultado el 27 de marzo de 2015 .
- ^ Kehrer, Aaron (akehrer) (5 de enero de 2015). "Sintaxis de Nim". GitHub . Consultado el 5 de enero de 2015 .
- ^ abc "Manual de Nim". Nim-lang.org . Consultado el 20 de julio de 2014 .
- ^ "Presentación de Strangeloop Nim". Archivado desde el original el 13 de julio de 2014. Consultado el 30 de abril de 2015 .
- ^ "Gestión de la memoria de Nim". nim-lang.org . Consultado el 17 de agosto de 2023 .
- ^ Binstock, Andrew (7 de enero de 2014). "El auge y la caída de las lenguas en 2013". Diario del Dr. Dobb . Consultado el 8 de octubre de 2018 .
- ^ Guía del usuario del compilador Nim
- ^ ab Sieka, Jacek (18 de julio de 2020), arnetheduck/nlvm , consultado el 21 de julio de 2020
- ^ "Nim Releases". Proyecto Nim . Consultado el 26 de enero de 2020 .
- ^ abcd Picheta, Dominik (2017). Nim en acción . Publicaciones Manning. ISBN 978-1617293436.
- ^ "Fuentes de Nim Pascal". GitHub . Consultado el 5 de abril de 2013 .
- ^ "Noticias". Nim-lang.org . Archivado desde el original el 26 de junio de 2016. Consultado el 11 de junio de 2016 .
- ^ "Colaboradores". GitHub . Consultado el 5 de abril de 2013 .
- ^ Picheta, Dominik (2014-12-29). «Versión 0.10.2 publicada». Nim-lang.org . Consultado el 2018-10-17 .
- ^ "Nim v2.0 lanzado". Lenguaje de programación Nim . Consultado el 17 de agosto de 2023 .
- ^ Yegulalp, Serdar (16 de enero de 2017). "El lenguaje Nim se nutre de lo mejor de Python, Rust, Go y Lisp". InfoWorld .
- ^ Entrevista con el creador del lenguaje Nim, Andreas Rumpf, 2020-03-09 , consultado el 2023-10-15
- ^ "Manual de Nim: Sintaxis de llamada de método" . Consultado el 12 de octubre de 2018 .
- ^ "Manual de Nim: Igualdad de identificadores". nim-lang.org . Consultado el 17 de agosto de 2023 .
- ^ Picheta, Dominik (dom96); Wetherfordshire, Billingsly (fowlmouth); Felsing, Dennis (def-); Raaf, Hans (oderwat); Dunn, Christopher (cdunn2001); wizzardx (2017-10-25). "Consejos y trucos". GitHub . Consultado el 2018-10-17 .
{{cite web}}: CS1 maint: nombres numéricos: lista de autores ( enlace ) - ^ Rumpf, Andreas (15 de enero de 2014). Nimrod: un nuevo enfoque de la metaprogramación. InfoQ . El evento ocurre a las 2:23 . Consultado el 20 de julio de 2014 .
- ^ Rumpf, Andreas (12 de octubre de 2018). "Nim Compiling". GitHub . Consultado el 17 de octubre de 2018 .
- ^ abc "Guía del usuario del compilador Nim".
- ^ "Gestión de la memoria de Nim". nim-lang.org . Consultado el 28 de julio de 2024 .
- ^ "Introducción a ARC/ORC en Nim". Lenguaje de programación Nim . Consultado el 17 de agosto de 2023 .
- ^ "ORC - Vorsprung durch Algorithmen". Lenguaje de programación Nim . Consultado el 17 de agosto de 2023 .
- ^ "Nim v2.0 lanzado". Lenguaje de programación Nim . Consultado el 17 de agosto de 2023 .
- ^ "Nimble". GitHub . Consultado el 12 de octubre de 2018 .
- ^ "Lanzamiento de Nim v0.12.0". GitHub . Consultado el 28 de noviembre de 2020 .
- ^ "c2nim". GitHub . Consultado el 12 de octubre de 2018 .
- ^ "Script de mantenimiento de Nim". nim-lang.org . Consultado el 16 de noviembre de 2021 .
- ^ "Manual del usuario de nimgrep". nim-lang.org . Consultado el 16 de noviembre de 2021 .
- ^ "Guía de integración de IDE de Nim". nim-lang.org . Consultado el 16 de noviembre de 2021 .
- ^ "Manual del usuario de niminst". nim-lang.org . Consultado el 16 de noviembre de 2021 .
- ^ "Herramientas disponibles con Nim". nim-lang.org . 2021-10-19. Archivado desde el original el 2015-05-09 . Consultado el 2022-02-18 .
- ^ "choosenim". GitHub . Consultado el 12 de octubre de 2018 .
- ^ Glukhov, Yuriy (12 de noviembre de 2021), ágil , consultado el 16 de noviembre de 2021
- ^ nimterop/nimterop, nimterop, 2021-11-12 , consultado el 16 de noviembre de 2021
- ^ Biblioteca estándar de Nim
- ^ Instalación, El lenguaje de programación Nim, 2021-09-25 , consultado el 2021-11-16
- ^ StefanSalewski (15 de noviembre de 2021), Enlaces GTK4 y GTK3 de alto nivel para el lenguaje de programación Nim , consultado el 16 de noviembre de 2021
- ^ "NimQml". GitHub . 10 de noviembre de 2022.
- ^ "WxNim". GitHub . 2022-11-29.
- ^ SDL2 para Nim, El lenguaje de programación Nim, 26 de octubre de 2021 , consultado el 16 de noviembre de 2021
- ^ Arabadzhi, Vladimir (15 de noviembre de 2021), sdl2_nim 2.0.14.2 , consultado el 16 de noviembre de 2021
- ^ "naylib". GitHub . 28 de julio de 2024.
- ^ "godot-nim". GitHub . 28 de julio de 2024.
- ^ "NimForUE". GitHub . 28 de julio de 2024.
- ^ Cairo, El lenguaje de programación Nim, 5 de octubre de 2021 , consultado el 16 de noviembre de 2021
- ^ opengl, El lenguaje de programación Nim, 2021-11-14 , consultado el 2021-11-16
- ^ "vulkan". GitHub . 28 de julio de 2024.
- ^ Ward (15 de noviembre de 2021), Winim , consultado el 16 de noviembre de 2021
- ^ "Biblioteca estándar de Nim". Documentación de Nim . Archivado desde el original el 6 de abril de 2015. Consultado el 4 de abril de 2015 .
- ^ Lim, Andri (jangko) (17 de octubre de 2018). "nimLUA". GitHub . Consultado el 17 de octubre de 2018 .
- ^ "NimJL". GitHub . 2022-08-24.
- ^ "Nbindgen". GitHub . 17 de noviembre de 2022.
- ^ "cs2nim". GitHub . 10 de octubre de 2022.
- ^ Glukhov, Yuriy (20 de julio de 2020), yglukhov / nimpy , consultado el 21 de julio de 2020
- ^ "ts2nim". GitHub . 21 de noviembre de 2022.
- ^ "Manual de Nim". nim-lang.org . Consultado el 10 de julio de 2021 .
- ^ "Foro Nim: Actualización sobre funciones estrictas". forum.nim-lang.org . Consultado el 17 de agosto de 2023 .
- ^ "Nim por ejemplo - Funciones de primera clase".
- ^ "Características experimentales de Nim: funciones estrictas".
- ^ "Manual de Nim: Funciones".
- ^ "std/sequtils". nim-lang.org . Consultado el 17 de agosto de 2023 .
- ^ "Manual de Nim: variantes de objetos". nim-lang.org . Consultado el 17 de agosto de 2023 .
- ^ "src/fusion/matching". nim-lang.github.io . Consultado el 17 de agosto de 2023 .
- ^ "Tutorial de Nim (Parte II): Programación orientada a objetos". nim-lang.org . Consultado el 17 de agosto de 2023 .
- ^ abcd "Nim by Example - Programación orientada a objetos". nim-by-example.github.io . Consultado el 17 de agosto de 2023 .
- ^ "sistema/excepciones". nim-lang.org . Consultado el 17 de agosto de 2023 .
- ^ "Manual de Nim: clases de tipos". nim-lang.org . Consultado el 21 de julio de 2020 .
- ^ "Tutorial de Nim (Parte III)". nim-lang.org . Consultado el 17 de agosto de 2023 .
- ^ Chronos - Una biblioteca eficiente para programación asincrónica, Estado, 2023-08-14 , recuperado 2023-08-17
- ^ "Foro Nim". nim-lang.org . Consultado el 4 de mayo de 2015 .
- ^ "Repositorio de código fuente primario y rastreador de errores". GitHub . Consultado el 4 de mayo de 2015 .
- ^ "Comunidad". Lenguaje de programación Nim . Consultado el 17 de agosto de 2023 .
- ^ "Conferencia en línea Nim 2020". Nim . Consultado el 28 de noviembre de 2020 .
- ^ "NimConf 2020". Nim . Consultado el 17 de agosto de 2023 .
- ^ "Lista de reproducción de NimConf 2020". YouTube . Consultado el 28 de noviembre de 2020 .
- ^ "NimConf 2021". NimConf 2021 . Consultado el 17 de agosto de 2023 .
- ^ "Nim en OSCON 2015". Convención de código abierto de O'Reilly (OSCON) . O'Reilly Media. 20 de julio de 2015. Archivado desde el original el 6 de octubre de 2015. Consultado el 17 de octubre de 2018 .
- ^ Rumpf, Andreas; Swartz, Jason; Harrison, Matt. "Lenguajes esenciales: Nim, Scala, Python". O'Reilly . O'Reilly Media . Consultado el 17 de octubre de 2018 .
- ^ Rumpf, Andreas (26 de octubre de 2015). OSCON 2015 – Nim: una descripción general. YouTube (vídeo) . Consultado el 12 de octubre de 2018 .
- ^ "Eventos". fosdem.org . Consultado el 17 de febrero de 2020 .
- ^ "Nim Devroom en FOSDEM 2022 - Convocatoria de participación". Lenguaje de programación Nim . Consultado el 17 de agosto de 2023 .
- ^ "Sala de desarrollo del lenguaje de programación Nim". archive.fosdem.org . Consultado el 17 de agosto de 2023 .
Enlaces externos
- Sitio web oficial
- Nim en GitHub
- Información sobre Nim en Stack Overflow
- Programación de computadoras con el lenguaje de programación Nim Una introducción suave por Stefan Salewski