Skip to content

Aprende Nim en 5 Minutos

Juan Carlos edited this page Aug 22, 2020 · 6 revisions

(Spanish only)

Nim es un lenguaje de programación imperativo de tipado estático, que le da al programador mucho poder sin comprometer la eficiencia.

  • Nim es eficiente, expresivo y elegante.
# Los comentarios de una linea comienzan con un #
## La Documentacion comienza con un ##


#[
  Este es un comentario multi-linea.

  En Nim, los comentarios multi-linea pueden estar anidados, empezando con un #[
  ... y terminando con un ]#

]#


var                      # Declarar (y asignar) variables,
  letra: char = 'n'      # con o sin anotaciones de Tipado.
  lenguaje = "N" & "im"  # Concatenar strings con &
  nLongitud: int = len(lenguaje)
  flotante: float
  booleano: bool = false


let               # Usa let para declarar y asignar variables.
  piernas = 400   # piernas es immutable por que usa let.
  brazos = 2_000  # _ es ignorado y es útil para números largos.
  acercaDePi = 3.15


const           # Las constantes son computadas en tiempo de compilación. Esto provee
  debug = true  # rendimiento y es útil para expresiones en tiempo de compilación.
  compilarCodigoMalo = false


when compilarCodigoMalo:           # `when` es un `if` en tiempo de compilación.
  piernas = piernas + 1            # Esto es un error y no compilara.
  const entrada = readLine(stdin)  # Los valores de las const deben ser conocidos en tiempo de compilacion.


discard 1 > 2 # Nota: El compilador se quejara si el resultado de una expresión
              # no es usado. `discard` puede evitar esto.


# Estructuras de Datos ########################################################


# Tuplas
var
  chicos: tuple[nombre: string, edad: int]     # Tuplas tienen *ambos* nombres de campo
  hoy: tuple[pronostico: string, temp: float]  # *y* orden.

chicos = (nombre: "Pepe", edad: 2)  # Asignar todo de una sola vez es posible con el literal ()
hoy.pronostico = "Nublado"          # o campos individuales.
hoy.temp = 22.1


# Secuencias
var bebidas: seq[string]

bebidas = @["Agua", "Jugo", "Chocolatada"] # @[V1,..,Vn] es la secuencia literal

bebidas.add("Leche")

if "Leche" in bebidas:
  echo "Tenemos Leche y ", bebidas.len - 1, " otras bebidas."

let miBebida = bebidas[2]


# Tipos ########################################################################


# Definiendo tus propios tipos pone al compilador a trabajar por ti.
# Es lo que hace el tipado estático poderoso y útil.
type
  Nombre = string # Un alias de tipo te da un nuevo tipo que es intercambiable
  Edad = int      # con el tipo viejo original pero es mas descriptivo.
  Persona = tuple[nombre: Nombre, edad: Edad] # Puedes definir estructuras de datos también.
  OtraSintaxis = tuple
    campoUno: string
    campoDos: int

var
  juan: Persona = (nombre: "Juan", edad: 17)
  nuevaEdad = 18  # Deberia ser mejor usar Age en lugar de int.

juan.edad = nuevaEdad  # Pero igualmente funciona por que int y Age son sinonimos.

type
  Efectivo = distinct int  # `distinct` hace que un nuevo tipo sea intencionalmente incompatible con su
  Desc = distinct string   # tipo base.

var
  dinero: Efectivo = 100.Efectivo  # `.Efectivo` convierte el int a nuetro tipo Efectivo.
  descripcion: Desc = "Interesting".Desc

when compilarCodigoMalo:
  juan.edad = dinero         # Error! edad es de tipo int y dinero es Cash.
  john.nombre = descripcion  # El compilador dice: "No!"


# Mas Tipos y Estructuras de Datos ########################################################


# Enumeraciones permiten un tipo tener uno de un numero limitado de valores.
type
  Color = enum cRojo, cAzul, cVerde
  Direccion = enum # Formato alternativo de como escribir el Enum.
    dNorte
    dOeste
    dEste
    dSur

var
  orientacion = dNorte # `orientacion` es de tipo Direction, con el valor `dNorte`.
  pixel = cVerde # `pixel` es de tipo Color, con el vlor `cVerde`.

discard dNorte > dEste  # Enums son usualmente un tipo "ordinal".


# Subranges especifican un rango valido limitado.
type CarasDeUnDado = range[1..20]  # Solamente un int desde 1 hasta 20 es un valor valido.
var tirar_dado: CarasDeUnDado = 13

when compilarCodigoMalo:
  tirar_dado = 23 # Error!


# Arrays
type
  ContadorDado = array[CarasDeUnDado, int]  # Los Array tienen longitud fija y
  NombresDeDir = array[Direccion, string]   # son indexados por cualquier tipo ordinal.
  Verdades = array[42..44, bool]

var
  contador: ContadorDado
  direcciones: NombresDeDir
  posibilidades: Verdades

posibilidades = [false, false, false] # Los Array literal son creados con [V1,..,Vn]
posibilidades[42] = true

direcciones[dNorte] = "Ahh. El norte recuerda!."
direcciones[dOeste] = "No, no podes ir ahi."

tirar_dado = 13
contador[tirar_dado] += 1
contador[tirar_dado] += 1

var otroArray = ["El Indice por defecto", "comienza en", "0"]


# Mas estructuras de datos estan disponibles, incluyendo tablas, sets, listas, colas, y arboles crit-bit.
# http://nim-lang.org/docs/lib.html#collections-and-algorithms


# IO y Control de flujo ###########################################################


# case, readLine()
echo "Leiste algun libro bueno ultimamente?"

case readLine(stdin)
of "no", "No":
  echo "Ve a tu biblioteca local."
of "yes", "Yes":
  echo "Bien, sigue asi."
else:
  echo "Eso es genial; Supongo."


# while, if, continue, break
import strutils as str # http://nim-lang.org/docs/strutils.html

echo "Estoy pensando un numero entre 41 y 43. Adivina cual!."
let numero = 42

var
  adivinado_crudo: string
  adivinado: int

while adivinado != numero:
  adivinado_crudo = readLine(stdin)
  if adivinado_crudo == "": continue  # Omite esta iteración.
  adivinado = str.parseInt(adivinado_crudo)
  if adivinado == 1001:
    echo "AAAAAAGGG!"
    break
  elif adivinado > numero:
    echo "Nope. Muy grande."
  elif adivinado < numero:
    echo adivinado, " es muy chico."
  else:
    echo "Yeeeeeehaw!"


# Iteracion ########################################################


for i, elem in ["Si", "No", "Tal vez"]:  # O solamente `for elem in`.
  echo elem, " esta en el indice: ", i

for k, v in items(@[(persona: "Vos", poder: 100), (persona: "Yo", poder: 9000)]):
  echo v

let miString = """
an <example>
`string` to
play with
"""  # string multi-linea

for line in splitLines(miString):
  echo(line)

for i, c in miString:        # Indice y letra. O `for j in` para solamente la letra.
  if i mod 2 == 0: continue  # Un `if` compacto.
  elif c == 'X': break
  else: echo c


# Procedimientos #############################################################


type Respuesta = enum rSi, rNo

proc preguntar(question: string): Respuesta =
  echo question, " (s/n)"
  while true:
    case readLine(stdin)
    of "s", "S", "si", "Si":
      return Respuesta.rSi  # Los Enums pueden ser completamente calificados.
    of "n", "N", "no", "No":
      return Respuesta.rNo
    else: echo "Por favor se claro: si o no."

proc agregarAzucar(amount = 2) =  # El valor por defecto de amount es 2, No retorna nada.
  assert amount > 0 and amount < 9000, "Azucar muy loco"
  for a in 1..amount:
    echo a, " azucar..."

case preguntar("Queres azucar con tu cafe?")
of aSi:
  agregarAzucar(3)
of aNo:
  echo "Oh, por favor usa un poco!"
  agregarAzucar()
# No hay necesidad de un `else` aqui. Unicamente `yes` o `no` son los valores posibles.


# FFI #####################################################################


# Nim compila a C, por tal motivo el FFI es muy fácil:

proc strcmp(a, b: cstring): cint {.importc: "strcmp", nodecl.}

let cmp = strcmp("C?", "Facil!")

Adicionalmente, Nim se diferencia del resto por su metaprogramación, rendimiento, y características de ejecución de código en tiempo de compilación.

Clone this wiki locally