codexivo 0.2.0 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/lenguaje.md CHANGED
@@ -5,8 +5,9 @@ donde va el lenguaje está en la [especificación v1](./especificacion-v1.md); l
5
5
 
6
6
  ## Un programa
7
7
 
8
- Un programa es una lista de sentencias. El punto y coma al final de cada sentencia es opcional si la siguiente empieza en otra
9
- línea. El valor de un programa es el de su última expresión, o lo que regrese con `regresa`.
8
+ Un programa es una lista de sentencias, una por línea. El punto y coma solo hace falta para poner dos sentencias en la misma
9
+ línea (`x = 1; y = 2`); los ejemplos de esta guía no lo usan. El valor de un programa es el de su última expresión, o lo que
10
+ regrese con `regresa`.
10
11
 
11
12
  El mismo lenguaje funciona mediante la biblioteca ESM `codexivo`, el comando npm `codexivo` (sin instalar Bun) y los ejecutables
12
13
  autónomos de cada sistema. Consulta [REPL y terminal](./repl.md) para ejecutar archivos y proporcionar entrada estándar.
@@ -22,52 +23,104 @@ imprimir("Hola,", nombre)
22
23
  ## Palabras reservadas
23
24
 
24
25
  ```
25
- variable procedimiento regresa
26
- si pero_si si_no mientras hacer hasta_que para
27
- verdadero falso nulo y o no
26
+ variable constante procedimiento regresa dominio
27
+ si pero_si si_no
28
+ mientras hacer hasta_que para desde hasta con_paso para_cada en repetir veces
29
+ romper continuar
30
+ verdadero falso nulo
31
+ y o no mod div
32
+ es_igual_a es_distinto_de es_menor_que es_mayor_que
33
+ es_menor_o_igual_a es_mayor_o_igual_a
28
34
  ```
29
35
 
30
36
  ## Valores
31
37
 
32
38
  | Tipo | Ejemplos |
33
39
  | ------------- | ----------------------------------------------------------------------------- |
34
- | número | `10`, `3.14`, `.5`, `-2` |
40
+ | número | `10`, `3.14`, `.5`, `-2`, `1_000_000` (el `_` solo separa grupos de dígitos) |
35
41
  | texto | `"hola"`, `'mundo'`, `"línea\nnueva"` (escapes: `\n`, `\t`, `\\`, `\"`, `\'`) |
36
42
  | lógico | `verdadero`, `falso` |
37
43
  | nulo | `nulo` |
38
44
  | lista | `[1, "a", verdadero]` |
45
+ | diccionario | `{ "nombre": "Ana", "edad": 16 }` |
39
46
  | procedimiento | `procedimiento(x) { regresa x * 2; }` |
40
47
 
41
- Las listas se comparten: si dos variables apuntan a la misma lista, un cambio se ve desde las dos.
48
+ Las listas y los diccionarios se comparten: si dos variables apuntan a la misma lista, un cambio se ve desde las dos.
42
49
 
43
50
  ## Variables
44
51
 
45
52
  ```codexivo
46
- variable contador = 0;
47
- contador = contador + 1;
48
- contador += 5; // también -=, *=, /=
53
+ variable contador = 0
54
+ contador = contador + 1
55
+
56
+ constante LADOS = 4
57
+ imprimir(LADOS * contador)
49
58
  ```
50
59
 
51
60
  - Toda variable se declara una vez con `variable` y un valor inicial.
61
+ - `=` **no** es una igualdad: guarda en la variable de la izquierda el valor de la derecha. `contador = contador + 1` se lee
62
+ «calcula `contador + 1` y guarda el resultado en `contador`». En el sandbox se ve el valor entrando en la variable.
52
63
  - Asignar a una variable sin declararla es un error.
64
+ - Una `constante` no se puede cambiar: reasignarla es un error.
53
65
  - Lo que se declara dentro de un bloque `{ }` solo existe dentro de él.
54
66
 
55
67
  Los nombres pueden llevar `ñ`, acentos y diéresis: `año`, `canción`, `pingüino`.
56
68
 
69
+ ### Atajos
70
+
71
+ Cuando ya se entiende la asignación, hay formas cortas para los cambios más comunes:
72
+
73
+ ```codexivo
74
+ variable total = 10
75
+ total += 5 // lo mismo que total = total + 5; también -=, *=, /=, %=
76
+ total++ // suma 1
77
+ total-- // resta 1
78
+ ```
79
+
80
+ `++` y `--` son sentencias, no expresiones: `x = i++` es un error. Se escribe `i++` en su propia línea.
81
+
57
82
  ## Operadores
58
83
 
59
84
  De menor a mayor precedencia:
60
85
 
61
- | Operadores | Notas |
62
- | ----------------------------------- | ------------------------------------------------------------------------ |
63
- | `o` | Cortocircuito |
64
- | `y` | Cortocircuito |
65
- | `no`, `!` | |
66
- | `==` `!=` `<` `>` `<=` `>=` | No se pueden encadenar: `1 < x < 5` es un error; escribe `1 < x y x < 5` |
67
- | `+` `-` | `+` también une dos textos |
68
- | `*` `/` | `/` es división real; dividir entre cero es un error |
69
- | `-` (signo) | |
70
- | llamadas `f(x)`, índices `lista[i]` | |
86
+ | Operadores | Notas |
87
+ | ---------------------------------------------------- | ------------------------------------------------------------------------ |
88
+ | `o` | Cortocircuito |
89
+ | `y` | Cortocircuito |
90
+ | `no`, `!` | |
91
+ | `==` `!=` `<` `>` `<=` `>=` y sus formas en palabras | No se pueden encadenar: `1 < x < 5` es un error; escribe `1 < x y x < 5` |
92
+ | `+` `-` | `+` también une dos textos |
93
+ | `*` `/` `div` `mod` (`%`) | Dividir entre cero (con `/`, `div` o `mod`) es un error |
94
+ | `-` (signo) | |
95
+ | `^` | Potencia, asociativa a la derecha: `2 ^ 3 ^ 2` es `2 ^ 9` |
96
+ | llamadas `f(x)`, índices `lista[i]` | |
97
+
98
+ ```codexivo
99
+ 7 / 2 // 3.5, división real
100
+ 7 div 2 // 3, división entera hacia abajo
101
+ -7 div 2 // -4
102
+ 7 mod 3 // 1, el residuo (también 7 % 3)
103
+ -7 mod 3 // 2: siempre se cumple a == (a div b) * b + (a mod b)
104
+ -2 ^ 2 // -4, como en matemáticas: la potencia va antes que el signo
105
+ ```
106
+
107
+ Cada comparación tiene una forma en palabras que significa exactamente lo mismo:
108
+
109
+ | Símbolo | Palabra |
110
+ | ------- | -------------------- |
111
+ | `==` | `es_igual_a` |
112
+ | `!=` | `es_distinto_de` |
113
+ | `<` | `es_menor_que` |
114
+ | `>` | `es_mayor_que` |
115
+ | `<=` | `es_menor_o_igual_a` |
116
+ | `>=` | `es_mayor_o_igual_a` |
117
+
118
+ ```codexivo
119
+ variable edad = 16
120
+ si (edad es_mayor_o_igual_a 13 y edad es_menor_que 18) {
121
+ imprimir("adolescente")
122
+ }
123
+ ```
71
124
 
72
125
  - `==` compara por valor, también listas: `[1, 2] == [1, 2]` es `verdadero`.
73
126
  - `+` no mezcla textos y números: `"Total: " + 5` es un error. Usa `texto(5)` o `imprimir("Total:", 5)`.
@@ -76,76 +129,360 @@ De menor a mayor precedencia:
76
129
  ## Condiciones y bucles
77
130
 
78
131
  ```codexivo
79
- variable edad = 15;
80
- si (edad >= 18) {
81
- imprimir("adulto");
82
- } pero_si (edad >= 13) {
83
- imprimir("adolescente");
132
+ variable edad = 15
133
+ si (edad es_mayor_o_igual_a 18) {
134
+ imprimir("adulto")
135
+ } pero_si (edad es_mayor_o_igual_a 13) {
136
+ imprimir("adolescente")
84
137
  } si_no {
85
- imprimir("niño");
138
+ imprimir("niño")
139
+ }
140
+ ```
141
+
142
+ Hay una forma de bucle para cada intención:
143
+
144
+ | Para… | Se escribe |
145
+ | --------------------------------------- | --------------------------------- |
146
+ | Repetir algo n veces | `repetir n veces { }` |
147
+ | Contar | `para i desde a hasta b { }` |
148
+ | Repetir mientras se cumpla algo | `mientras (condición) { }` |
149
+ | Repetir hasta que se cumpla algo | `hacer { } hasta_que (condición)` |
150
+ | Recorrer una lista, texto o diccionario | `para_cada x en colección { }` |
151
+
152
+ ```codexivo
153
+ repetir 3 veces {
154
+ imprimir("¡hola!")
155
+ }
156
+
157
+ variable suma = 0
158
+ para i desde 1 hasta 10 {
159
+ suma = suma + i
160
+ }
161
+ imprimir("La suma es", suma)
162
+
163
+ para i desde 10 hasta 0 con_paso -2 {
164
+ imprimir(i)
86
165
  }
87
166
 
88
- variable i = 0;
89
- mientras (i < 3) {
90
- i += 1;
167
+ variable intentos = 0
168
+ mientras (intentos es_menor_que 3) {
169
+ intentos = intentos + 1
91
170
  }
92
171
 
93
172
  hacer {
94
- i -= 1;
95
- } hasta_que (i == 0);
173
+ intentos = intentos - 1
174
+ } hasta_que (intentos es_igual_a 0)
96
175
 
97
- para (variable j = 0; j < 3; j += 1) {
98
- imprimir(j);
176
+ para_cada fruta en ["mango", "piña"] {
177
+ imprimir(fruta)
178
+ }
179
+
180
+ para n desde 1 hasta 10 {
181
+ si (n mod 2 es_igual_a 0) {
182
+ continuar // salta a la siguiente vuelta
183
+ }
184
+ si (n es_mayor_que 7) {
185
+ romper // sale del bucle
186
+ }
187
+ imprimir(n)
99
188
  }
100
189
  ```
101
190
 
191
+ - `para i desde a hasta b` incluye los dos extremos. El paso es 1 si no se escribe `con_paso`.
192
+ - `i` se crea sola, sin `variable`, es nueva en cada vuelta y solo existe dentro del cuerpo. Avanza sola: cambiarla
193
+ dentro del bucle es un error.
194
+ - `desde`, `hasta` y `con_paso` se calculan **una vez**, al empezar. Si después cambia la variable que se usó en
195
+ `hasta`, el bucle no se entera.
196
+ - Para contar hacia atrás hay que decirlo: `para i desde 10 hasta 1` es un error; se escribe `con_paso -1`. Un paso 0
197
+ también es un error.
198
+ - `repetir n veces` evalúa `n` una sola vez, al empezar. Tiene que ser un número entero, 0 o más; con 0 el bloque no se
199
+ ejecuta. Lleva la cuenta por dentro, sin crear ninguna variable.
102
200
  - `hacer … hasta_que` ejecuta el bloque al menos una vez y repite **hasta que** la condición sea verdadera.
103
- - La variable de un `para` solo existe dentro del bucle.
201
+ - `para_cada x en …` recorre una lista, un texto o un diccionario. `x` es nueva en cada vuelta y solo existe dentro del
202
+ cuerpo. Cambiar elementos de la lista mientras se recorre está bien; agregar o quitar elementos es un error.
203
+ - `romper` sale del bucle más cercano y `continuar` salta a su siguiente vuelta. Fuera de un bucle son un error, también
204
+ dentro de un procedimiento que se llama desde un bucle.
104
205
 
105
206
  ## Procedimientos
106
207
 
107
208
  ```codexivo
209
+ procedimiento área(base, altura) {
210
+ regresa base * altura
211
+ }
212
+ área(3, 4)
213
+
214
+ // también como valor, guardado en una variable
108
215
  variable saludar = procedimiento(nombre) {
109
- regresa "Hola, " + nombre;
110
- };
111
- saludar("Uriel");
216
+ regresa "Hola, " + nombre
217
+ }
218
+ saludar("Uriel")
112
219
  ```
113
220
 
114
- - Se crean con `procedimiento(parámetros) { … }` y se guardan en variables.
221
+ - Un procedimiento con nombre existe desde el inicio de su bloque: se puede llamar antes de la línea donde se declara, y
222
+ dos procedimientos pueden llamarse entre sí. Su nombre no se puede repetir en el mismo bloque.
115
223
  - Hay que llamarlos con exactamente tantos valores como parámetros.
116
224
  - Sin `regresa`, un procedimiento regresa `nulo`.
117
225
  - Recuerdan las variables de donde se crearon (closures) y pueden llamarse a sí mismos.
118
226
 
119
- Los procedimientos con nombre (`procedimiento saludar(nombre) { … }`) llegarán con la v1.
120
-
121
227
  ## Listas y textos
122
228
 
123
229
  ```codexivo
124
- variable números = [10, 20, 30];
125
- números[0]; // 10
126
- números[-1]; // 30, desde el final
127
- "hola"[1]; // "o"
230
+ variable números = [10, 20, 30]
231
+ números[0] // 10
232
+ números[-1] // 30, desde el final
233
+ "hola"[1] // "o"
234
+
235
+ números[0] = 15
236
+ números[-1] += 1
237
+ números[1]++
238
+
239
+ variable matriz = [[1, 2], [3, 4]]
240
+ matriz[1][0] = 9
241
+ ```
242
+
243
+ - Los índices son enteros desde 0; un índice fuera de rango es un error que dice cuántos elementos hay.
244
+ - Los textos no se pueden cambiar letra por letra: `t[0] = "H"` es un error. Se construye un texto nuevo.
245
+
246
+ ## Diccionarios
247
+
248
+ ```codexivo
249
+ variable persona = { "nombre": "Ana", "edad": 16 }
250
+ persona["nombre"] // "Ana"
251
+ persona.edad // 16, lo mismo que persona["edad"]
252
+ persona.ciudad = "León" // agrega la clave
253
+ persona.edad += 1
254
+
255
+ para_cada clave, valor en persona {
256
+ imprimir(clave, valor)
257
+ }
258
+
259
+ si (tiene(persona, "correo")) {
260
+ imprimir(persona.correo)
261
+ }
262
+
263
+ variable calculadora = {
264
+ "suma": procedimiento(a, b) { regresa a + b; },
265
+ }
266
+ calculadora.suma(1, 3) // 4
128
267
  ```
129
268
 
130
- Los índices son enteros desde 0; un índice fuera de rango es un error que dice cuántos elementos hay.
269
+ - Las claves son textos o números (`1` y `"1"` son claves distintas) y van entre comillas: `{ nombre: "Ana" }` es un
270
+ error. Para usar el valor de una variable como clave, escríbela entre paréntesis: `{ (clave): 1 }`.
271
+ - `d.campo` funciona con claves que son nombres válidos; para las demás, `d["clave con espacios"]`.
272
+ - Leer una clave que no existe es un error; pregunta antes con `tiene(d, clave)`.
273
+ - Se recorren en el orden en que se agregaron las claves: `para_cada clave en d` da solo las claves y
274
+ `para_cada clave, valor en d`, las dos. Agregar o quitar claves mientras se recorre es un error.
275
+ - `==` compara por valor sin importar el orden: `{ "a": 1, "b": 2 } == { "b": 2, "a": 1 }` es `verdadero`.
276
+ - Al inicio de una sentencia, `{` abre un bloque; en cualquier otra posición, un diccionario.
277
+
278
+ ## Dominios
279
+
280
+ Un `dominio` es un espacio de nombres: agrupa procedimientos, variables y constantes bajo un nombre, y desde fuera se usan
281
+ con `.`. No es un módulo ni hay que importarlo: se declara en el mismo programa.
282
+
283
+ ```codexivo
284
+ dominio calculadora {
285
+ constante PRECISIÓN = 2
286
+ variable operaciones = 0
287
+
288
+ procedimiento suma(a, b) {
289
+ operaciones++
290
+ regresa redondear(a + b, PRECISIÓN)
291
+ }
292
+
293
+ procedimiento promedio(a, b) {
294
+ regresa suma(a, b) / 2 // dentro del dominio, sin prefijo
295
+ }
296
+ }
297
+
298
+ calculadora.suma(1, 3) // 4
299
+ calculadora.promedio(2, 3) // 2.5
300
+ calculadora.operaciones // 2
301
+
302
+ dominio geometría {
303
+ dominio círculo {
304
+ procedimiento área(r) {
305
+ regresa PI * r ^ 2
306
+ }
307
+ }
308
+ }
309
+ geometría.círculo.área(1)
310
+ ```
311
+
312
+ - Dentro de un dominio solo van declaraciones: `variable`, `constante`, `procedimiento` y otros `dominio`. Un `si` o un
313
+ `imprimir` van dentro de un procedimiento del dominio o fuera de él.
314
+ - Dentro, los miembros se usan sin prefijo y ven lo que está fuera del dominio. Fuera, se usan con `.`:
315
+ `calculadora.suma`. Sin el prefijo no existen.
316
+ - Desde fuera solo se pueden cambiar los miembros declarados con `variable` (`calculadora.operaciones = 0`). Las
317
+ constantes, los procedimientos y los dominios que contiene quedan fijos, y no se pueden agregar miembros nuevos.
318
+ - El nombre del dominio no se puede reasignar. `tipo(calculadora)` es `"dominio"`.
319
+
320
+ ## Procedimientos como valores
321
+
322
+ Un procedimiento es un valor como cualquier otro: se guarda en variables, en listas y diccionarios, y se le pasa a otros
323
+ procedimientos. La biblioteca trae varios que reciben uno:
324
+
325
+ ```codexivo
326
+ variable números = [3, 8, 1, 6]
327
+ procedimiento es_par(n) {
328
+ regresa n mod 2 == 0
329
+ }
330
+
331
+ mapear(números, procedimiento(n) { regresa n * 10; }) // [30, 80, 10, 60]
332
+ filtrar(números, es_par) // [8, 6]
333
+ reducir(números, procedimiento(total, n) { regresa total + n; }, 0) // 18
334
+ alguno(números, es_par) // verdadero
335
+ todos(números, es_par) // falso
336
+ buscar(números, procedimiento(n) { regresa n > 5; }) // 8
337
+ ordenar(números, procedimiento(a, b) { regresa a > b; }) // [8, 6, 3, 1]
338
+ ```
339
+
340
+ | Procedimiento | Qué hace |
341
+ | ---------------------------- | --------------------------------------------------------------------------------------- |
342
+ | `mapear(lista, f)` | Lista nueva con `f(x)` de cada elemento |
343
+ | `filtrar(lista, f)` | Lista nueva con los elementos para los que `f(x)` es `verdadero` |
344
+ | `reducir(lista, f, inicial)` | Junta todo en un valor: empieza con `inicial` y en cada elemento hace `f(acumulado, x)` |
345
+ | `alguno(lista, f)` | `verdadero` si `f(x)` es `verdadero` para al menos un elemento |
346
+ | `todos(lista, f)` | `verdadero` si `f(x)` es `verdadero` para todos |
347
+ | `buscar(lista, f)` | El primer elemento con `f(x)` `verdadero`, o `nulo` |
348
+ | `ordenar(lista, va_antes)` | Lista nueva ordenada; `va_antes(a, b)` responde «¿va `a` antes que `b`?» |
349
+
350
+ - `f` de `filtrar`, `alguno`, `todos` y `buscar`, y el comparador de `ordenar`, tienen que regresar `verdadero` o `falso`.
351
+ - `ordenar` es estable: los elementos que el comparador no distingue conservan su orden.
352
+ - Un error dentro de `f` dice dónde está y desde dónde se llamó: `programa > mapear > f`.
353
+
354
+ ## Pilas y colas
355
+
356
+ Son listas con un vocabulario propio, para que el algoritmo se lea como se explica:
357
+
358
+ | Pila | Cola | Qué hace |
359
+ | -------------- | --------------- | -------------------------------------- |
360
+ | `apilar(p, x)` | `encolar(c, x)` | Agrega al final |
361
+ | `desapilar(p)` | `desencolar(c)` | Quita y regresa el último / el primero |
362
+ | `tope(p)` | `frente(c)` | Regresa, sin quitarlo, el que saldría |
363
+
364
+ ```codexivo
365
+ variable pendientes = []
366
+ encolar(pendientes, "lavar")
367
+ encolar(pendientes, "secar")
368
+ imprimir(desencolar(pendientes), frente(pendientes))
369
+
370
+ variable pila = []
371
+ apilar(pila, 1)
372
+ apilar(pila, 2)
373
+ imprimir(desapilar(pila), tope(pila))
374
+ ```
375
+
376
+ Sacar de una pila o cola vacía es un error: _"No se puede `desencolar` de una cola vacía."_
131
377
 
132
378
  ## Biblioteca
133
379
 
134
- Los nombres con acento también se aceptan sin él (`máximo` o `maximo`).
135
-
136
- | Procedimiento | Qué hace |
137
- | --------------------------------- | -------------------------------------------------------------------------- |
138
- | `imprimir(a, b, …)` | Escribe los valores separados por un espacio y termina la línea |
139
- | `leer()` | Siguiente línea de entrada como texto, o `nulo` si ya no hay |
140
- | `leer_número()` | Siguiente línea de entrada como número |
141
- | `tipo(x)` | `"número"`, `"texto"`, `"lógico"`, `"nulo"`, `"lista"` o `"procedimiento"` |
142
- | `texto(x)`, `número(x)` | Conversiones explícitas |
143
- | `longitud(x)` | Caracteres de un texto o elementos de una lista |
144
- | `absoluto(x)` | Valor absoluto |
145
- | `máximo(…)`, `mínimo(…)` | De varios números o de una lista |
146
- | `redondear(x, decimales?)` | Redondea; los `.5` se alejan del cero |
147
- | `agregar(lista, x)` | Agrega al final (cambia la lista) |
148
- | `primero(lista)`, `último(lista)` | Primer y último elemento |
380
+ Todo está disponible sin importar nada. Los nombres con acento también se aceptan sin él (`máximo` o `maximo`).
381
+
382
+ ### Entrada, salida y tipos
383
+
384
+ | Procedimiento | Qué hace |
385
+ | ----------------------- | -------------------------------------------------------------------------------------------------------- |
386
+ | `imprimir(a, b, …)` | Escribe los valores separados por un espacio y termina la línea |
387
+ | `leer()` | Siguiente línea de entrada como texto, o `nulo` si ya no hay |
388
+ | `leer_número()` | Siguiente línea de entrada como número |
389
+ | `tipo(x)` | `"número"`, `"texto"`, `"lógico"`, `"nulo"`, `"lista"`, `"diccionario"`, `"dominio"` o `"procedimiento"` |
390
+ | `texto(x)`, `número(x)` | Conversiones explícitas |
391
+ | `longitud(x)` | Caracteres de un texto, elementos de una lista o claves de un diccionario |
392
+
393
+ ### Matemáticas
394
+
395
+ | Procedimiento | Qué hace |
396
+ | -------------------------- | ---------------------------------------------------------------------- |
397
+ | `absoluto(x)` | Valor absoluto |
398
+ | `máximo(…)`, `mínimo(…)` | De varios números o de una lista |
399
+ | `redondear(x, decimales?)` | Redondea; los `.5` se alejan del cero |
400
+ | `piso(x)`, `techo(x)` | Redondea hacia abajo o hacia arriba: `piso(-2.1)` es `-3` |
401
+ | `entero(x)` | Quita los decimales: `entero(-2.7)` es `-2` |
402
+ | `raíz(x)` | Raíz cuadrada; de un número negativo es un error |
403
+ | `aleatorio(a, b)` | Un entero al azar entre `a` y `b`, los dos incluidos |
404
+ | `PI` | La constante 3.14159…; una variable tuya con el mismo nombre la oculta |
405
+
406
+ `aleatorio` usa una semilla por ejecución: con la misma semilla, el programa da exactamente los mismos números. `run`
407
+ regresa la semilla que usó en `seed`, y se puede fijar con la opción `seed`.
408
+
409
+ ```codexivo
410
+ variable dado = aleatorio(1, 6)
411
+ imprimir("Salió", dado)
412
+ imprimir(piso(7 / 2), techo(7 / 2), raíz(16))
413
+ ```
414
+
415
+ ### Texto
416
+
417
+ Ninguno cambia el texto original (los textos no cambian nunca): todos regresan un valor nuevo.
418
+
419
+ | Procedimiento | Qué hace |
420
+ | ------------------------------------------------ | --------------------------------------------------------------------------------------- |
421
+ | `mayúsculas(t)`, `minúsculas(t)` | El mismo texto en mayúsculas o en minúsculas |
422
+ | `recortar(t)` | Sin espacios ni saltos de línea al principio y al final |
423
+ | `dividir(t, separador)` | Lista con los pedazos de `t` entre cada separador |
424
+ | `unir(lista, separador)` | Un texto con los elementos de la lista separados por `separador` |
425
+ | `reemplazar(t, buscar, poner)` | Cambia cada aparición de `buscar` por `poner` |
426
+ | `contiene(t, parte)` | `verdadero` si `parte` aparece en `t` |
427
+ | `empieza_con(t, parte)`, `termina_con(t, parte)` | Si `t` empieza o termina con `parte` |
428
+ | `posición_de(t, parte)` | Dónde empieza la primera aparición de `parte`, o `-1` si no está |
429
+ | `subtexto(t, inicio, fin)` | Los caracteres de `inicio` hasta **antes** de `fin`: `subtexto("hola", 1, 3)` es `"ol"` |
430
+ | `caracteres(t)` | Lista con cada carácter |
431
+ | `invertir(t)` | El texto al revés |
432
+ | `código_de(c)`, `carácter_de(n)` | El código Unicode de un carácter, y el carácter de un código |
433
+
434
+ ```codexivo
435
+ variable frase = " El sol sale "
436
+ variable palabras = dividir(recortar(frase), " ")
437
+ imprimir(unir(palabras, "-"))
438
+ imprimir(mayúsculas(palabras[1]), contiene(frase, "sol"), posición_de(frase, "sale"))
439
+ ```
440
+
441
+ ### Listas
442
+
443
+ Regla: **`agregar`, `insertar`, `quitar` (y sus variantes) y `vaciar` cambian la lista; todo lo demás regresa un valor
444
+ nuevo.** Los índices siguen la misma convención que `[ ]`: desde 0, y los negativos cuentan desde el final.
445
+
446
+ | Procedimiento | Qué hace |
447
+ | ----------------------------------------------- | ------------------------------------------------------------------------------ |
448
+ | `agregar(lista, x)` | Agrega al final |
449
+ | `insertar(lista, i, x)` | Pone `x` en la posición `i` y recorre los demás |
450
+ | `quitar(lista, i)` | Quita el elemento en la posición `i` y lo regresa |
451
+ | `quitar_último(lista)`, `quitar_primero(lista)` | Quitan el último o el primero y lo regresan |
452
+ | `vaciar(lista)` | Quita todos los elementos (también sirve con un diccionario) |
453
+ | `primero(lista)`, `último(lista)` | Primer y último elemento |
454
+ | `contiene(lista, x)`, `posición_de(lista, x)` | Si `x` está (comparando por valor) y en qué posición, o `-1` |
455
+ | `rango(a, b, paso?)` | Lista de `a` a `b`, **incluyendo** `b`; con `paso` negativo cuenta hacia abajo |
456
+ | `índices(lista)` | Las posiciones válidas: `rango(0, longitud(lista) - 1)` |
457
+ | `rebanar(lista, inicio, fin)` | Los elementos de `inicio` hasta **antes** de `fin` |
458
+ | `invertir(lista)`, `copiar(lista)` | Una lista nueva al revés, o igual |
459
+ | `ordenar(lista)` | Una lista nueva ordenada; todos números o todos textos |
460
+ | `sumar(lista)` | La suma de sus números |
461
+ | `lista_de(n, valor)` | Lista con `n` copias de `valor` |
462
+ | `matriz(filas, columnas, valor)` | Lista de filas, cada una con `columnas` copias de `valor` |
463
+
464
+ `lista_de` y `matriz` copian el valor en cada casilla, así cambiar una no cambia las demás:
465
+
466
+ ```codexivo
467
+ variable tablero = matriz(3, 3, ".")
468
+ tablero[1][1] = "X"
469
+ para_cada fila en tablero {
470
+ imprimir(unir(fila, " "))
471
+ }
472
+
473
+ variable números = [5, 3, 8]
474
+ insertar(números, 0, 1)
475
+ imprimir(ordenar(números), sumar(números), quitar_último(números), números)
476
+ ```
477
+
478
+ ### Diccionarios
479
+
480
+ | Procedimiento | Qué hace |
481
+ | ------------------------- | ----------------------------------------------------------------- |
482
+ | `claves(d)`, `valores(d)` | Listas nuevas con las claves o los valores, en orden de inserción |
483
+ | `tiene(d, clave)` | `verdadero` si el diccionario tiene esa clave |
484
+ | `quitar(d, clave)` | Quita la clave y regresa su valor (cambia el diccionario) |
485
+ | `copiar(d)` | Un diccionario nuevo con las mismas claves y valores |
149
486
 
150
487
  ## Errores
151
488
 
@@ -156,7 +493,45 @@ Error de ejecución en la línea 2, columna 5: No se puede dividir entre cero.
156
493
  Pista: Revisa que el divisor no valga 0 antes de dividir.
157
494
  ```
158
495
 
496
+ ## Puente hacia otros lenguajes
497
+
498
+ Muchos lenguajes (C, Java, JavaScript) cuentan con un `for` de tres partes. Codexivo también lo tiene, para practicar antes de
499
+ pasar a ellos:
500
+
501
+ ```codexivo
502
+ para (variable i = 1; i <= 10; i += 1) {
503
+ imprimir(i)
504
+ }
505
+ ```
506
+
507
+ Es el mismo bucle que `para i desde 1 hasta 10`, escrito a mano:
508
+
509
+ | Parte | Qué hace | En `para … desde … hasta` |
510
+ | ---------------- | ---------------------------------------------------- | ------------------------- |
511
+ | `variable i = 1` | Se ejecuta una vez, al empezar | `desde 1` |
512
+ | `i <= 10` | Se revisa antes de cada vuelta; si es falsa, termina | `hasta 10` |
513
+ | `i += 1` | Se ejecuta al final de cada vuelta | `con_paso 1` |
514
+
515
+ La diferencia es que aquí todo es explícito y modificable: la condición se vuelve a evaluar en cada vuelta y la variable se
516
+ puede cambiar dentro del cuerpo. Cualquiera de las tres partes puede faltar (`para (; condición;)`). La variable solo existe
517
+ dentro del bucle.
518
+
159
519
  ## Límites
160
520
 
161
521
  Para que un error nunca congele la página, la ejecución se detiene con un error de límite al superar 10 000 000 de
162
522
  operaciones, 10 000 llamadas anidadas o 1 000 000 de caracteres impresos. Los tres se pueden configurar.
523
+
524
+ ## Operaciones
525
+
526
+ Cada operación básica (leer una variable, poner un valor, sumar, comparar, asignar, decidir, llamar) cuesta 1. Los
527
+ procedimientos de la biblioteca cuestan según el trabajo que hacen, con `n` el tamaño de su primer argumento:
528
+
529
+ | Costo | Procedimientos |
530
+ | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
531
+ | `n · ⌈log₂ n⌉` | `ordenar` |
532
+ | `n` | `contiene`, `posición_de`, `copiar`, `invertir`, `sumar`, `insertar`, `quitar`, `quitar_primero`, `desencolar`, `claves`, `valores`, `índices`, `máximo`, `mínimo`, `mapear`, `filtrar`, `reducir`, `alguno`, `todos`, `buscar`, y los de texto que recorren el texto |
533
+ | lo que crean | `rango`, `rebanar`, `subtexto`, `lista_de`, `matriz` |
534
+ | 1 | todos los demás |
535
+
536
+ Lo que hace el procedimiento que recibe `mapear` (y los demás) se cuenta aparte, como cualquier código. El mismo programa con
537
+ la misma entrada siempre da el mismo número de operaciones, y los retos lo usan en lugar del tiempo.