3 puntos por GN⁺ 23 일 전 | 1 comentarios | Compartir por WhatsApp
  • Lenguaje pequeño que usa sintaxis estilo Rust y funciona sobre el runtime de Go, combinando las ventajas de ambos lenguajes
  • Estructura que refuerza la seguridad y expresividad con tipos de datos algebraicos, pattern matching, sistema de tipos Hindley-Milner e inmutabilidad por defecto
  • Garantiza interoperabilidad con el ecosistema de Go mediante import directo de paquetes Go, operador pipeline, bloques try y concurrencia basada en task
  • Mejora la experiencia del desarrollador y la estabilidad del código con detección de errores en tiempo de compilación, mensajes de diagnóstico claros y soporte LSP
  • Un punto clave es que el código de Lisette se transforma en código Go legible, por lo que puede integrarse naturalmente con proyectos Go existentes

Resumen de Lisette

  • Lisette es un lenguaje pequeño basado en sintaxis de Rust que compila al runtime de Go
  • Se caracteriza por tipos de datos algebraicos, pattern matching, sin nil, sistema de tipos Hindley-Milner, inmutabilidad por defecto e interoperabilidad con el ecosistema de Go
  • Puede instalarse con el comando cargo install lisette, y permite importar y usar directamente paquetes de Go como fmt, io y os

Sintaxis familiar

  • Tiene una estructura sintáctica similar a Rust
    • Soporta pattern matching mediante enum y match
    • Permite definir métodos con bloques struct e impl
  • Es un lenguaje orientado a expresiones, por lo que if, let y los bloques devuelven valores
  • Soporta encadenamiento y lambdas, lo que permite expresar de forma concisa el manejo de variables de entorno o la manipulación de cadenas
  • Soporta interfaces y genéricos, y permite escribir funciones genéricas mediante definiciones interface y restricciones T: Trait
  • Permite manejar de forma concisa el tipo Option con las sintaxis if let y let else

Seguridad

  • Detecta en tiempo de compilación errores que podrían ocurrir en el runtime de Go

    • Si no se manejan todos los patrones en una sentencia match, se genera un error
    • No se permite usar nil; los valores faltantes se representan con Option<T>
    • Se genera una advertencia si se ignora un valor de retorno Result
    • Se genera una advertencia si un tipo privado se expone en una API pública
    • Se genera un error si una variable inmutable se pasa como argumento mutable
    • Si falta un campo de una estructura, ocurre un error de compilación
    • Los mensajes de diagnóstico incluyen ubicación exacta en el código y sugerencias de corrección
    • Con soporte para LSP (Language Server Protocol) puede usarse en editores principales como VSCode, Neovim y Zed

Usabilidad

  • Diseñado con énfasis en la interoperabilidad con Go
  • El operador pipeline (|>) permite expresar el encadenamiento de funciones de forma concisa
  • Los bloques try simplifican la propagación de errores
  • La concurrencia se implementa con task y Channel, de forma similar a las goroutines de Go
  • Los atributos de serialización permiten especificar nombres de campos JSON, omisión, conversión a cadena y etiquetas de validación
  • Incluye bloques recover para recuperación de panic, y permite manejo seguro de errores con el tipo Result
  • Soporta la sintaxis defer para garantizar liberación de recursos o rollback de transacciones

Resultado de compilación transparente

  • El código de Lisette se transforma en código Go claro y fácil de leer
    • Los tipos Option y Result se convierten respectivamente en las estructuras lisette.Option y lisette.Result
    • La sintaxis match se transforma en condicionales de Go para manejar cada rama
    • El operador ? se sustituye internamente por código de verificación de Result
  • Como ejemplo, la función classify recibe Option<int> y se transforma en condicionales explícitos de Go, mientras que la función combine se convierte en código Go que verifica Result

Información adicional

  • Repositorio oficial: github.com/ivov/lisette
  • Publicado bajo licencia MIT, y desarrollado por Iván Ovejero a partir de 2026

1 comentarios

 
GN⁺ 23 일 전
Comentarios en Hacker News
  • Hablé con el autor y, aunque no probé el lenguaje directamente, Lisette me parece interesante y claramente mejorado frente a Go
    Aun así, creo que es difícil superar por completo las limitaciones de Go. Por ejemplo, el problema del typed nil que viene de los tipos de interfaz de Go se maneja con Option en Lisette, pero el doble desempaquetado (Some(Some(h))) puede volverse incómodo
    Además, la forma en que Go maneja defer sigue siendo poco práctica y no permite liberación automática de recursos como RAII
    TypeScript complementó a JavaScript porque no había una alternativa que pudiera ejecutarse en el navegador, pero ahora existe WASM, así que la situación es distinta
    Por eso surge la duda de “si ya existe Rust, ¿por qué hacer que Go se parezca a Rust?”. Aun así, Lisette parece apuntar a un punto intermedio
    Al final, Lisette parece adecuado para quienes quieren mejorar una base de código existente en Go o seguir usando el runtime de Go
    Lo que me da curiosidad es la ausencia de una guía de inicio rápido que responda: “¿cómo empiezo a escribir este archivo en Lisette en lugar de Go?”
    Artículo relacionado: Go is still not good

    • Go sigue siendo único por ofrecer un runtime de concurrencia basado en GC
      En dominios donde se manejan grafos de referencias complejos, el GC es esencial, y gracias a la estructura de stacks en modo usuario de Go, tiene un modelo de memoria eficiente
    • En los lenguajes con GC, la velocidad de desarrollo es mucho mayor. Hice chatbots en Rust y Python, y aun teniendo experiencia con Rust, Python fue mucho más rápido
      Go también sirve bien para crear este tipo de herramientas CLI rápidas — por ejemplo: wordle-tui
    • Go tiene muchas rarezas como lenguaje, pero es excelente como target de compilación
      Tiene muchas ventajas: sintaxis simple, soporte multiplataforma, runtime y GC integrados, estructura de “errors as values”, green threads y un compilador AOT rápido
      El defer de Go es útil, pero el manejo de errores y las reglas de alcance se sienten incómodos
    • Me llamó la atención la frase del blog de que “Go es un lenguaje que se equivocó dos veces con NULL”
      TypeScript tampoco resolvió ese problema, y de hecho es peor. Por eso hice yo mismo un paquete de tipo Option y lo publiqué en NPM → fp-sdk
    • El async de Rust es menos cómodo que el de Go porque no tiene GC. Solo por eso ya hay razones para elegir el runtime de Go
  • Ya existen varios lenguajes que compilan a Go — XGo, Borgo, Soppo, etc.

    • Borgo y Lisette simplemente reemplazan el retorno (T, error) por un tipo Result, pero semánticamente no son exactamente lo mismo
      Por ejemplo, en io.Reader.Read, (n!=0, io.EOF) significa finalización normal, así que tratarlo simplemente como error causaría un comportamiento incorrecto
    • Me pregunto cómo se propagan los errores de compilación desde el lenguaje objetivo al lenguaje fuente
  • La calidad de los mensajes de error de Lisette es impresionante. Las pistas de “help” se sienten realmente útiles
    Aun así, me preocupa que el código transformado a Go pueda volverse verboso, y que en errores de runtime haya que depurar en código Go
    También parece difícil llamar a Lisette desde código Go existente
    Me pregunto si Lisette es un lenguaje experimental o si realmente apunta a producción

    • El desarrollador respondió directamente: si usas la opción lis run --debug, se insertan comentarios //line source.lis:21:5 en el código Go para que los stack traces se mapeen al código original de Lisette
      El LSP maneja los errores de compilación tomando como referencia los archivos .lis
      Por ahora no existe la función de llamar a Lisette desde Go, pero la prioridad es permitir importar paquetes de Go desde Lisette
      Al principio era un experimento, pero el objetivo es convertirlo en un lenguaje de nivel producción
  • Me pregunto por qué no adoptaron tal cual una sintaxis parecida a Rust
    Por ejemplo: import "foo.bar" en lugar de use foo::bar, Bar.Baz => en lugar de Bar::Baz =>, etc.
    Quien conoce Rust puede confundirse, y quien no lo conoce no transfiere ese conocimiento a Rust

    • Estas diferencias de sintaxis son menores; lo importante es llevar el sistema de tipos de Rust a Go
      int y float64 siguen las reglas de nombres de tipos de Go
    • Cuando uno va y viene entre varios lenguajes, la similitud sintáctica puede incluso provocar confusión. Por ejemplo, a menudo olvido que en PHP hay que usar . en lugar de +
    • Yo también al principio quise hacer un lenguaje estilo Rust basado en TypeScript, pero terminé dándome cuenta de que Rust en sí no es tan difícil como parece
    • Implementar un modelo de memoria estilo Rust en un lenguaje con GC es muy poco natural. Es como si cada objeto tuviera su propio espacio de direcciones, lo que lo vuelve complejo
    • Lisette es un lenguaje inspirado en Rust, no intenta convertirse en Rust. Su público principal son los desarrolladores de Go
  • El runtime de Go es bueno, pero el lenguaje en sí se siente tosco y sin intención de mejorar
    Así que si alguien llega al punto de usar un transpiler, probablemente de verdad odia Go

  • Me pregunto por qué Rust y otros lenguajes de su familia separan struct y method
    No entiendo por qué no se pueden definir métodos directamente dentro del struct

    • En Rust, los campos de un struct influyen en los auto-traits, así que es importante poder verlos de un vistazo
      Además, los bloques impl pueden tener restricciones genéricas distintas de las del struct, por lo que se pueden definir varios
      Por último, Rust es un lenguaje diseñado para pensar alrededor de la forma (Shape) de los datos
    • Personalmente, siento que los bloques impl se parecen a los métodos de Go, y no diría que uno sea claramente mejor que el otro
  • Si existiera un lenguaje con apariencia de Python pero que compilara a Rust o Go, sería realmente genial

    • Mojo es un lenguaje de alto rendimiento con sintaxis basada en Python creado por el fundador de Swift
    • Spy es un intento temprano que compila a C, y Nim también es un lenguaje maduro de una línea similar
    • Nim tiene una sintaxis parecida a Python y un sistema de tipos estático, y compila a varios targets como wasm y C
    • Static Python Skill es un intento de compilar Python de forma estática
    • Grumpy fue un transpiler de Python→Go hecho por Google, pero lleva 9 años sin actualizarse (apuntaba a Python 2.7)
  • Lisette parece un lenguaje que logra bien el equilibrio entre la simplicidad de Go y la complejidad de Rust
    Me pregunto si hay alguna razón por la que la velocidad de compilación deba ser mucho más lenta que la de Go, y qué partes de Rust se excluyeron intencionalmente
    Por ejemplo: borrow checking, tipos de datos, async, etc.

  • Go es un lenguaje fácil de aprender, pero le faltan funciones
    Lisette parece un lenguaje interesante que llena esos vacíos
    Así como TypeScript extendió JavaScript, agregar a Go un sistema de tipos expresivo y un compilador estricto podría convertirlo en un excelente lenguaje de backend
    Mi sugerencia personal sería soportar compartición de tipos con frontends en TypeScript. Esa es una de las razones por las que TypeScript también es popular en backend

  • Como desarrollador de automatización de infraestructura que duda entre la seguridad de Rust y la simplicidad de Go, la idea de poner la usabilidad de Rust sobre el runtime de Go me parece muy atractiva
    Voy a seguir de cerca la evolución del proyecto