let-go: lenguaje de la familia Clojure hecho en Go con arranque de 7 ms
(github.com/nooga)- let-go es un dialecto de Clojure escrito en Go, con compilador a bytecode y una VM de pila, que funciona sin JVM como un único binario de ~10 MB
- El arranque en frío es de unos 7 ms y, según la suite de pruebas de Clojure de jank-lang, su compatibilidad con Clojure se presenta como 4696 / 4921 assertions superadas (95.4%)
- Su autor lo usa para CLI, scripting y servidores web; además construyó sobre let-go un runtime de contenedores sin daemon, y puede compilar a binarios independientes o a páginas web WASM autocontenidas
- El objetivo es implementar muchas funciones de Clojure como persistent data structures, lazy seqs, transducers, protocols, records, multimethods, core.async y BigInts, además de ofrecer interop bidireccional con funciones,
structychannelde Go - No es un drop-in replacement de Clojure sobre JVM, no carga JARs, y los proyectos reales con dependencias de librerías requieren ajustes
- En benchmarks sobre Apple M1 Pro se reporta tamaño de binario de 10 MB, tiempo de arranque de 6.7 ms y memoria en reposo de 13.5 MB, mostrando ventaja en unidades de ejecución más pequeñas frente a Babashka, Joker, go-joker, gloat y Clojure JVM
- En tareas de cálculo numérico más grandes, el WASM JIT de go-joker o una JVM con HotSpot ya calentada quedan por delante; let-go se resume como similar a Babashka en la mayoría de los benchmarks algorítmicos y más de 10 veces más rápido que Joker upstream
- Los namespaces estándar incluyen
clojure.core,clojure.string,clojure.set,clojure.edn,clojure.test,clojure.core.async,io,http,json,transit,os,System,syscall,pods, entre otros - Puede cargar Babashka pods, por lo que puede usar ese ecosistema de pods para SQLite, AWS, Docker, vigilancia de archivos y más, y comparte
~/.babashka/pods/conbb - Entre las limitaciones conocidas están la falta de implementación de Refs / STM, Agents, hierarchies, reader tagged literals,
deftype,reify,clojure.spec,alter-var-root,subseq/rsubseq, así como la ausencia de detección automática de overflow de int64 - Entre las diferencias de comportamiento, el bloque
gono es una máquina de estados IOC sino una goroutine real; las regex usanre2de Go en lugar de las regex de Java, y el sistema numérico se compone deint64+float64+BigInt - La instalación es posible con Homebrew para macOS/Linux, desde Releases para Linux, macOS y Windows en amd64/arm64, o con Go 1.22+ usando
go install github.com/nooga/let-go@latest lgsoporta REPL, evaluación de expresiones y ejecución de archivos, y además ofrece compilación a bytecode.lgb, empaquetado como ejecutable standalone y creación de apps web WASM- La salida WASM consiste en un
index.htmlautocontenido con WASM inline de unos 6 MB gzipped y un service worker; al usar el namespaceterm, ofrece emulación de terminal basada en xterm.js - El servidor nREPL integrado funciona con CIDER, Calva y Conjure; dentro de programas en Go también se puede embeber let-go mediante
pkg/apicomo una capa de scripting para pasar valores, funciones,structychannelde Go a la VM
1 comentarios
Opiniones de Hacker News
¡Está bueno! Hace poco estuve experimentando con ponerle sintaxis Lisp a la semántica de Go: https://codeberg.org/veqq/Joe
Entre los lenguajes tipo Clojure sin JVM, Janet también está muy bien, y lo he estado usando en producción desde hace un tiempo: https://janet-lang.org/
Si quieres la VM y las bibliotecas de Lua, también está Fennel
También vale la pena probar este REPL de navegador en Wasm: https://gloathub.org/repl/
Gloat es una herramienta de automatización AOT para Glojure
El verano pasado hice posible el AOT de Glojure junto con James Hamlin, y desde entonces he seguido desarrollándolo. También estoy trabajando con marcingas(nooga) para que Gloat/Glojure/let-go colaboren bien entre sí
Sorprende que funcione en Plan 9
Estaría genial que Go se volviera un lenguaje de primera clase, o sea incluido por defecto, en 9front
Estoy trasteando con una red social para Plan 9: https://youtube.com/watch?v=q6qVnlCjcAI&si=MBCeM0QdA0WsKAe7
Está hecha completamente con rc y awk, pero hubo partes donde habría estado bien tener algo de Go o Clojure por ahí
Probé amd64 en 9front y parece que todo funciona bien. La CLI no se siente muy Plan 9 todavía, pero en algún momento me gustaría hacer el port más nativo
Ahora mismo hay varios dialectos de Clojure sobre Go, así que lo que más me interesa saber es cuál de ellos está completamente hosteado sobre Go y ofrece un nivel de interoperabilidad comparable al que tiene Clojure de JVM con Java
Me gustaría poder usar desde Go lo que yo haga, y desde Clojure usar Go, e incluso armar proyectos mixtos. También estaría bueno que, aparte de la interoperabilidad, se detallara qué cosas son iguales, cuáles no y cómo difieren
En cambio, let-go puede pasar de ida y vuelta cualquier valor de Go, incluyendo structs, funciones y canales, pero no puede traer directamente bibliotecas arbitrarias de Go sin envolverlas antes. Esas bibliotecas tienen que estar compiladas en el runtime
Es un detalle menor, pero en el README dice arranque en frío de 7 ms y unas líneas más abajo dice 6 ms. Capaz que se vuelve más rápido cuanto más lees el README
Es exactamente el tipo de port de Clojure que siempre estuve buscando
Porque siempre pensé que la biblioteca estándar de Go y la abstracción de canales daban una API base más simple y mejor, y que además encajaría bien con APIs del estilo core.async. También satisface esa necesidad de un gran binario monolítico
Gracias por el trabajo; cuando se me baje un poco mi nueva afición por C++26, sin duda voy a volver a mirarlo
Además, no sé por qué Glojure no estaba en mi radar, y este también parece un proyecto excelente
Digo PHP antiguo porque originalmente PHP era más parecido a un DSL centrado en la web; ahora ya no. Una especie de lenguaje backend fácil de escribir, parecido a PHP pero con la potencia de Go detrás, sonaría interesante, y Clojure sería una gran elección
Como alternativa también está Joker: https://joker-lang.org
Es realmente excelente y creo que está totalmente subestimado
Aun así, no quiero agregarle demasiadas cosas a let-go. Me gusta que quepa dentro de 10 MB
Ojalá el nombre del lenguaje fuera mejor que simplemente “lets-go”. ¿Qué tal “clogo”?
(let [...] (go ...))¡Te deja hacer let en Go!
Clogo para mí sería no-go. Si hay otras ideas buenas, con gusto las consideraría
Sería muy bienvenida una PR a https://github.com/chr15m/awesome-clojure-likes