1 điểm bởi GN⁺ 2 giờ trước | 2 bình luận | Chia sẻ qua WhatsApp
  • Janet là một phương ngữ Lisp nhỏ, nhưng có ngôn ngữ mệnh lệnh, hàm hạng nhất, không gian tên định danh đơn và phạm vi khối từ vựng, nên có thể bắt đầu một cách đơn giản
  • Ngôn ngữ lõi chỉ gồm 8 lệnh do, def, var, set, if, while, break, fn, còn macro tạo ra các lớp bao điều khiển luồng mạnh hơn hoặc tiện hơn
  • Khả năng phân phối được đảm bảo bằng cách biên dịch chương trình Janet thành tệp thực thi native được liên kết tĩnh với Janet runtime, nên không yêu cầu người dùng cài Janet hay phụ thuộc nào
  • Parsing Expression Grammar (PEG) đơn giản, mạnh mẽ và dễ dự đoán hơn regex, còn sh cho phép biểu diễn pipe và redirect ngay trong Janet, mở rộng phạm vi viết CLI
  • Thực thi ở thời điểm biên dịch chạy trước các lệnh top-level rồi lưu snapshot trạng thái chương trình xuống đĩa, nhờ đó có thể chuyển giá trị, tham chiếu dùng chung, generator và trạng thái closure sang runtime mà không cần macro

Lõi đơn giản

  • Janet là một ngôn ngữ mệnh lệnh với hàm hạng nhất, không gian tên định danh đơn và phạm vi khối từ vựng
  • Phần lõi của ngôn ngữ được giữ nhỏ gọn với 8 lệnh do, def, var, set, if, while, break, fn
  • Macro cho phép tạo các lớp bao điều khiển luồng cấp cao mạnh hơn hoặc tiện hơn
  • Ngữ nghĩa runtime quen thuộc, và phần còn lại của ngôn ngữ cũng nhỏ đến mức toàn bộ thư viện chuẩn nằm gọn trong một trang

Phân phối native và nhúng

  • Chương trình Janet có thể dễ dàng được biên dịch thành tệp thực thi native liên kết tĩnh Janet runtime
  • Người dùng nhận bản phân phối không cần cài Janet, phụ thuộc của dự án hay bất kỳ thành phần bổ sung nào khác
  • Janet biên dịch chính nó thành bytecode, sau đó ghi bytecode đó vào một tệp .c khởi động Janet runtime, rồi biên dịch tệp C đó bằng trình biên dịch C của hệ thống
  • Một binary native “hello world” đơn giản nhỏ hơn 1MB; với Janet 1.27.0 trên macOS aarch64, kích thước là 784K
  • Binary này còn chứa toàn bộ Janet runtime, garbage collector, và cả bytecode compiler, nên cũng có thể tạo chương trình đánh giá mã Janet tại runtime
  • Janet runtime là một thư viện C nhỏ, nên sau khi liên kết có thể thao tác giá trị Janet bằng cách gọi các hàm C thông thường
  • Cũng có thể nhúng vào website để tạo các trang tĩnh với DSL lập trình tùy biến cho người dùng như Toodle

Phân tích cú pháp văn bản và DSL cho tiến trình con

  • Xử lý văn bản của Janet dựa trên parsing expression grammar thay vì regex
  • Parsing expression grammar đơn giản, mạnh mẽ và dễ dự đoán hơn regex, đồng thời không bị bó buộc theo dòng nên có thể phân tích văn bản nhiều dòng
  • Có thể phân tích HTML, JSON và các ngôn ngữ không chính quy khác, cũng như xử lý định dạng tệp nhị phân có chứa các null byte tùy ý
  • sh là một DSL shell scripting của bên thứ ba cho phép biểu diễn trực tiếp pipe và redirect trong mã Janet
($ find . -name *.janet | say)
  • DSL này nâng Janet từ một lựa chọn thay thế hợp lý cho Perl thành một lựa chọn thay thế hợp lý cho Bash trong phạm vi chương trình khá rộng

Collection và cảm giác cú pháp

  • Các kiểu collection của Janet đều có cả dạng mutable và immutable
  • Collection immutable có ngữ nghĩa giá trị, nên vector immutable [1 2] không khác với (take 2 [1 2 3]) dù địa chỉ bộ nhớ khác nhau
  • Collection mutable có ngữ nghĩa tham chiếu, nên hash table `@{:x 1 :y 2}`` chỉ bằng chính nó và một hash table khác có cùng khóa và giá trị vẫn là một đối tượng riêng biệt
  • Cú pháp dùng ngoặc rộng rãi, nhưng dùng [] cho list và {} cho table để phân biệt hình dạng
  • Literal mutable luôn có tiền tố @, như @"mutable string"
  • Hàm ẩn danh được viết là (fn [x] (+ 1 x)), và cũng có cú pháp rút gọn nâng biểu thức thành hàm bằng |, như |(+ 1 $)
  • Splat hoặc spread dùng ;, như (+ ;args)
  • Chuỗi backtick có thể mở bằng số lượng backtick tùy ý và phải đóng bằng đúng số lượng đó; bên trong chuỗi backtick, các escape sequence như \n không có hiệu lực
  • Tham số còn lại dùng & thay vì ., nên viết như (defn foo [first & rest] ...)
  • Janet không hỗ trợ reader macro, nên bản thân cú pháp là cố định; nếu đã biết đọc Janet thì có thể đọc mọi chương trình Janet

Macro và trạng thái thời điểm biên dịch

  • Macro Janet là mã dùng để viết mã, và ở thời điểm biên dịch nó đồng thời xử lý các giá trị cùng cây cú pháp trừu tượng của luồng thực thi hiện tại và luồng mã ứng dụng sẽ chạy trong tương lai
  • Macro Janet không hygienic, và cũng không có không gian tên riêng cho hàm
  • Tuy vậy, có thể unquote literal function để viết macro hoàn toàn trong suốt tham chiếu
  • Khi biên dịch chương trình Janet, trước tiên nó thực thi các lệnh top-level, câu lệnh thông thường, khai báo hàm... rồi ghi một snapshot trạng thái chương trình ra đĩa
  • Snapshot này giữ nguyên các tham chiếu dùng chung, nên sau khi khởi động lại vẫn có thể tiếp tục thay đổi các giá trị mutable
  • Generator ghi nhớ lệnh cần chạy ở lần resume tiếp theo, còn closure cũng giữ lại các giá trị đã đóng
  • Macro là một dạng đặc biệt của thực thi mã ở thời điểm biên dịch, nhưng khả năng này vẫn dùng được ngay cả khi không có macro
  • Trong game có thể tiền xử lý spline, có thể đọc tệp ở thời điểm biên dịch để đưa asset vào binary cuối cùng, và cũng có thể thực hiện các side effect tùy ý
  • Janet for Mortals cho thấy ví dụ tự động sinh database binding dựa trên tệp schema SQL, và cho rằng kiểu công việc này khá khó trong phần lớn ngôn ngữ khác

Thoải mái hơn truyền thống Lisp

  • Janet không giữ nguyên các quy ước Lisp cũ
  • CAR được đặt tên là first, PROGNdo, LAMBDAfn, SETQdef
  • nil không phải danh sách rỗng mà là một kiểu độc lập, còn boolean là giá trị hạng nhất
  • Janet tránh họ EQ, EQL, EQUAL, EQUALP, và linked list cũng hầu như không xuất hiện

2 bình luận

 
Ý kiến trên Hacker News
  • Janet có một số điểm còn thiếu. Chủ yếu là quản lý gói và chỉ định phiên bản còn yếu, và nhìn chung còn thiếu các thư viện như định tuyến HTTP nâng cao
    Dù vậy, tôi rất thích việc có thể tạo binary và script bằng JPM, và tính di động của nó cũng rất tốt. Trước đây tôi từng thử đưa ngôn ngữ lập trình Janet lên máy chơi game Playdate như một bản proof of concept
    Tôi thích viết code bằng Janet, nhưng mỗi lần như vậy thì việc mọi người tưởng tôi là người tạo ra ngôn ngữ này cũng hơi khó xử

    • Julia Evans có một bài rất thú vị trực quan hóa Gunzip bằng Julia: https://jvns.ca/blog/2013/10/24/day-16-gzip-plus-poetry-equa...
      Sẽ hay nếu có một phiên bản “Janet viết về Janet”
    • Không biết bạn đã thử jeep chưa: https://github.com/pyrmont/jeep/
      Nó cho phép vendor dependency và dễ dàng cài đặt các bundle Janet hiện đại mà không cần jpm
    • Nếu cần phía server thì như veqq đã nói, có joy với máy chủ HTTP nhẹ tự triển khai. Nếu cần client, việc bọc libcurl hoặc một HTTP client khác bằng Janet C API khá đơn giản
      Nếu bạn cởi mở với phát triển LLM, có thể để LLM viết wrapper còn logic thực tế thì viết bằng Janet
    • Tôi tò mò định tuyến HTTP nâng cao ở đây cụ thể là gì. Tôi làm toàn bộ phần web bằng https://github.com/joy-framework/joy, nên nếu có tính năng nào còn thiếu thì chắc tôi có thể thêm vào trong khoảng một tuần
  • Cùng tác giả đó còn có một ngôn ngữ tương tự ra đời sớm hơn là Fennel. Nó biên dịch sang Lua và phần triển khai cũng hoàn toàn viết bằng Lua
    Nó không có thư viện chuẩn riêng, nên thiếu khá nhiều thứ hay ho như thư viện parser của Janet, nhưng lại rất phù hợp để viết script trong các môi trường nhúng Lua
    https://fennel-lang.org/

    • Fennel thực sự rất hay, và cũng là một cách tốt để bắt đầu với dòng ngôn ngữ Clojure. Điều tôi phàn nàn lớn nhất là việc debug đúng kiểu một bãi mìn transpile
      Kết nối giữa Fennel và Lua VM rất mong manh, và chất lượng còn chưa bằng một nửa debugger và REPL của Janet. Fennel có tính di động tốt hơn nhiều, và nhờ LuaJIT mà thậm chí có thể vượt xa SBCL, nên điều này càng đáng tiếc
      Nhưng tôi nghĩ trải nghiệm transpile thật sự kéo nó lại. Có cách lách, nhưng ngay cả khi triển khai debug.setinfo thì bạn vẫn sẽ gặp những ca biên như khối match khá khó chịu
      Tôi cho rằng sẽ rất đáng giá nếu fork LuaJIT2 để sửa phần debug và cấu trúc lỗi cho phù hợp hơn với tính minh bạch ở cấp ngôn ngữ. Khi đó những ngôn ngữ như Fennel sẽ hấp dẫn hơn rất nhiều
  • Tác giả bài viết trước đây đã làm những công cụ này bằng Janet, từng được nhắc tới trên HN
    https://bauble.studio
    https://toodle.studio
    Nhờ hai công cụ nghệ thuật thú vị này mà tôi đã kỳ vọng khá nhiều vào Janet trong một thời gian

  • Tôi luôn thấy vui khi Janet nhận được sự chú ý. Một trong những tính năng hiện đại mà tôi muốn nhắc tới là sandbox
    “Vô hiệu hóa các tập tính năng để trình thông dịch không thể sử dụng một số tài nguyên hệ thống nhất định. Một khi đã vô hiệu hóa thì không có cách nào bật lại các tính năng đó.”
    https://janet-lang.org/api/misc.html#sandbox

    • Đây đúng là một tính năng rất ngầu, nhưng tôi tò mò không biết những tình huống nào mà một lập trình viên bình thường thực sự cần kiểu sandboxing này
  • Nhìn thấy “SETQ is def” thì ban đầu tôi đã buột miệng “gì cơ?”. Vì SETQ không tạo binding mà chỉ cập nhật thôi
    Đọc tài liệu (https://janet-lang.org/docs/bindings.html) thì có vẻ tác giả thực sự đã nhầm, vì ở đó ghi rằng “binding được tạo bằng def là bất biến”. Có lẽ ý họ là “SETQ is set”
    Tôi rất muốn thích Janet vì nó trông như điểm cân bằng hợp lý giữa Guile, Tcl và CL, nhưng tôi có phản xạ bài xích bản năng với việc dùng vector ngoặc vuông cho lambda và toán tử điều khiển luồng. Với Clojure tôi cũng vậy, rất khó để vượt qua, dù có lẽ nếu cố đủ nhiều thì vẫn được
    Ngoài ra tôi cũng tò mò tình trạng hiện tại của LSP/SLIME ra sao. Dạo này đó là thứ khá quan trọng

    • Việc dùng ngoặc vuông trong cú pháp Clojure rất nhất quán và khá logic
      Khi dùng ngoặc tròn, phần tử đầu tiên của danh sách sẽ quyết định cách diễn giải phần còn lại. Ví dụ (func a b c) là gọi hàm, (macro x y z) là mở rộng macro, còn ([p q r] …) là phần thân hàm “trần”, bắt đầu bằng một vector tham số rồi theo sau là các biểu thức thực thi
      Ngoặc vuông được dùng khi các phần tử đều cùng một “loại” và phần tử đầu tiên không có gì đặc biệt. Ví dụ (defn f [a b c] …) là một nhóm tham số cùng loại và tham số đầu tiên không đặc biệt, còn (let [a 1 b 2] …) cũng là một nhóm binding và binding đầu tiên không đặc biệt
      Ngoại lệ duy nhất tôi nghĩ ra là khi case dùng để nhóm nhiều phần tử khớp, nhưng đó là vì tính tiện dụng. Sau khi hiểu được logic này thì tôi đã đổi ý, và từ đó thấy nó khá đẹp
    • Bạn hoàn toàn có thể không dùng ngoặc vuông và ngoặc nhọn. Thay vì [1 2 3] có thể viết (array 1 2 3), và thay vì (fn [x] (+ 1 x)) có thể viết (f (x) (+ 1 x))
      Nó không phải bắt buộc
    • Khi hiểu cách destructuring hoạt động trong Clojure, vai trò của ngoặc vuông sẽ trở nên rõ ràng hơn
  • Với các script hệ thống vượt quá một độ dài nhất định, Janet đã thay thế sh, Python, awk... đối với tôi
    Thời gian khởi chạy script rất nhanh, trên hệ thống của tôi theo hyperfine là 1.4ms, gần bằng 1ms của dash. Đây là tính theo script chứ không phải file thực thi đã biên dịch
    Nhờ mô-đun sh-dsl, có thể viết lệnh shell rất thanh lịch như ($ cmda w x | cmdb y z). Khả năng nạp image để debug cũng cực kỳ hữu ích
    Tôi chỉ mới bắt đầu dùng rất gần đây, nhưng có cảm giác nó đã trở thành một trong những ngôn ngữ yêu thích của tôi rồi; Lisp khác duy nhất tôi từng dùng trước đó là MIT Scheme cho SICP

    • Với tôi thì babashka đã thay thế sh, Python, awk... rồi
  • Bài này thật mới mẻ. Nó có mùi của những cuộc thảo luận trước thời AI trên Internet
    Có ngôn ngữ mới, cú pháp mới, và những cuộc tranh luận nảy lửa giữa những người đã viết code nhiều năm. Tôi ước ai đó sẽ khởi động một cộng đồng trực tuyến không cho phép AI

    • Nếu bạn chưa theo kịp diễn biến gần đây, đợt tái ra mắt mới nhất của digg.com đã thất bại vì không chống nổi làn sóng bot
      Thực ra chắc phải nói là đợt tái ra mắt ngay trước đó, và hình như bây giờ lại có một trang chủ mới nữa. Người đầu tiên tìm ra cách chặn AI một cách ổn định trong cộng đồng trực tuyến có lẽ sẽ trở nên rất giàu
      https://www.techspot.com/news/111698-digg-relaunch-fails-two...
    • Tôi thường nghĩ về việc làm sao có thể tạo ra một cộng đồng trực tuyến không cho phép AI. Điều khó là làm được điều đó mà không phá vỡ tính ẩn danh trực tuyến
      Một dạng “bằng chứng về tính người” là một bài toán rất khó giải
    • Điều đáng kinh ngạc về AI là ngay cả khi không phải người nhiệt tình ủng hộ AI, người ta vẫn có thể lôi AI vào những cuộc trò chuyện chẳng liên quan đến AI. Những người phản đối sẽ làm việc đó thay
    • Chỗ như vậy có lẽ là lobsters. Sau một cuộc thảo luận có hơn 300 bình luận, có lẽ là lớn nhất lịch sử trang, bài viết bằng AI đã bị cấm
      Quy tắc chính xác do ban quản trị đặt ra là “sự chấp bút đáng kể của con người”, nhưng đừng để bị đánh lừa. Có rất nhiều người trên lobsters phản đối LLM về mặt ý thức hệ. Công nghệ đã được dùng “một cách đáng kể” đến mức nào thực ra không quan trọng lắm
      Công việc của tôi bị xếp vào loại rác chỉ vì có AI chạm vào, và cũng có người gọi tôi là kẻ phô bày bản thân hay kẻ có fetish khi tôi nói mình dùng AI. Tôi chỉ muốn báo trước cho ai đang cân nhắc tham gia
    • Trớ trêu thay, bình luận này, vốn là bình luận đứng đầu, giờ cũng trở thành nội dung về AI
  • Những câu như “bằng cách cho phép unquote các hàm literal, Janet cho phép viết macro hoàn toàn trong suốt tham chiếu” khiến người làm Lisp có vẻ thật sự phấn khích với những thứ cực kỳ trừu tượng
    Nếu nói như vậy với một người bình thường ngoài đường, chắc họ sẽ muốn bỏ chạy

    • Ví dụ về macro C có chứa literal nhưng không có tính trong suốt tham chiếu là như sau
      #define MULTIPLY(x, y) x * y
      int result = MULTIPLY(2 + 3, 4); // 14
      Không biết nghĩa của một thuật ngữ không có nghĩa là nó xấu. Nhìn cách diễn đạt thì có lẽ ý người ta là vậy
      Có một ngôn ngữ chung để nói về các mẫu và vấn đề lặp đi lặp lại trong lập trình là điều tốt. Chế nhạo thuật ngữ kiểu “đúng là đám lập trình viên kỳ quặc” thì vô nghĩa và chỉ phản tác dụng
    • Tôi tự hỏi bạn đã bao giờ thử giải thích ngôn ngữ lập trình hướng đối tượng và ưu điểm của nó cho một người bình thường ngoài đường chưa
    • Khoảng một năm trước tôi bắt đầu viết một trình thông dịch Scheme và đã đi được khá xa. Vài tháng trước tôi dừng lại khi có công việc mới
      Tôi đang nghĩ đến chuyện bắt đầu lại, nhưng phân vân liệu các tính năng ngách có đáng để triển khai không. Với tôi thì chúng cũng khó triển khai. Có lẽ tốt hơn là bỏ qua dynamic-unwind, thậm chí có thể bỏ luôn call/cc, rồi tập trung vào khả năng debug, hệ sinh thái, hiệu năng và quản lý gói
    • Mỗi khi bị hỏi “Bạn làm nghề gì?”, tôi hầu như luôn nhận được kiểu phản ứng đó
      Vì thế tôi thường trả lời rất mơ hồ kiểu “Tôi làm việc liên quan đến máy tính”, hoặc nói “Cũng không phải việc gì thú vị lắm đâu” rồi chuyển chủ đề. Chỉ cần cụ thể hơn một chút là mọi người bắt đầu tìm lối thoát
    • Có lẽ cả lập trình viên trung bình cũng vậy
      Thành thật mà nói tôi nghĩ các cộng đồng họ Lisp đã được hưởng lợi phần nào vì quy mô nhỏ. Ví dụ, ngay cả cuốn Design Patterns rất cũ cũng đã cảnh báo nên ưu tiên composition hơn inheritance, thế mà lập trình viên hướng đối tượng vẫn cứ tạo ra những hệ phân cấp sâu 15 tầng
  • Khi mới làm quen với Janet, các tài liệu này đã thực sự giúp ích cho tôi
    https://janetdocs.org/tutorials
    https://janet.guide/ do tác giả bài viết tạo ra

  • Tôi từng bị thu hút bởi các bài về Janet thỉnh thoảng xuất hiện trên HN, nhưng cuốn Janet for Mortals mà ai cũng đánh giá cao lại hoàn toàn không cho tôi cảm giác là sách dành cho người trần

    • Cũng có tài liệu nhập môn nhẹ nhàng hơn: https://janetdocs.org/tutorials
    • Thật bất ngờ. Ngôn ngữ này rất trực quan, đơn giản, và có rất ít quy tắc phải ghi nhớ. Nó là Lisp, nhưng bề mặt rất nhỏ gọn
      So với các ngôn ngữ khác thì Janet thực sự thuộc loại dễ học, nên việc cuốn sách đó khó hiểu làm tôi ngạc nhiên. Tôi chưa đọc sách, nhưng cũng khá quen với ngôn ngữ này, và thành thật mà nói tôi chỉ có thể khen nó
    • Cá nhân tôi thì bị khựng lại vì cú pháp macro xuất hiện quá sớm, nhưng sau đó thực sự có rất nhiều nội dung đáng giá
    • Tôi từng có cảm giác đó với Haskell. Haskell quá khó với tôi, nhưng bản thân cú pháp thì tôi lại thích
      Janet trông giống Lisp 2.0 nên cú pháp cũng mang phong cách Lisp
 
Ý kiến trên Lobste.rs
  • Chỉ sau 10 tháng bắt đầu dùng Janet, tôi đã mê đến mức gần như quên hết các ngôn ngữ ngoài họ APL, đồng thời đang vận hành trang tài liệu của cộng đồng và cũng đang viết hướng dẫn
    Trong vòng 3 tuần đầu tôi đã viết lại toàn bộ các script cá nhân, và phần mềm vận hành mới tôi làm cũng được viết bằng Janet
    Về mặt triển khai, gần như toàn bộ ngôn ngữ Janet hoạt động như một hash map, nên có thể xem symbol cục bộ bằng (keys (curenv)), xem symbol lõi bằng (keys (getproto (curenv))), và nếu muốn còn có thể dựng thứ gì đó giống CLOS dựa trên hash map; thậm chí đã có một triển khai như vậy
    Tôi đang chạy khoảng 20 website và nhiều dịch vụ bằng framework web Joy trên một VPS miễn phí 512MB, và cũng đã viết hướng dẫn liên quan
    Tuy vậy, cách gọi “bộ sưu tập bất biến” có phần không đúng với thực tế, vì thư viện chuẩn phần lớn trả về các giá trị có thể thay đổi, nên hiện tại không có nhiều lý do để quá câu nệ tính bất biến
    Khả năng chuyển giá trị ở thời điểm biên dịch sang thời điểm chạy đặc biệt mạnh. Ví dụ, nếu nhúng một tệp Kinh Thánh .tsv thành hash map vào binary ngay lúc biên dịch thì khi chạy chỉ cần tra cứu, và kết quả còn nhanh gấp đôi so với bản Go dùng embed
    Nếu tự triển khai cùng thứ đó trong Go dưới dạng hash map thì mã sẽ dài hơn rất nhiều, nhưng với Janet tôi còn có thể viết cả trình biên dịch Lisp sang Go chỉ trong 46 dòng
    Điểm thú vị hơn mà Ian Henry nhắc tới là Janet giữ lại trạng thái closure giữa các image/phiên, nghĩa là lưu môi trường liên quan vào hash map (curenv) rồi khôi phục ở một phiên REPL mới thì trạng thái bên trong closure vẫn tiếp tục được giữ nguyên

    • Một ví dụ rất hay làm bằng Janet là https://bauble.studio, và bài viết về quá trình xây dựng có tại https://ianthehenry.com/posts/bauble/building-bauble/ . Việc dùng WASM rất nổi bật
      Còn có DSL âm nhạc dựa trên Lisp tại https://lisp.trane.studio/ ; có thể xem bài báo https://dl.acm.org/doi/abs/10.1145/3677996.3678285 và ví dụ kết quả tại https://x.com/greg_ash/status/1824218993118388708
      Tôi cũng có thư viện tự viết, cung cấp cú pháp truy vấn kiểu SQL trên nhiều cấu trúc dữ liệu khác nhau
      Nó hỗ trợ chèn/cập nhật dataframe và lưu/tải CSV, đồng thời bao gồm cả Datalog và miniKanren, và cũng cho phép các phép toán vector hóa kiểu APL
      Cũng có jnj để dùng J trực tiếp trong Janet, còn Joy Web Framework có DSL truy vấn DB như (var account (db/find-by :account :where {:login (auth-result :login)})), và nó cũng được dùng trong mã xác thực của website thực tế
    • Cụm “bộ sưu tập bất biến” trong bài gốc có lẽ là cách diễn đạt chưa chính xác. Điều muốn nói đúng hơn không hẳn là collection mà gần với kiểu giá trị tổng hợp và kiểu tham chiếu hơn
      Khi nói “bộ sưu tập bất biến” người ta thường nghĩ đến cấu trúc dữ liệu persistent, mà dù hữu ích thì đó không phải tính năng mặc định của Janet
      Điều tôi thực sự thích là tính đối xứng giữa kiểu giá trị và kiểu tham chiếu; dù ở cuối bài có viết “immutable composite values”, nếu không phải chính tôi viết thì có lẽ tôi cũng khó hiểu ngay ý đó
  • Janet là một ngôn ngữ mới mẻ và có thể nhúng, nên tôi muốn thử dùng nó cho phần script nhúng trong các dự án như game engine
    Nó có vẻ rất hợp với những nơi cần hot reload để lặp nhanh mà không phải thay DLL; Lua cũng rất tuyệt, nhưng Janet ở vài mặt có vẻ biểu đạt tốt hơn

  • Janet thật sự rất ngầu với tư cách một ngôn ngữ, và một ngày nào đó tôi muốn dùng nó làm ngôn ngữ script cho các dự án Zig. Thật vui khi thấy ngày càng nhiều người nhắc đến Janet

  • Trông có vẻ hay, nhưng tôi đã quen dùng babashka để script bằng Clojure nên cảm giác khá giống. Ngoài khả năng nhúng ra thì không biết có ưu điểm lớn nào khác mà tôi đang bỏ lỡ không
    Những đoạn như “destructure mảng với rest args có thể gây ra bản sao tốn kém” khiến nó nhìn chung có vẻ kém thiên về lập trình hàm hơn, nên tôi không thích lắm

    • Tôi nghĩ một trong những tính năng sát thủ của Janet là hỗ trợ PEG tích hợp sẵn. Khi tạo một DSL textbox cho dự án game side project, nó thực sự rất tiện
      Đây là kiểu tính năng mà mỗi lần phải parse văn bản bằng ngôn ngữ khác tôi đều thấy thiếu
    • Kiểu destructuring đó không phải cách dùng phổ biến, và array/tuple trong Janet không phải linked list
      Janet không hẳn là một Clojure nhỏ gọn có thể nhúng, mà gần với Lua có hỗ trợ lập trình hàm tốt hơn