- ClojureScript 1.12.145 đã thay đổi compiler để xuất các hàm có gắn hint
^:async thành JavaScript async function
- Có thể viết hàm ClojureScript chờ giá trị Promise bằng
await, giúp cải thiện khả năng tương tác với JavaScript
- Có thể dùng
^:async trong test và kiểm chứng kết quả gọi hàm bất đồng bộ bằng await
- Trong khảo sát Clojure gần đây, hỗ trợ async functions chiếm tỷ trọng cao nhất trong các yêu cầu cải thiện ClojureScript liên quan đến khả năng tương tác với JavaScript
- Trong các trường hợp phổ biến khi làm việc với API trình duyệt mới nhất và các thư viện phổ biến, nhu cầu bổ sung phụ thuộc bổ sung giảm đi; có thể xem toàn bộ danh sách thay đổi tại mục 1.12.145 của changelog ClojureScript
Sử dụng ^:async và await
- ClojureScript 1.12.145 đã thay đổi compiler để xuất các hàm có gắn hint
^:async thành JavaScript async function
- Khi ClojureScript chuyển sang nhắm mục tiêu ECMAScript 2016, việc lựa chọn cẩn trọng các mảng cải thiện khả năng tương tác với JavaScript trở nên khả thi hơn
- Giờ đây có thể viết các hàm ClojureScript chờ giá trị
Promise bằng await
(refer-global :only '[Promise])
(defn ^:async foo [n]
(let [x (await (Promise/resolve 10))
y (let [y (await (Promise/resolve 20))]
(inc y))
;; not async
f (fn [] 20)]
(+ n x y (f))))
- Có thể dùng
^:async trong test và kiểm chứng kết quả gọi hàm bất đồng bộ bằng await
(deftest ^:async defn-test
(try
(let [v (await (foo 10))]
(is (= 61 v)))
(let [v (await (apply foo [10]))]
(is (= 61 v)))
(catch :default _ (is false))))
Bối cảnh và danh sách thay đổi
- Trong khảo sát Clojure gần đây, hỗ trợ async functions chiếm tỷ trọng cao nhất trong các yêu cầu cải thiện ClojureScript liên quan đến khả năng tương tác với JavaScript
- Với cải tiến lần này, trong các trường hợp phổ biến khi làm việc với API trình duyệt mới nhất và các thư viện phổ biến, nhu cầu bổ sung phụ thuộc giảm đi
- Có thể xem toàn bộ danh sách sửa đổi, thay đổi và cải tiến tại mục 1.12.145 của changelog ClojureScript
- ClojureScript 1.12.145 có sự đóng góp của thành viên cộng đồng Michiel Borkent
1 bình luận
Ý kiến trên Hacker News
Tôi thấy borkdude là người đăng chủ đề này, và cũng được ghi là một trong những người đóng góp cho bản phát hành lần này
Từ lâu, lập luận phản đối hỗ trợ async/await thường xoay quanh hai điểm: cần thay đổi sâu rộng trên toàn bộ trình biên dịch CLJS, và các macro từ thư viện như Promesa đã cung cấp sự tiện lợi tương tự
Ngoài ra cũng có ý kiến rằng cứ dùng core.async là được, hoặc ngôn ngữ hướng biểu thức không hợp với async/await, nhưng đó giống quan điểm cá nhân hơn là những luận điểm chủ đạo được lặp đi lặp lại trên diễn đàn
Trong Clojurians Slack, borkdude từng nói anh ấy không tin chắc việc thêm hỗ trợ là bất khả thi, và cuối cùng có vẻ đã dành thời gian để hiện thực hóa nó, nên thật sự rất cảm kích
Điều thú vị là ClojureScript đã hỗ trợ mô hình bất đồng bộ từ rất lâu bằng thư viện core.async, từ trước rất lâu khi chính JavaScript có async/await
Hoàn toàn không phải để hạ thấp giá trị của bản phát hành này, mà là để nói rằng việc chỉ cần thêm một thư viện vào dependency là đã có thể dùng một tính năng ngôn ngữ mới mà ngôn ngữ chủ còn chưa có, thật rất ngầu. Clojure thật tuyệt
Hình như tôi biết đến nó qua một bài nói chuyện của David Nolen
Sau đó tôi chuyển dần sang hướng dùng JavaScript ở frontend ở mức tối thiểu, và SSE đẹp ở chỗ nó là một chiều. Thật vui khi thấy dạo này các lập trình viên ở nhiều hệ ngôn ngữ khác nhau cũng bắt đầu quan tâm đến SSE
Bài nói chuyện gần đây của David Nolen, “A ClojureScript Survival Kit”, cũng rất hay: https://youtu.be/BeE00vGC36E
Dù cảm ơn thế nào cũng không đủ cho những gì David “Swannodette” Nolen đã làm với ClojureScript và core.async từ những ngày đầu. Điều đặc biệt gây bất ngờ trong bài nói này là ông ấy dường như thật sự hào hứng với hướng bỏ ClojureScript để chuyển sang Clojure thuần phía máy chủ, server-sent events, và chỉ một chút JavaScript tối thiểu
Phần demo thực tế bắt đầu khoảng phút 26:30. Ông ấy cho xem mức sử dụng tài nguyên của một web app chạy phía client, rồi chạy chính web app đó trên server và đẩy một chiều sang client bằng SSE, khiến mức dùng tài nguyên gần như về 0, khá ấn tượng
Không phải phù hợp với mọi trường hợp, nhưng với một thư viện biến đổi DOM tối giản, việc suy luận về web app và trạng thái của nó trở nên dễ hơn nhiều. Trước đây tôi từng phải chạy cả REPL cho Clojure lẫn REPL cho ClojureScript, xử lý nhiều lưu lượng hai chiều và trạng thái khó tái hiện, còn bây giờ thì nhanh hơn nhiều và dễ tái hiện hơn
Output JavaScript to hơn, không có mô hình lỗi nội tại, và khi có vấn đề thì nó bị biến thành mã state machine khó đọc, khó debug
Thêm nữa, macro
gokhông thể biến đổi mã nằm ngoài S-expression của chính nó, nên dễ đẩy hàm thành quá lớnNhư một người ở Cognitect từng nói, “core.async là thứ nhảm nhí đẹp đẽ”
Tôi khá bất ngờ khi gần đây trên mạng xã hội Clojure/ClojureScript bỗng xuất hiện thường xuyên hơn
Tôi từng dùng nó trong công việc vài năm quanh giai đoạn 2012, nhưng rồi giống nhiều người khác, đã rời JVM để sang các ngôn ngữ hàm có kiểu
Liệu sự quan tâm tăng lên gần đây là vì coding kiểu agent? Vì không có type checking và ít lỗi cú pháp hay từ khóa gây vướng nên quét code nhanh hơn chăng? Hay là sự trở lại của S-expression đang đến?
Những codebase Clojure nghiêm túc mà tôi biết đều đầu tư mạnh vào test suite, nên chỉ cần bổ sung kỹ thuật hướng dẫn AI tận dụng test suite hiệu quả nhất là có thể chạy khá tốt
Tôi cũng có đồng nghiệp để agent tương tác trực tiếp với REPL, và họ nói nó còn nhanh hơn vì không phải trả chi phí khởi động mỗi lần. Tôi thì lười chưa làm tới mức đó, nhưng hiện tại cũng đã đủ nhanh rồi
Clojure có rất ít thứ gây vướng víu. Ngoài
falsevànilthì mọi thứ đều là true, không có bảng ưu tiên toán tử, và ngôn ngữ lõi mặc định hỗ trợ cấu trúc dữ liệu bất biến, bền vữngMọi thứ đều là biểu thức, không phải kiểu trộn giữa toán tử và biểu thức.
map,reduce,filterlà built-in và được dùng tự nhiên trong code bình thườngCode Clojure viết từ 10 năm trước đến hôm nay phần lớn vẫn có khả năng chạy được, và hệ sinh thái cùng những người thiết kế ngôn ngữ gần như xem việc phá vỡ code cũ là điều cấm kỵ
Trong các ngôn ngữ tôi từng dùng, đây là ngôn ngữ cho cảm giác tự do nhất khi biểu đạt ý tưởng và ít đau đầu nhất. Flowstorm, một dạng reverse debugger trên thực tế, cũng là công cụ như trong mơ
Đây là một ngôn ngữ rất tốt nếu bạn muốn sống vui vẻ. Mặt khác, chính vì đa số người dùng thấy điều đó là hiển nhiên nên họ cũng không ồn ào lắm
Trong số các lập trình viên dùng Clojure cho mục đích thương mại, cũng có nhiều người không thật sự hạnh phúc vì họ chưa hiểu ngôn ngữ đủ sâu. Thường là vì họ không tự chọn nó hoặc chưa sẵn sàng, và theo tôi, trước khi dùng Clojure thì nên có khoảng 10 năm trải nghiệm những điều mình ghét ở các ngôn ngữ khác
Các video về phần mềm của Rich Hickey, người tạo ra Clojure, nổi tiếng và có ảnh hưởng thật, nhưng điều đó không có nghĩa đồng nghiệp của bạn đã xem hoặc quan tâm đến chúng
Làm việc với codebase Python lớn không có kiểu cùng AI rất mệt. Những phần không được test bao phủ thì việc xác nhận xem có bị phá vỡ hay không thật sự quá tẻ nhạt
Hệ thống kiểu càng mạnh càng tốt. Thêm nữa, mô hình AI được huấn luyện trên code, nên ngôn ngữ càng phổ biến thì khả năng nó làm tốt càng cao. ClojureScript rất hay, nhưng không phải ngôn ngữ chủ lưu, nên tôi nghĩ hiệu năng AI với nó sẽ kém hơn JavaScript
Cuối cùng, nếu cân nhắc tới AI thì tốt hơn nên chọn ngôn ngữ có kiểu, hoặc nếu là ngôn ngữ động thì chọn loại có type hint
Cái này thật sự lớn. Từ sau khi Jank được công bố, tôi chưa thấy điều gì trong hệ sinh thái Clojure khiến người ta hào hứng như thế này
Tôi thật sự muốn có một phương án thay thế JavaScript ở frontend vượt qua mức độ obscure để trở thành thứ có chỗ đứng thực sự
Tôi muốn thử thứ như ClojureScript, nhưng ngoài các dự án cá nhân thì khó hình dung nó có thể được dùng ở đâu. Có lẽ sẽ dễ áp dụng hơn trong các tổ chức mà backend đã là Clojure
Tôi chưa dùng nó trong production, nhưng đã deploy vài dự án cá nhân và vài thứ cho gia đình dùng. Reagent, wrapper React cho ClojureScript, thành thật mà nói, với tôi còn hợp lý hơn cả chính React
Bạn tạo HTML bằng Hiccup, và component chỉ là các hàm bên trong DSL Hiccup, mà DSL này thực chất cũng gần như là list, nên kết quả rất gọn gàng. Cái gì tĩnh thì trông tĩnh, cái gì động thì rõ ràng là động, và cảm giác ít “ma thuật” hơn React thông thường nhiều
Điểm tôi thấy không ổn là khi cố dùng các component không mang tính hàm tìm được trên NPM. Không đến mức chí mạng nhưng code sẽ xấu đi. Có thể sửa bằng wrapper, nhưng một số thư viện JS trong cljs ở trạng thái mặc định khá bừa bộn
Cộng đồng cũng rất thân thiện và trưởng thành
Hãy đổi các script cá nhân trước để làm quen rồi cảm nhận lợi ích. Không phải lúc nào cũng tốt hơn trong mọi trường hợp, nhưng về sau người khác có thể tìm đến bạn để hỏi lời khuyên, nên bản thân bạn cần đủ tự tin
Khi đưa công nghệ lạ vào, chiến lược tốt là chọn thứ ít quan trọng hơn để viết lại rồi cứ để đó. Nếu có vấn đề thì dễ rollback, còn nếu mọi người bắt đầu thích thì có thể mở rộng dần
Trước đây khi lén đưa F# vào một tổ chức .NET, tôi cũng bắt đầu bằng việc viết các bài test ít quan trọng hơn bằng F#
https://blisswriter.app/
https://blog.nestful.app/p/how-we-dropped-vue-for-gleam-and
Tôi không theo dõi cljs lâu rồi, nhưng nhớ là ban đầu nó từng được giới thiệu như kiểu “Clojure trên JavaScript”. Ít nhất tôi nhớ Rich lúc đầu cũng giải thích như vậy
Tôi hiểu chủ đích là làm cho nó gần với một runtime nữa nhất có thể
Nhưng thay đổi lần này có vẻ như đang thêm một tính năng chỉ có ở cljs, và
awaitthì vốn đã là keyword trongclojure.core, nên còn xung đột với chính ClojureTôi tự hỏi liệu theo thời gian hai bản hiện thực đã tách xa nhau, hay tính năng này đủ quan trọng với người dùng để chấp nhận sự khác biệt đó
Điều này quan trọng ở chỗ có thể xử lý khả năng tương tác với JavaScript mà không cần thêm thư viện phụ trợ
Đây là tính năng bị thiếu từ lâu, nên bản phát hành lần này thực sự đáng mừng
Có vẻ cách xử lý tốt hơn là bọc các hàm async/await bằng CSP. Clojure vốn đã có sẵn các pattern tốt hơn
core.async không biến mất, và nếu async/await phù hợp hơn với việc triển khai dựa trên Promise thì phần
.cljscủa core.async cũng có thể được cập nhậtNgay cả khi có thêm hint hàm mới này, cách đó chắc cũng không biến mất
https://clojurescript.org/guides/promise-interop#using-promi...
Tôi không chắc nên tiếp nhận chuyện này thế nào. Chẳng phải một trong những điểm cốt lõi của core.async là đẩy tất cả mấy thứ này vào channel sao?
Tôi không chắc việc có keyword
asynckiểu JavaScript có thật sự là một nâng cấp khôngBạn không bắt buộc phải dùng nó, và vẫn có thể tiếp tục dùng core.async. Đây cũng là tính năng được yêu cầu nhiều nhất trong khảo sát ClojureScript gần đây