DEV Community

Juan Carlos
Juan Carlos

Posted on

Aprende a programar con Nim

Copipastear

  • Todos los ejemplos se pueden copiar y pegar para ejecutarlos directamente!

Playground para practicar desde el navegador web.

Instalar en la computadora.

Hola Mundo

echo sirve para imprimir por la terminal los argumentos

echo "Hola Mundo"
Enter fullscreen mode Exit fullscreen mode

Otro ejemplo

echo 1, true, 2.0, "OwO", false, -9, 0
Enter fullscreen mode Exit fullscreen mode

Comentarios

Los comentarios son texto ignorado por el programa,
es decir el texto en un comentario no existe para la computadora,
usualmente se usa para documentar el codigo para que las personas lo puedan entender mejor.

Comentario es una linea que empieza con #.

# Esto es un comentario
echo "Hola" , " ", "Mundo" # Otro comentario
Enter fullscreen mode Exit fullscreen mode

Tipos Basicos

assert comprueba que el argumento evalua a Verdadero.

is sirve para comprobar el tipo de algo,
se usa de la forma valor is Tipo.

assert 42 is int
assert 3.14 is float
assert true is bool
assert "x" is string
assert 'z' is char
Enter fullscreen mode Exit fullscreen mode

Variables

Las variables se declaran con var, let, const.

var nombre = "valor"
Enter fullscreen mode Exit fullscreen mode

Mas ejemplos:

var a = 42

var
  b = "Para no repetir tanto el 'var' "
  c = "podes agrupar las variables asi"
  d = true

let e = 666 +
  420 *
  42
Enter fullscreen mode Exit fullscreen mode
Tiempo de Compilacion Tiempo de Ejecucion Inmutable Requiere Asignamiento
var No Si No No
let No Si Si Si
const Si No Si Si

Matematica Basica

Division entera usa el operador div

Modulo usa el operador mod

echo 1 + 2
echo 2 - 1
echo 2 * 2
echo 4 / 2
echo 4 div 2
echo 4 mod 2
Enter fullscreen mode Exit fullscreen mode

Valores Numericos

Puedes usar numeros Binarios, Hexadecimales, Octales, etc.

echo 0b1100  # Binario
echo 0xFFFF  # Hexadecimal
echo 0o777   # Octal

# _ es ignorado, es util para numeros grandes
echo 2_000_000

# Se comprobara que este numero siempre sea Positivo.
echo 0.Positive  # >= 0

# Se comprobara que este numero siempre sea Natural.
echo 1.Natural   # > 0
Enter fullscreen mode Exit fullscreen mode

If Elif Else

Control de flujo con bloques If Elif Else

if 9 > 0:
  echo "Ejemplo"
Enter fullscreen mode Exit fullscreen mode
var condicional = true

if condicional:
  echo 42
else:
  echo 0
Enter fullscreen mode Exit fullscreen mode

Un If Elif Else en una linea es un "Operador Ternario"

var condicional = true

if condicional: echo 42 else: echo 0
Enter fullscreen mode Exit fullscreen mode

Mas ejemplos

var valor = 5

if valor == 0:
  echo "valor es cero"
if valor < 0:
  echo "valor es negativo"
else:
  echo "valor es positivo"
Enter fullscreen mode Exit fullscreen mode

Case Switch

Case Switch es similar a un If Elif Else pero funciona distinto.
Tambien puede tener un else:

var valor = "gato"

case valor
of "perro":
  echo "valor es perro"
of "gato", "gatito":
  echo "valor es gato"
else:
  echo "valor es otro animal"
Enter fullscreen mode Exit fullscreen mode

case switch puede coincidir con multiples condiciones
of 1, 2, 3, 4, 5: en el ejemplo de abajo.

case switch puede usar elif como se observa abajo.

var valor = 42

case valor
of 0:
  echo "valor es cero"
of 1, 2, 3, 4, 5:
  echo "valor esta entre 0 y 5"
of 6..9:
  echo "valor esta entre 6 y 9"
elif valor < 0:
  echo "valor es negativo"
else:
  echo "valor es otro numero"
Enter fullscreen mode Exit fullscreen mode

Bloques

Bloques de codigo con un nuevo Contexto (Scope) se crean con block

let ejemplo = "Afuera del block"

block:
  let ejemplo = "Adentro del block"
  echo ejemplo

echo ejemplo
Enter fullscreen mode Exit fullscreen mode

Tambien puede usarse para evaluar codigo a un valor

let valor = block:
  let a = 1
  let b = 2
  a + b

assert valor == 3
Enter fullscreen mode Exit fullscreen mode

Bloques pueden tener un nombre etiqueta.

Se puede salir explicitamente de un bloque usando break

echo "Afuera del block"

block el_bloque_loco:
  echo "Adentro del block"
  break el_bloque_loco

echo "Afuera del block"
Enter fullscreen mode Exit fullscreen mode

Bucle For

El bucle for sirve para iterar un valor iterable,
para aplicar algun tipo de logica a los items individualmente.

for se puede interrumpir con break tambien.

for i in 5..9:
  echo i
  if i == 7: 
    break
Enter fullscreen mode Exit fullscreen mode

Otro ejemplo

for item in [1, 2, 3, 4, 5, 6]:
  if item mod 2 == 0:
    echo "item es par"
  else:
    echo "item es impar"
Enter fullscreen mode Exit fullscreen mode

Bucle While

El bucle while es similar al for,
pero sirve para repetir un bloque de codigo,
siempre y cuando un argumento de condicion booleana sea verdadera.

while se puede interrumpir con break tambien.

var z = 0
while z < 9:
  echo z
  inc z
Enter fullscreen mode Exit fullscreen mode

Leer y Escribir archivos

readFile sirve para leer archivos.

writeFile sirve para escribir archivos.

writeFile("/tmp/ejemplo.txt", "Los datos van aca.")
var contenido = readFile("/tmp/ejemplo.txt")
echo contenido
Enter fullscreen mode Exit fullscreen mode

Leer y Escribir Variables de Entorno

getEnv sirve para leer Variables de Entorno.

putEnv sirve para escribir Variables de Entorno.

import os
putEnv("EXAMPLE", "value")
echo getEnv("EXAMPLE")
Enter fullscreen mode Exit fullscreen mode

Funciones

proc declara una nueva funcion,
los argumentos llevan su tipo y el tipo de retorno va al final.

proc nombre(argumento0: int, argumento1: int): int =
  argumento0 + argumento1
Enter fullscreen mode Exit fullscreen mode

Tambien se puede escribir en una linea

proc nombre(argumento0: int, argumento1: int): int = argumento0 + argumento1
Enter fullscreen mode Exit fullscreen mode

Puede no retornar ningun tipo

proc nombre(argumento0: int, argumento1: int) = 
  echo argumento0 + argumento1
Enter fullscreen mode Exit fullscreen mode

Puede no tomar ningun argumento

proc nombre(): int = 
  return 42
Enter fullscreen mode Exit fullscreen mode

Una funcion sin nombre es una funcion anonima

proc (argumento0: float): float = argumento0 + 1.0
Enter fullscreen mode Exit fullscreen mode

Mas ejemplos

proc saludar() = 
  echo "Hola Mundo"
Enter fullscreen mode Exit fullscreen mode

Funcion que retorna muchas cosas juntas

proc retornaMuchasCosas(): auto =
  result = (clave0: 9, clave1: true, clave2: "texto")
Enter fullscreen mode Exit fullscreen mode

Funcion Flecha (Arrow Functions) esta en el modulo de azucar

import importa modulos de la libreria estandard, o de terceros.

import sugar

let saludar = (argumento: int) => echo "Hola ", argumento
Enter fullscreen mode Exit fullscreen mode

Otro ejemplo, pero sin argumentos

import sugar

let saludar = () => echo "ejemplo"
Enter fullscreen mode Exit fullscreen mode

Arrow Function multi-linea

import sugar

let ejemplo = (c: int) => (
  let a = 1
  let b = 2
  a + b + c)

assert ejemplo(42) == 45
Enter fullscreen mode Exit fullscreen mode

Estructura de Programa

Para darle mas estructura puedes crear una funcion principal main,
no es obligatorio, pero es recomendado.

when es un if pero que se evalua durante la compilacion.

isMainModule es true cuando es el modulo principal que se esta ejecutando.

proc main() =
  echo "Hola Mundo"

when isMainModule:
  main()
Enter fullscreen mode Exit fullscreen mode

Programa de conversion de escalas de Temperatura

proc main(celsius: int) =
  let kelvin = celsius + 273
  let fahrenheit = float(celsius) * 1.8 + 32.0
  echo "Temperatura Celsius: ", celsius
  echo "Temperatura Fahrenheit: ", fahrenheit
  echo "Temperatura Kelvin: ", kelvin

when isMainModule:
  main(celsius = 22)
Enter fullscreen mode Exit fullscreen mode

Base64

base64 sirve para convertir a Base64.

import base64
let datos = encode("Hello World")
assert datos == "SGVsbG8gV29ybGQ="
Enter fullscreen mode Exit fullscreen mode

Abrir navegador web

browsers sirve para abrir una direccion web en el navegador web.

import browsers
openDefaultBrowser("https://nim-lang.org")
Enter fullscreen mode Exit fullscreen mode

Busqueda Binaria

algorithm contiene algoritmos comunes, como ser la Busqueda Binaria.

import algorithm
assert binarySearch([0, 1, 2, 3, 4], 4) == 4
assert binarySearch([0, 1, 2, 3, 4], 2) == 2
Enter fullscreen mode Exit fullscreen mode

JSON

json tiene todo lo necesario para manipular datos JSON.

JSON se escribe literal en el codigo,
el operador %* se encarga de "entender" el JSON.

import json

let datos = %*{
  "clave": "valor",
  "otro": 42,
  "ultimo": 2.5
}

assert datos is JsonNode
echo datos.pretty

writeFile("/tmp/ejemplo.json", datos.pretty)
echo parseFile("/tmp/ejemplo.json")
Enter fullscreen mode Exit fullscreen mode

Distancia de Levenshtein

editdistance implementa la Distancia de Levenshtein.

import std/editdistance
assert editdistance("Gatito", "Patito") == 1
Enter fullscreen mode Exit fullscreen mode

Random

random implementa generador de numeros al azar y utilidades de random.

import random
randomize()

let num = rand(99)  # Numero al azar entre 0 y 99
assert num in 0..99

let colores = ["rojo", "verde", "azul"]
let alazar = sample(colores)
assert alazar in colores
Enter fullscreen mode Exit fullscreen mode

HTTP

httpclient tiene un Cliente HTTP.

import httpclient
var cliente = newHttpClient()
echo cliente.getContent("http://nim-lang.org")
Enter fullscreen mode Exit fullscreen mode

Tipos

Puedes crear tus propios tipos usando type.

Los nombres de los tipos deben usar siempre la primer letra en mayuscula.

Este es un tipo vacio sin ningun atributo

type Nombre = object
Enter fullscreen mode Exit fullscreen mode

Este tipo tiene atributos

type Nombre = object
  atributo: string  # Atributo de tipo string
  otro: int         # Atributo de tipo int
Enter fullscreen mode Exit fullscreen mode

Tambien se puede agrupar tipos en un bloque type

type 
  TipoVacio = object

  Nombre = object
    atributo: string  # Atributo de tipo string
    otro: int         # Atributo de tipo int

  Otro = object
    foo: bool         # Atributo de tipo bool
Enter fullscreen mode Exit fullscreen mode

Orientacion a Objetos

Un tipo puede heredar de otro tipo usando object of

Todos los tipos heredan de un tipo raiz,
que es la madre de todos los tipos,
el objeto raiz es RootObj.

En este ejemplo Gatito hereda de Animal,
a su vez Animal hereda de RootObj.

type 
  Animal = ref object of RootObj

  Gatito = ref object of Animal
Enter fullscreen mode Exit fullscreen mode

Metodos en Objetos

Para tener funcionalidades en los objetos se puede darle funciones,
se le otorgan funcionalidad usando self: Objeto,
self: Objeto siempre debe ser el primer argumento.

type 
  Animal = ref object of RootObj
  Gatito = ref object of Animal

proc miau(self: Gatito) =
  echo "Miau Miau"

let gato = Gatito()
gato.miau()
Enter fullscreen mode Exit fullscreen mode

Constructores de Objeto

Para darle valores por defecto a los atributos de algun tipo se puede usar un Constructor,
un constructor es simplemente una funcion que retorna el tipo.

Por convencion usualmente se nombra al constructor como "new+tipo" o "init+tipo",
es decir para el tipo Gatito deberia ser
newGatito() o initGatito()

type 
  Animal = ref object of RootObj
  Gatito = ref object of Animal
    edad: int
    nombre: string

proc newGatito(edad: int, nombre: string): Gatito =
  Gatito(edad: edad, nombre: nombre)

proc miau(self: Gatito) =
  echo "Miau Miau"

let gato = newGatito(edad: 2, nombre: "Bastet")
assert gato.edad == 2
assert gato.nombre == "Bastet"
gato.miau()
Enter fullscreen mode Exit fullscreen mode

Volvamos a darle mas estructura de programa

type 
  Animal = ref object of RootObj
  Gatito = ref object of Animal
    edad: int
    nombre: string

proc newGatito(edad: int, nombre: string): Gatito =
  Gatito(edad: edad, nombre: nombre)

proc miau(self: Gatito) =
  echo "Miau Miau"

proc main(edad: int, nombre: string) =
  let gato = newGatito(edad: edad, nombre: nombre)
  assert gato.edad == 2
  assert gato.nombre == "Bastet"
  gato.miau()

when isMainModule:
  main(edad = 2, nombre = "Bastet")
Enter fullscreen mode Exit fullscreen mode

Colecciones

Colecciones sirven para agrupar valores dentro de un mismo contenedor.

No veremos cada una en detalle por que eso ya es parte de la libreria estandard,
pero aqui esta un resumen rapido de los contenedores:

Indexado Indice Tipos Capacidad Longitud
array Si 0 Homogeneo Estatica Estatica
set No Valor Homogeneo Dinamica Dinamica
seq Si 0 Homogeneo Dinamica Dinamica
tabla No Clave Homogeneo Dinamica Dinamica
tupla Si 0/Clave Heterogeneo Estatica Estatica
JSON No Clave Heterogeneo Dinamica Dinamica
BTrees No Clave Homogeneo Dinamica Dinamica
CritBits No Clave Homogeneo Dinamica Dinamica
  • Si necesitas una lista usa seq.
  • Si necesitas un diccionario mapeado usa table.
  • Si necesitas tipos mezclados usa JSON.
  • Si necesitas retornar muchos valores de una funcion usa tuple.

Existen mas contenedores pero esos son los mas comunes.

Existen mas contenedores en paquetes de terceros.

Un contenedor no es mas que un Tipo,
puedes crear tus propios contenedores personalizados.

Frontend

Puede correr el codigo en el navegador web,
hay modulos en la libreria estandard orientados a la web.

Los modulos que solo funcionan para JavaScript,
su nombre comienza con "js",
por ejemplo jsfetch, jsre, jsbigints, etc etc.

Tambien puede correr el codigo en NodeJS,
con paquetes de terceros.

...y en cualquier contexto que tenga un interprete de JavaScript.

Documentacion

Gracias por leer

👑

Top comments (0)