# Errores frecuentes al programar en DKL

Esta página reúne errores comunes al escribir programas en Devkron, con el mensaje que producen y la forma correcta. Todos los ejemplos usan datos ficticios.

## Un archivo incluido empieza en modo declarativo

Un archivo insertado con `#include` se interpreta desde el contexto **declarativo**, aunque el programa principal esté en modo imperativo. Si el archivo contiene funciones o código imperativo, debe empezar con `#!`:

```DKL
#!
module "Utilerías de ejemplo:"
{
    saludo::nombre
    {
        return "Hola, " + nombre
    }
}
```

Sin el `#!` inicial, el contenido se toma como declaraciones y las funciones no existen: al llamarlas aparece `Función: saludo no reconocida o no registrada`.

## Los dos puntos en la descripción de `module` definen un espacio de nombres

En `module "descripción:espacio.de.nombres"`, lo que sigue a `:` es el **espacio de nombres**, y se antepone al nombre de las funciones del bloque (vea [Organización y estructura del programa](Lenguaje-imperativo/Organizacion_y_estructura_del_programa.md)). Por eso un texto como `module "utilerías: lectura"` hace que la función `saludo` se llame en realidad `lectura.saludo`, y llamarla como `saludo(...)` fuera del bloque produce `Función: saludo no reconocida o no registrada`.

* Si solo quiere una descripción, no use `:` en medio del texto, o póngalo al final: `module "Utilerías de ejemplo:"`.
* Si quiere un espacio de nombres, llame a las funciones con el nombre completo: `util.saludo("Ana")` para `module "Utilerías:util"`.

## `list.add` espera un objeto

`list.add(lista, valor)` agrega una **referencia** a la lista. Con una constante numérica (`list.add(l, 5)`) no se agrega el número: en la lista queda un objeto vacío (`{}`) sin ningún error. Para agregar valores simples de forma segura, conviértalos en objeto con `from.json`:

```DKL
ref l = list.create()
do list.add(l, from.json('"33"'))
do list.add(l, from.json('33'))
do print(to.json(l))
```

Salida: `["33",33]`.

## `format` usa el formato de cadenas de C#

El segundo argumento de `format(número, formato)` es una cadena de formato numérico de .NET (C#):

| Expresión | Resultado |
|---|---|
| `format(1234.5, "0.00")` | `1234.50` |
| `format(1234.5, "#,#.#")` | `1,234.5` |

## El incremento del `for`

Si el incremento es de uno en uno, no se escribe. Si es distinto, se escribe **solo la expresión** (`a+2`), no una asignación:

```DKL
for i=0; i<3
{
    do print("i=" + str(i))
}

for a=1; a<10; a+2
{
    do print("a=" + str(a))
}
```

El segundo ciclo produce `a=1`, `a=3`, `a=5`, `a=7` y `a=9`. Con `a=a+2` como incremento el programa falla con `Operador inválido`.

## `#def` siempre lleva la lista de atributos por orden

La sintaxis es `#def identificador (atributos por orden) "valor" (atributos predeterminados)`. La lista de atributos por orden no se puede omitir:

```DKL
#include "dkli.dkh"
#def emisor (Rfc, Nombre) "cfdi:Emisor" (Rfc="XAXX010101000" Nombre="" RegimenFiscal="601")
#!
program "ejemplo def"
{
    ##
    comprobante
    {
        emisor ("EKU9003173C9", "EMPRESA DE EJEMPLO")
        emisor ("EKU9003173C9"; RegimenFiscal="612")
    }
}
```

Produce:

```XML
<comprobante><cfdi:Emisor Rfc="EKU9003173C9" Nombre="EMPRESA DE EJEMPLO" RegimenFiscal="601" /><cfdi:Emisor Rfc="EKU9003173C9" Nombre="" RegimenFiscal="612" /></comprobante>
```

Al usarlo, los valores por orden van separados por comas; después de `;` van atributos con nombre, separados por espacio, que reemplazan los valores predeterminados. `#def emisor "cfdi:Emisor" (Rfc="XAXX010101000")`, sin la lista por orden, es un error de sintaxis (`Símbolo no esperado`).

## Un nodo por línea

Escriba cada nodo hijo en su propio renglón. En los registros es obligatorio: cada miembro de `new`, `using` o `member` va en su línea.

Incorrecto (falla al ejecutarse con `Se esperaba un operador`, aunque `-parse` no marque error):

```DKL
new r
{
    @"a":1 @"b":2
}
```

Correcto:

```DKL
new r
{
    @"a":1
    @"b":2
}
```

## El número de línea de un error puede estar desfasado

El número de línea que informa un error puede no coincidir exactamente con la línea del problema: los comentarios y los bloques entre llaves pueden desplazarlo varias líneas. Revise también las líneas anteriores a la indicada.

## "Tipos no coinciden" por una función que devolvió 0

Si una función no ejecuta ningún `return`, devuelve `0`, que es el valor de retorno predeterminado. Cuando se esperaba una cadena, el error aparece después, al usar el resultado:

```DKL
nombre.cliente::id
{
    if id > 0 { return "Cliente " + str(id) }
}

do print("Nombre: " + nombre.cliente(0))
```

La última línea produce `Tipos no coinciden`. Asegúrese de que todas las rutas de la función devuelvan un valor del tipo esperado.

## Validar la sintaxis con `-parse`

`dkl archivo.dkl -parse` revisa la sintaxis sin ejecutar la parte imperativa, pero **siempre termina con código 0**, aun cuando hay errores. En un script, busque el texto `Error de sintaxis` en la salida en lugar de revisar el código de salida:

```bash
if ./dkl miprograma.dkl -parse 2>&1 | grep -q "Error de sintaxis"; then
    echo "Hay errores de sintaxis"
fi
```

`-parse` no detecta errores que solo aparecen al ejecutar (como los de las secciones anteriores sobre `new` o el `for`): pruebe también ejecutando el programa.
