- let-go là một phương ngữ Clojure được viết bằng Go, có trình biên dịch bytecode và stack VM, hoạt động dưới dạng binary khoảng 10MB mà không cần JVM
- Thời gian cold start khoảng 7ms và theo jank-lang Clojure test suite, mức độ tương thích với Clojure được công bố là vượt qua 4696 / 4921 assertions (95,4%)
- Tác giả đang dùng nó cho CLI, script và web server; đồng thời cũng đã xây dựng daemonless container runtime trên let-go, và có thể biên dịch thành binary chạy độc lập hoặc trang web WASM tự chứa
- Mục tiêu là triển khai nhiều tính năng của Clojure như persistent data structures, lazy seqs, transducers, protocols, records, multimethods, core.async, BigInts, đồng thời cung cấp interop hai chiều với hàm,
struct, channel của Go
- Đây không phải drop-in replacement cho Clojure trên JVM, không tải JAR, và các dự án thực tế có phụ thuộc thư viện sẽ cần điều chỉnh
- Trên benchmark Apple M1 Pro, nó cho thấy lợi thế về đơn vị thực thi nhỏ gọn hơn Babashka, Joker, go-joker, gloat và Clojure JVM với kích thước binary 10MB, thời gian khởi động 6,7ms, bộ nhớ nhàn rỗi 13,5MB
- Trong các tác vụ tính toán số lớn hơn, WASM JIT của go-joker hoặc JVM HotSpot sau khi warm-up cho kết quả tốt hơn; let-go được tổng kết là tương đương Babashka ở phần lớn benchmark thuật toán và nhanh hơn hơn 10 lần so với Joker upstream
- Các namespace tiêu chuẩn gồm
clojure.core, clojure.string, clojure.set, clojure.edn, clojure.test, clojure.core.async, io, http, json, transit, os, System, syscall, pods...
- Có thể tải Babashka pods, nên có thể dùng hệ sinh thái pod cho SQLite, AWS, Docker, giám sát file..., và chia sẻ
~/.babashka/pods/ với bb
- Các hạn chế đã biết gồm chưa triển khai Refs / STM, Agents, hierarchies, reader tagged literals,
deftype, reify, clojure.spec, alter-var-root, subseq / rsubseq, cùng với việc không tự động phát hiện int64 overflow
- Về khác biệt trong hành vi, khối
go là goroutine thực sự chứ không phải IOC state machine, regex dùng re2 của Go thay vì Java regex, và hệ số được cấu thành từ int64 + float64 + BigInt
- Có thể cài đặt qua Homebrew cho macOS/Linux, Releases cho Linux·macOS·Windows trên amd64/arm64, hoặc dùng
go install github.com/nooga/let-go@latest với Go 1.22+
lg hỗ trợ REPL, expression eval và chạy file; đồng thời còn cung cấp biên dịch bytecode .lgb, đóng gói standalone executable và tạo ứng dụng web WASM
- Đầu ra WASM gồm
index.html tự chứa khoảng 6MB gzipped với WASM được inline và service worker; khi dùng namespace term sẽ cung cấp giả lập terminal dựa trên xterm.js
- Máy chủ nREPL tích hợp hoạt động với CIDER, Calva, Conjure; còn trong chương trình Go, có thể nhúng let-go như một lớp scripting qua
pkg/api để truyền giá trị, hàm, struct, channel của Go vào VM
1 bình luận
Ý kiến trên Hacker News
Hay đấy! Gần đây tôi cũng đã thử nghiệm gắn ngữ nghĩa của Go với cú pháp Lisp: https://codeberg.org/veqq/Joe
Trong số các ngôn ngữ họ Clojure không có JVM thì Janet cũng rất tuyệt, và tôi đã dùng nó trong production một thời gian: https://janet-lang.org/
Nếu muốn Lua VM và thư viện thì cũng có Fennel
Cũng nên thử Wasm browser REPL này: https://gloathub.org/repl/
Gloat là công cụ tự động hóa AOT cho Glojure
Mùa hè năm ngoái tôi đã cùng James Hamlin làm cho Glojure AOT khả thi, và từ đó đến nay vẫn tiếp tục phát triển nó. Tôi cũng đang làm việc với marcingas(nooga) để Gloat/Glojure/let-go có thể phối hợp tốt với nhau
Việc nó chạy được trên Plan 9 thật đáng ngạc nhiên
Sẽ rất hay nếu Go trở thành ngôn ngữ hạng nhất trên 9front, tức là ngôn ngữ được tích hợp sẵn
Tôi đang nghịch một mạng xã hội cho Plan 9: https://youtube.com/watch?v=q6qVnlCjcAI&si=MBCeM0QdA0WsKAe7
Mọi thứ đều được làm bằng rc và awk, nhưng có vài chỗ tôi ước gì có Go hay Clojure chen vào
amd64 đã được thử trên 9front và có vẻ mọi thứ đều hoạt động tốt. CLI thì chưa thực sự đậm chất Plan 9, nhưng sau này tôi có ý định làm cho bản port này tự nhiên hơn với nền tảng
Giờ đã có vài phương ngữ Go của Clojure, nên điều tôi muốn biết nhất là bên nào được host hoàn toàn trên Go, và cung cấp mức độ tương tác như JVM Clojure có với Java
Sẽ tuyệt nếu tôi có thể dùng thứ mình tạo ra từ Go, và trong Clojure cũng có thể dùng Go, thậm chí tạo cả dự án lai. Ngoài khả năng tương tác, tôi cũng muốn có tài liệu nêu rõ chi tiết điểm nào giống, điểm nào khác và khác ra sao
Ngược lại, let-go có thể truyền qua lại bất kỳ giá trị Go nào, bao gồm struct, function và channel, nhưng không thể kéo trực tiếp thư viện Go bất kỳ vào mà không cần wrapper. Các thư viện đó phải được build sẵn ở runtime
Một góp ý nhỏ là README ghi cold start 7ms, nhưng vài dòng bên dưới lại là 6ms. Có lẽ càng đọc README thì nó càng nhanh hơn
Đây đúng là kiểu bản port Clojure mà tôi luôn tìm kiếm
Vì tôi nghĩ thư viện lõi và abstraction channel của Go là API nền tảng đơn giản và tốt hơn, lại còn có vẻ rất hợp với các API kiểu core.async. Nó cũng đáp ứng được nhu cầu về một binary đơn khối lớn
Cảm ơn vì công sức này, và khi sự hứng thú mới của tôi với C++26 dịu bớt thì nhất định tôi sẽ xem lại
Ngoài ra tôi cũng không hiểu sao Glojure lại chưa từng lọt vào radar của tôi, vì trông đây cũng là một dự án rất tuyệt
Tôi nói PHP ngày xưa vì ban đầu PHP gần như là một DSL tập trung vào web, còn bây giờ thì không còn vậy nữa. Một ngôn ngữ backend dễ viết, hơi giống PHP nhưng có sức mạnh của Go chống lưng, nghe khá thú vị, và Clojure là một lựa chọn tuyệt vời
Ngoài ra còn có Joker: https://joker-lang.org
Nó thực sự rất tuyệt và theo tôi là bị đánh giá thấp nghiêm trọng
Tuy vậy, tôi không muốn thêm quá nhiều thứ vào let-go. Tôi thích việc nó vẫn nằm gọn trong 10MB
Tôi ước tên ngôn ngữ hay hơn chỉ là “lets-go”. “clogo” thì sao?
(let [...] (go ...))Nó cho phép dùng let trong Go!
Với tôi thì Clogo là no-go. Nhưng nếu có ý tưởng nào hay khác thì tôi sẵn sàng cân nhắc
Nếu gửi PR vào https://github.com/chr15m/awesome-clojure-likes thì sẽ rất được hoan nghênh