- Hurl es un lenguaje de programación experimental que construye el flujo de control solo con manejo de excepciones, en lugar de bifurcaciones o bucles comunes
- Surgió de una conversación entre Nicole Tietz-Sokolskaya y amigos de Recurse Center, y el sitio ofrece documentación de uso, ejemplos, guía de depuración y preguntas y respuestas
- Los testimonios de la página de introducción ponen deliberadamente al frente un tono de broma, con frases como “monstrosity is beautiful” y “Certified unhinged™”
- El código fuente de Hurl y del sitio está publicado, pero para enviar parches por email se requiere ceder los derechos del parche
- La licencia se ofrece a elección entre AGPL-3.0, GAL-1.0 o una licencia comercial
Un experimento de lenguaje que deja solo el manejo de excepciones
- Hurl fue creado con un solo propósito: explorar si es posible un lenguaje construido únicamente con flujo de control basado en manejo de excepciones
- La idea surgió de una conversación entre Nicole Tietz-Sokolskaya y amigos de Recurse Center, cuyas identidades no se revelan “por decoro”
- El sitio ofrece documentación de uso de Hurl, ejemplos, guía de depuración y preguntas y respuestas
Parece una broma, pero es un proyecto publicado de verdad
- La página de introducción incluye testimonios que muestran el carácter de Hurl
- “This monstrosity is beautiful, and I must never touch it”
- “Certified unhinged™!”
- “is "🤮" an available quote?”
- Si quieres incluir un testimonio adicional, debes enviarle un email a Nicole, y se requiere consentimiento explícito para incluir la cita
Código fuente y condiciones de licencia
- El código fuente del lenguaje Hurl y de este sitio está publicado en Hurl's repo
- Si encuentras bugs o errores, puedes enviar parches por email, pero debes ceder todos los derechos sobre el parche
- Es una condición para mantener la posibilidad de relicenciamiento y de licenciamiento comercial
- El proyecto puede usarse bajo una de las siguientes tres licencias
-
AGPL-3.0
- GAL-1.0: Gay Agenda License
- licencia comercial
- Durante la revisión de licencias también se consideraron joke licenses y unfortunate licenses, pero finalmente se usan las tres licencias anteriores
-
1 comentarios
Opiniones en Hacker News
Si diseñara un lenguaje de programación, haría obligatorio el uso de namespaces en include/import y, si es posible, también impediría los efectos secundarios a nivel superior.
Recibirlo como
let foo = include "lib/foo.hurl"y luego llamar afoo.init()hace que sea mucho más fácil razonar sobre el código.En cambio, si después de
include "lib/foo.hurl" // side effectsaparecebaz(buz), es difícil saber si la función y la variable vienen de la biblioteca estándar o si fueron incluidas desde algún lado.import "foo/bar"debería permitir usarfoo.*obar.*, nobazz.*. Go es justo lo que se me viene a la mente.VSCode también hace algo parecido con plugins y LSP, pero mucho peor. La navegación de código es tan lenta que no puedo trabajar con VSCode.
Me pregunto si este tipo de propuesta solo es útil cuando no existen esas herramientas. Al menos en un entorno profesional, parece imposible vivir sin ellas.
foo.init(), algo que no se puede hacer con un import “desnudo”.Eso no significa que este proyecto no tenga valor; más bien lo veo como una obra de arte.
Una vez hice un fork de Ruby para que
requireno sobrescribiera la tabla de símbolos, pero el ecosistema de Ruby parecía depender demasiado del estado global mutable compartido, así que al final perdí el interés en Ruby como tal.Las excepciones siempre me parecieron malas porque hacen difícil entender el contrato entre quien llama y quien es llamado, y además aumentan el acoplamiento del código.
Prefiero el enfoque de manejarlo con valores de retorno, como en Go o Rust. Al echarle un vistazo rápido al lenguaje, no sé bien si hay algo que resuelva este problema.
Si el IDE pudiera detectar dinámicamente todas las excepciones no capturadas de una función y permitir saltar a los lugares donde pueden lanzarse, este modelo podría estar bien. Pero no sé cómo manejaría el acoplamiento, y el grafo de flujo de control parece que se volvería extremadamente inestable.
Claro que en Java, salvo que herede de
RuntimeException, las excepciones que una función puede lanzar forman parte de la firma de la función. Si lanzas una excepción sin agregarla a la firma, no compila.Las condiciones de Java hacen mucho más fácil que el IDE reporte excepciones no capturadas, pero si no son excepciones de runtime, es un problema que se puede resolver con análisis estático.
En cambio, devolver valores envueltos estandarizados como
Ok/Errparece más simple tanto para el soporte de herramientas como para la comodidad del desarrollador.La única diferencia es que, con el enfoque de pasar excepciones, tienes que escribir a mano el código repetitivo que el compilador podría hacer por ti.
No entiendo cómo alguien con una cabeza que funcione normalmente en 2024 querría hacer eso a mano.
Durante el tiempo que lo usé, encontrar la causa raíz sin depurador fue mucho más doloroso.
El ejemplo de
tossdice que “se usa principalmente para pasar varios valores fuera de una función y no es estrictamente necesario, pero es lindo”, pero lejos de ser inútil, en realidad implementa generadores reanudables.Claro, puede volverse bastante interesante si quieres hacer algo distinto de reanudar de inmediato. Solo tienes que organizar todo el codebase como una pila interna-externa de
toss.returntiene que estar léxicamente acotado al manejador.Por ejemplo, en Python puedes llamar a
next()desde cualquier lugar.Esto se parece más a pasar un callback por un canal lateral.
tossllama a ese callback, yreturnliteralmente retorna desde ahí.En otros lenguajes sería una función realmente útil, pero aquí se trata como algo lindo y descartable; casi parece un chiste.
yielden C#?Hurl parece bastante cercano al sistema de condiciones al estilo Smalltalk o Common Lisp.
Desenrollar la pila y reanudar son solo dos de los reinicios posibles: https://gigamonkeys.com/book/beyond-exception-handling-condi...
Más allá del proyecto en sí, creo firmemente que el mundo sería un lugar mejor si más cosas usaran la extensión .wtf en sus dominios.
Esto suena como una forma débil de efectos algebraicos, pero sigue siendo genial ver lenguajes así y lo que se puede hacer con ellos.
Si los efectos algebraicos son básicamente algo como la palabra clave
tossde Hurl, me pregunto en qué sentido son más potentes quetoss.Es un experimento mental interesante.
Detesto de verdad las excepciones y quiero un lenguaje sin excepciones.
Las excepciones son el
gotode nuestra era.Teniendo
Maybe/OptionyEffect/Result, casi no hay razón para lanzar excepciones y tener que rastrear mentalmente dónde se manejan.Me preocupa un poco que los efectos algebraicos ganen más popularidad y terminen influyendo también en el ya demasiado complejo JS de frontend, porque fomentan lanzar “excepciones” para controlar el flujo.
Si todo esto es para evitar el problema de los colores async/sync, para mí no vale la pena en absoluto.
Wow, esto no me gusta. Pero, curiosamente, tiene algo casi elegante.
Es muy difícil de modelar mentalmente, pero aun así.
Hablando un poco más en serio, me gustaría que hubiera una sintaxis
catchdistinta para excepciones reanudables y no reanudables. Así desaparecería la ambigüedad sintáctica sobre sireturndevuelve el flujo de control al lado que lanzó la excepción inmediata más cercana o no.Y la biblioteca estándar no debería escaparse usando funciones normales que devuelven valores. Que te dé acidez comer tu propia comida para perros no es motivo para no comerla.
¿Entendí bien que lo que se hace con
hurlse puede capturar, pero lo que se hace contossno? Va a tomar un tiempo acostumbrarse.También me preocupa cuánto Hurl tendría que escribir antes de que la gente empiece a llamarme tosser.
Tosssuena como una construcción de lenguaje interesante. Sube por la pila buscando un manejador de excepciones y luego vuelve al punto original para reanudar la ejecución como si nada hubiera pasado.Parece que con esta construcción se podría inyectar comportamiento adicional en runtime.
Normalmente, en código orientado a objetos, la inyección de dependencias se hace mediante constructores de servicios, pero ¿
tosspermite hacerlo con “manejadores de toss”?https://koka-lang.github.io/koka/doc/book.html#why-handlers
No sé mucho, pero sí sé que permite inyectar comportamiento en runtime de esta manera.
Resume Nextde VB.