Skip to content
Ridgun
English

Ridgun

The language itself: a compiler that compiles itself, the stable project tool, the specification and the book

00-por-que-necesito-ridgun.md133 lines · 8.2 KBRaw
1# Capítulo 00: ¿Por qué necesito Ridgun? ¿Ah, sí? No lo sabía... ¡Cuéntame más!
2
3Seamos sinceros: cuando alguien te dice *"hemos creado un nuevo lenguaje de programación"*, tu primera reacción natural —y muy sana— es arquear una ceja y pensar:
4
5> *"¿Otro más? Pero si ya tengo Python para ir rápido, Rust o C para cuando necesito velocidad, y Bash para pegar cosas en la terminal. ¿Para qué demonios necesito yo aprender Ridgun?"*
6
7Es una pregunta excelente. Y la respuesta corta es: **porque te has acostumbrado a sufrir tres dolores diarios pensando que eran inevitables**.
8
9Vamos a ponerles nombre.
10
11---
12
13## Dolor n.º 1: "El síndrome de los dos mundos" (Prototipar en uno, reescribir en otro)
14
15Seguro que has vivido esta película:
16
171. Empiezas una herramienta o un motor de cálculo en **Python**, **JavaScript** o **Ruby** porque quieres pensar en el problema, no en punteros ni en el compilador.
182. El código queda corto y bonito... pero cuando le pasas un archivo de 500 MB o intentas usar los 16 núcleos de tu máquina, se arrastra. Y si quieres distribuir tu programa a un servidor limpio, tienes que empaquetar medio gigabyte de entorno virtual, intérprete y librerías dinámicas.
193. Resignado, decides reescribirlo en **C**, **C++** o **Rust**. Ahora vuela y ocupa unos pocos cientos de kilobytes, pero tu código de 40 líneas se ha convertido en 300 líneas llenas de `unwrap()`, `&mut`, `'a`, `Arc<Mutex<...>>`, llaves `{}` y puntos y coma `;`.
20
21**¿Qué cambia con Ridgun?**
22En Ridgun escribes código **más corto y limpio que en Python**, pero cuando ejecutas `ridgunc build`, obtienes **un único binario nativo ELF de ~350 KB** sin intérprete, sin máquina virtual externa y sin recolector de basura. No hay fase de *"luego lo reescribimos en el lenguaje rápido"*: el código limpio donde piensas el problema **ya es** el binario nativo de producción.
23
24---
25
26## Dolor n.º 2: "Leer código ajeno (o el tuyo de hace 6 meses) es jugar a ser detective"
27
28Mira cómo escribimos lógica condicional en casi todos los lenguajes mainstream:
29
30```text
31if (estado == ACTIVO && (rol == ADMIN || (rol == EDITOR && tienePermiso))) {
32 if (cuota > 0) {
33 return procesar(usuario);
34 } else {
35 return denegar("Sin cuota");
36 }
37} else {
38 return denegar("No autorizado");
39}
40```
41
42Nuestros ojos no evolucionaron para emparejar llaves anidadas ni para desentrañar árboles de `if / else` escalonados. Cuando los ingenieros, matemáticos o físicos quieren entender reglas complejas sin equivocarse, no escriben párrafos de `if / else`: **dibujan una tabla**.
43
44En Ridgun, **el código es esa tabla**:
45
46```ridgun
47autorizar String String Bool Int => String
48autorizar "activo" "admin" _ cuota =
49 | cuota > 0 = "Procesando petición"
50 | otherwise = "Denegado: sin cuota"
51autorizar "activo" "editor" True cuota =
52 | cuota > 0 = "Procesando petición"
53 | otherwise = "Denegado: sin cuota"
54autorizar _ _ _ _ = "Denegado: no autorizado"
55```
56
57Mira las columnas:
58- Columna 1: el estado (`"activo"` o `_`).
59- Columna 2: el rol (`"admin"`, `"editor"` o `_`).
60- Columna 3: si tiene permiso (`True` o `_`).
61- Columna 4: la `cuota`.
62
63No tienes que ejecutar mentalmente el programa línea por línea para saber qué pasa cuando entra un `"editor"` con permiso `False`: tus ojos bajan verticalmente por la tabla y lo ven en medio segundo.
64
65---
66
67## Dolor n.º 3: "Mi ordenador tiene 16 núcleos, pero mi programa solo usa 1 (porque me da pánico tocar hilos)"
68
69Hoy hasta el teléfono más modesto tiene 8 núcleos, y cualquier servidor o portátil de trabajo tiene entre 12 y 32. Sin embargo, el 95% de los programas cotidianos siguen ejecutándose en un solo hilo secuencial.
70
71¿Por qué? Porque en los lenguajes imperativos, paralelizar significa abrir la caja de Pandora:
72- ¿Y si dos hilos modifican el mismo diccionario a la vez? (*Data race*).
73- ¿Y si bloqueo el `Mutex` A y luego el B en un hilo, y el B y luego el A en otro? (*Deadlock*).
74- ¿Y si contamino toda mi base de código con `async` y `await` de arriba abajo?
75
76En Ridgun, **toda función es pura y todo dato es inmutable por defecto**. Eso tiene una consecuencia mágica: **dos expresiones que no dependen una de la otra jamás pueden interferir entre sí**.
77
78Por eso, en Ridgun no tienes que gestionar hilos para aprovechar tu CPU. Solo declaras **qué depende de qué** con barras paralelas `||` y flechas `->`:
79
80```ridgun
81informe mensual Datos => Informe
82informe mensual d = combinar metricas_red metricas_disco metricas_cpu
83 || analizar red d -> metricas_red
84 || analizar disco d -> metricas_disco
85 || analizar cpu d -> metricas_cpu
86```
87
88Tú solo has escrito tres líneas limpias indicando de dónde sale cada dato. El compilador ve que las tres ramas son independientes y sabe que puede lanzarlas en paralelo sin que exista ni la más mínima posibilidad de un *data race* o un *deadlock*.
89
90¿Y si necesitas agentes persistentes con buzón de mensajes y estado aislado (por ejemplo, para mantener miles de sesiones de clientes, trabajadores en segundo plano o conexiones de red)? En Ridgun no tienes que definir clases `Actor` ni usar `Mutex`: **cualquier función normal se convierte en un agente autónomo en una sola línea con `agent`**:
91
92```ridgun
93contador = agent (sumar visita) 0
94send 1 to contador
95send 5 to contador
96total = receive from contador
97stop contador
98```
99
100Además, el compilador realiza una **elección inteligente en tiempo de compilación**: analiza estáticamente la profundidad y el coste de cada función en `||`, `||map`, `||filter` y `agent` para ejecutar las funciones ligeras como pasos *green-thread* de sobrecarga cero (sin pagar el coste de calentar hilos del sistema operativo) y despachar automáticamente los cálculos pesados o recursivos a hilos reales del kernel en múltiples núcleos (`SYS_clone`).
101
102---
103
104## Dolor n.º 4: "El recolector de basura decide pausar el mundo justo en el peor momento"
105
106Los lenguajes funcionales clásicos (Haskell, OCaml, Erlang, Clojure) son maravillosos para razonar sobre el código, pero casi todos dependen de un **Recolector de Basura (*Garbage Collector*)** en tiempo de ejecución. Eso los descarta cuando necesitas:
107- Latencias predecibles al microsegundo.
108- Controlar exactamente cuánta memoria RAM puede consumir una operación antes de abortarla limpiamente.
109- Escribir utilidades del sistema operativo (`ls`, `find`, `sh`, `doas`, `make`) o tocar registros de hardware (`MMIO`).
110
111Ridgun te da **toda la elegancia del mundo funcional puro, pero con Gestión de Memoria de Ridgun (`RMM`: `RMM1` estática y `RMM2` por conteo de asignaciones en cascada) más regiones léxicas con cuota exacta (`with region`)**:
112
113```ridgun
114parsear paquete String => Result
115parsear paquete crudo =
116 with region 16_KB do
117 decodificar trama crudo
118```
119
120Cada estructura temporal es liberada de forma determinista por el compilador (`RMM1` / `RMM2`) en el instante en que deja de usarse, y si un atacante te envía un paquete malicioso diseñado para explotar la memoria, al superar el byte 16.384 la región se corta al instante, libera su arena en $O(1)$ y te devuelve `Err OutOfMemory`. Sin caídas del proceso, sin pausas de GC y sin fugas de memoria.
121
122---
123
124## En resumen: ¿Cuándo brilla Ridgun?
125
126Ridgun está hecho para ti si alguna vez has querido:
127
1281. **Escribir herramientas de sistemas, compiladores, analizadores o utilidades CLI** que arranquen en microsegundos, pesen unos pocos cientos de KB y no puedan romperse por punteros nulos ni efectos colaterales ocultos.
1292. **Construir sistemas concurrentes y servidores basados en el Modelo Nativo de Agentes (`agent`, `send ... to`, `receive from`, `stop`)**, donde cualquier función pura se convierte en un agente con o sin estado aislado y el compilador elige inteligentemente entre ejecución *green-thread* ultraligera e hilos nativos multinúcleo.
1303. **Programar algoritmos, pipelines de datos o álgebra de tensores** donde el compilador verifique por ti hasta las dimensiones de las matrices (`Tensor[M, K] * Tensor[K, N] => Tensor[M, N]`) antes de ejecutar nada.
1314. **Disfrutar leyendo tu propio código**: que cada archivo `.rg` parezca una página de un libro bien maquetado gracias al formateador tabular automático (`stable format`).
132
133¿Te pica la curiosidad? Pasa al **Capítulo 01** y escribamos nuestro primer programa en menos de dos minutos.