Janet dành cho người thường (2023)
(ianthehenry.com)- Janet for Mortals là một cuốn sách trực tuyến miễn phí về ngôn ngữ lập trình Janet, nhưng trọng tâm của bài hồi tưởng nằm ở quá trình tạo ra một tài liệu kỹ thuật bao gồm cả web REPL và các dự án ví dụ, hơn là bản thân cuốn sách
- Toàn bộ công việc mất 20 tuần, vượt quá ước tính 12 tuần cho riêng phần viết thuần túy, vì phát sinh thêm các việc phụ như website, binding C++, demo trên trình duyệt, parser CLI và công cụ kiểm thử
- Website của sách cung cấp REPL tích hợp dùng CodeMirror và cú pháp Lezer; tính năng tự động hoàn thành truy vấn môi trường Janet qua WebAssembly, còn
(report)lưu phản hồi vào SQLite cmd,judge,to do, Toodle.Studio được dùng làm các ví dụ nền tảng cho thấy Janet có thể được dùng cho scripting, công cụ CLI, kiểm thử, chạy trong trình duyệt và tương tác với JavaScript- Ngay sau khi ra mắt, chỉ nhờ đăng lên Hacker News và Lobsters, website có 30.025 khách truy cập duy nhất vào thứ Sáu, 9.568 vào thứ Bảy và 3.777 vào Chủ nhật, nhưng số IP duy nhất đọc từ 5 chương trở lên được ước tính là 387
Phạm vi cuốn sách và khối lượng công việc thực tế
- Janet for Mortals là một cuốn sách trực tuyến miễn phí về ngôn ngữ lập trình Janet
- Tổng thời gian thực hiện là 20 tuần, tính theo thời gian rảnh
- Ước tính ban đầu là 12 tuần, và nếu chỉ xét thời gian viết phần nội dung tiếng Anh thì không sai lệch quá nhiều
- Lịch trình thực tế bao gồm một phần lớn là các dự án lập trình xung quanh cuốn sách
- Dung lượng cuối cùng là 44.000 từ văn xuôi tiếng Anh, không tính các đoạn mã
- The Great Gatsby được đưa ra làm đối chiếu có 47.000 từ
- Ngắn hơn chưa tới một nửa so với loạt bài trước đó về Nix
- Trong 5 tháng, cùng với cuốn sách, các việc sau cũng được thực hiện
- Website của sách
jimmy: binding cho thư viện cấu trúc dữ liệu bền vững C++- Toodle.Studio: sân chơi turtle graphics tương tác
cmd: thư viện phân tích đối số dòng lệnhjudge: framework kiểm thử snapshot inlineto do: trình quản lý danh sách việc cần làm trên dòng lệnh
Website và REPL tích hợp
- Thiết bị cốt lõi của website Janet for Mortals là REPL tích hợp
- Người dùng có thể mở REPL bất cứ lúc nào bằng phím Escape
- REPL được cố định ở cuối trang nên không che nhiều nội dung chính
- Trình soạn thảo dùng CodeMirror
- CodeMirror mặc định không hỗ trợ Janet
- Nó dựa trên phần hỗ trợ ngôn ngữ Janet đã làm trước đó cho Bauble
- Những cú pháp Janet như chuỗi
multi`backtick`quoted, vốn không quan trọng trong Bauble DSL, lại cần thiết trong sách
- Khi bổ sung cú pháp Lezer mà CodeMirror sử dụng, cùng một cú pháp cũng được tái sử dụng cho tô sáng cú pháp trong các đoạn mã của sách
- Không tìm thấy static site generator quen thuộc nào hỗ trợ tô sáng mã Janet
- Ban đầu cuốn sách chỉ có đen trắng, nhưng màu sắc được thêm vào để cú pháp Janet xa lạ trông thân thiện hơn
- Static site generator được tự viết bằng
redo- Phần lõi của generator được viết bằng JavaScript nên có thể gắn cú pháp Lezer vào
- Toàn bộ cấu hình là một cấu trúc mong manh được nối với nhau bằng shell
- Remark được dùng cả để phân tích bản thảo sách lẫn trong REPL phía client
- Một extension đơn giản được thêm vào để gắn nhãn cho code block
- Docstring trong thư viện chuẩn Janet được viết bằng Markdown, nên được render tức thời thành HTML trong tự động hoàn thành của REPL
Tự động hoàn thành và phản hồi một chiều
- Tự động hoàn thành trong REPL được xem là quan trọng cho độc giả mới làm quen với Janet
- Khi REPL khởi động, môi trường Janet được truy vấn động qua WebAssembly
- Dù người dùng định nghĩa một symbol mới có docstring, nó cũng không xuất hiện trong kết quả tự động hoàn thành
- Có thể tạo lại tự động hoàn thành sau mỗi lần chạy lệnh, nhưng được đánh giá là không đáng
- Hàm
(report)nhận một chuỗi rồi POST lên một web server đơn giản, và server lưu nó vào cơ sở dữ liệu SQLite- Tương tự một hộp bình luận, nhưng điểm đặc trưng là gửi trực tiếp từ REPL
- Nhờ chức năng này, tác giả đọc phản hồi và sửa nhiều lỗi
- Không triển khai cách trả lời
- Backend report không phải Janet mà là một ứng dụng Haskell nhỏ
- Nó chỉ có nhiệm vụ nhận yêu cầu POST và đưa vào cơ sở dữ liệu SQLite
- Web server không được viết bằng Janet
- Yếu tố quan trọng nhất của web server được xem là bảo mật
- Janet và thư viện HTTP của Janet chưa được xem là đủ kiểm chứng để kết nối trực tiếp với Internet
jimmy: thử nghiệm tương tác C++
jimmylà binding Janet cho immer- immer là thư viện cấu trúc dữ liệu bền vững
- Binding chưa hoàn thiện, và có khả năng sẽ không hoàn thiện cho tới khi phát sinh nhu cầu sử dụng
- Dù vậy, nó vẫn được xem là một ví dụ thành công cho cách tương tác với mã C++ từ Janet
Toodle.Studio và Janet trong trình duyệt
- Bauble là một sân chơi nghệ thuật nhỏ đã được tạo trước đó, và là trải nghiệm đầu tiên nhúng Janet vào trình duyệt
- Khi đó không có nhiều tài liệu về nhúng Janet
- Độ khó cao vì phải dùng WebAssembly, Emscripten và TypeScript cùng nhau trong trình duyệt
- Kết quả cuối cùng của Bauble là một website có logic ứng dụng được viết bằng Janet
- UI dùng nhiều JavaScript, nhưng logic cốt lõi do Janet đảm nhiệm
- Một trong những động lực quan trọng để viết sách là muốn làm cho kỹ thuật dùng Janet trong trình duyệt trở nên dễ tiếp cận hơn
- Trong sách, Toodle.Studio được tạo làm ví dụ thay cho Bauble
- Bauble không có trạng thái và gần giống một hàm thuần biến chuỗi thành chuỗi, nên khá đơn giản xét từ góc độ tương tác
- Toodle.Studio rõ ràng là một fork của Bauble, nhưng tương tác giữa JavaScript và Janet phức tạp hơn
- Toodle.Studio có các yếu tố kỹ thuật phù hợp hơn cho ví dụ trong sách
- Phải chạy bất đồng bộ một chương trình Janet chạy lâu theo thời gian
- Vì mã JavaScript giữ cùng một giá trị Janet bằng nhiều tham chiếu, cần cân nhắc quản lý bộ nhớ
- Phải trao đổi các cấu trúc dữ liệu lồng nhau phức tạp với Janet thông qua C++
- Logo của Toodle.Studio là một chú rùa hoạt hình tạo bằng Bauble
- Được thêm vào sau phản hồi rằng đây là demo turtle graphics nhưng lại không có rùa
- Mắt của rùa được làm để nhìn theo chuột
cmd: parser đối số CLI cho Janet
cmdlà thư viện phân tích đối số dòng lệnh- Trong sách nó chỉ xuất hiện khoảng ba đoạn, nhưng cần thiết để cho thấy rõ Janet là một ngôn ngữ scripting tốt
cmdchịu ảnh hưởng mạnh từCore.Commandcủa OCamlCore.Commandđược xem là thư viện phân tích đối số dòng lệnh tốt nhất mà tác giả từng dùng- Tác giả cố tái hiện trải nghiệm đó trong Janet
cmdkhông tốt bằngCore.Command- Tác giả cho rằng mọi thứ sẽ dễ hơn rất nhiều nếu có kiểu
- Dù vậy, nó có 95% các tính năng được xem là quan trọng, và nhờ ký pháp ngắn gọn nên tiện hơn cho các script ad-hoc
- Vẫn còn thiếu chức năng sinh hàm tự động hoàn thành cho Bash
Core.Commandtự động sinh phần này- API của
cmdđược thiết kế để sau này có thể thêm chức năng đó
judge: framework kiểm thử snapshot inline
judgelà một trong những thứ đầu tiên được tác giả tạo bằng Janet vào năm 2021- Sau khi hiểu Janet hơn, tác giả đã viết lại từ đầu
- API trở nên dễ dùng hơn
- Phần triển khai cũng đơn giản hơn nhiều và dễ thay đổi hơn
- Khác biệt chính giữa Judge v1 và v2 nằm ở vị trí test và helper
- Test có thể nằm không chỉ trong thư mục
test/mà cả trong file nguồn thông thường - Thêm các helper
test-macrovàtest-stdout
- Test có thể nằm không chỉ trong thư mục
- Cách làm tương ứng của OCaml cho
test-stdoutđược nói là gần như cách duy nhất tác giả dùng khi viết test trong công việc- OCaml không có cách thật sự tiện để nhúng dữ liệu tùy ý vào mã nguồn, nên tiếp cận bằng cách biến mọi thứ thành chuỗi
- Sau khi sách ra mắt, chế độ
--interactiveđược thêm vào Judge- Trong sách có một chương về kiểm thử và debug bằng Judge
to do: công cụ việc cần làm viết bằng Janet thay vì Bash
to dođược chọn làm ví dụ cho chương scripting- Đây là một công cụ không tầm thường tác giả từng viết bằng Bash, và phần triển khai Bash rất đau đớn
- Những phần đặc biệt khó trong Bash là phân tích văn bản và xử lý ngày tháng
- Phân tích văn bản nhiều dòng bằng Sed không hề dễ chịu
- Thao tác
datehoạt động giống nhau trên macOS và Linux được xem là gần như bất khả thi
- Trong Janet, nhờ dùng PEG,
shvàcmd, tác giả có thể tạo nhiều tính năng hơn, nhanh hơn so với danh sách việc cần làm Bash ban đầu- Ví dụ, thêm tính năng chọn nhiều bằng
fzf - Việc tạo chuỗi null-terminated trong Bash được xem là khó
- Ví dụ, thêm tính năng chọn nhiều bằng
- Sách chỉ đề cập phiên bản đơn giản hóa
- Không có chức năng lên lịch việc trong tương lai
- Không có khái niệm “bỏ qua” một việc
- Chức năng cốt lõi là thêm mục vào danh sách và đánh dấu hoàn thành
- Khi dùng cùng
zsh-autoquoter, nó được xem là một ứng dụng hữu ích một cách bất ngờ
Công việc code và bảo trì trong quá trình viết
- Trong 20 tuần làm sách, việc viết code chiếm gần một nửa
- 8 tuần dành cho code, và trong một số giai đoạn tác giả vừa viết vừa code song song
- Ban đầu, tác giả chỉ dự kiến cải tiến Judge và viết parser đối số
- Việc triển khai parser đối số khó hơn dự kiến rất nhiều
- Tác giả không ngờ Bauble lại quá đơn giản đến mức phải làm thêm một sân chơi nghệ thuật mới
- Phần viết thực tế được thực hiện bằng Markdown trong Sublime Text
- Sublime Text là editor tác giả ưa dùng để viết văn xuôi dài
- Trong lúc viết, Janet có 2 phiên bản mới
- Các chương về debug và native module phải được cập nhật theo thay đổi của ngôn ngữ
- Tác giả dự định duy trì cuốn sách theo các bản phát hành Janet mới nhất
Phản ứng khi ra mắt và mức độ được đọc
- Việc quảng bá sách chỉ gồm đăng lên Hacker News, đăng lên Lobsters và tweet
- Trên Hacker News, nó nằm trên trang đầu cả ngày và có một thời gian đứng hạng 1
- Theo log truy cập Nginx, số khách truy cập duy nhất như sau
- Thứ Sáu: 30.025 người
- Thứ Bảy: 9.568 người
- Chủ nhật: 3.777 người
- Các con số này gần với số người bấm vào liên kết; số người thực sự đọc sách được cho là ít hơn nhiều
- Website không có phân tích theo dõi hành vi phía client
- Chỉ có thể ước tính sơ bộ bằng log truy cập
- Luồng truy cập các chương cho thấy tỷ lệ giữ chân không tốt
- Chương 1: 22% số người vào trang chủ
- Chương 2: 20% số người vào chương 1
- Chương 3: 69% số người vào chương 2
- Chương 4 “Pegular Expressions” và chương 9 “Xenofunctions” có lượng truy cập nhiều hơn chương 3
- Tính đến cuối tuần ra mắt, ước tính tốt nhất về số độc giả thực sự là 387 người
- Dựa trên số IP duy nhất đã tải từ 5 chương khác nhau trở lên
Nguồn gốc tên gọi và những giới hạn bộc lộ qua phản hồi
- Tên ngôn ngữ Janet bắt nguồn từ Janet, thực thể bất tử trong The Good Place
- Thực thể này giúp những mortals di chuyển trong thế giới sau khi chết, nên cũng liên hệ với tiêu đề cuốn sách
- Chương có ít lượt truy cập nhất là “Testing and Debugging”
- Đây là chương thứ ba từ cuối sách
- Tác giả cho rằng ba chương cuối là phần thú vị nhất của sách
- Phương pháp kiểm thử trong chương đó được xem là một trong những cải thiện năng suất lớn nhất trong sự nghiệp kỹ sư cá nhân của tác giả
- Tác giả nhận được 494 phản hồi qua chức năng report của REPL tích hợp
- Nhiều phản hồi là “sách hay” hoặc tin nhắn thử nghiệm
- Hàng chục phản hồi là báo lỗi chính tả, yêu cầu giải thích hoặc bình luận hữu ích
- Một số người dùng gửi câu hỏi mà không để lại thông tin liên hệ, và vì không có chức năng trả lời nên tác giả không thể phản hồi
- Chức năng report được triển khai như một tính năng phản hồi một chiều rất thô sơ
1 bình luận
Ý kiến trên Hacker News
Cũng không thể bỏ qua https://bauble.studio/ của cùng tác giả
Nó không chạy trên trình duyệt của chiếc máy tính cũ của tôi, nhưng khi học ở thư viện và muốn nghỉ một chút, tôi thường nghịch bauble khoảng 30 phút trên máy tính của thư viện
Chỉ cần thay đổi các con số qua lại mà đã tạo được đồ họa rất ấn tượng, và tôi mong Janet sẽ tồn tại lâu dài
unknown symbol twisterror: script:16:1: compile error: unknown symbol twistin evaluate [lib/evaluator.janet] on line 81, column 7in bauble-evaluator/evaluate [lib/init.janet] on line 8, column 12So sánh Janet với GNU Guile khá thú vị
Điểm mạnh ban đầu của Guile là nó được tạo ra để dễ dùng song song với C, nhưng vì là một ngôn ngữ lâu đời nên có vẻ vẫn chưa tiếp nhận cảm giác hiện đại kiểu đưa trình quản lý gói vào mặc định trong toolchain của ngôn ngữ
Điều tôi thích ở Guile là họ đã bỏ nhiều công sức để giải thích tính tương thích với chuẩn RNRS
Tôi không rõ Janet thực sự giống Scheme đến mức nào, nhưng cũng thấy tò mò
Nó gần với việc ai đó tạo ra Clojure trên nền Lua hơn
Cuốn sách ở https://janet.guide/, còn ngôn ngữ ở https://janet-lang.org/
Tôi thích cách tiếp cận thực dụng của cuốn sách này, và đó là lý do lớn khiến hiện tôi đang học bằng cách giải Everybody Codes bằng Janet
https://everybody.codes
Cách diễn đạt “con rùa là một ẩn dụ” hơi đáng tiếc
Con rùa không phải ẩn dụ mà là có thật: http://classicacorn.computinghistory.org.uk/8bit_focus/logo/...
Tất nhiên nó đúng với định nghĩa ẩn dụ là “một thứ đại diện cho thứ khác, một biểu tượng”, nhưng nghe giống như trò đùa về việc hiểu nhầm biểu tượng lưu bằng đĩa mềm là tủ lạnh
Cảm giác như thiếu mất bối cảnh rằng ngày xưa thực sự từng có những con rùa phần cứng thú vị và dễ thương
Chỉ nhìn tiêu đề, tôi tưởng đây là một trợ lý AI khác lấy cảm hứng từ Janet trong The Good Place, nên khá bất ngờ một cách dễ chịu khi hóa ra nó là một ngôn ngữ lập trình
Ngôn ngữ Janet được đặt tên theo Janet, thực thể bất tử trong The Good Place giúp con người vượt qua thế giới bên kia, nên tiêu đề cũng là một trò đùa khéo léo phù hợp với điều đó
Việc nó đi kèm PEG (ngữ pháp biểu thức phân tích cú pháp) thay vì một engine regex mặc định cũng khá bất ngờ
Tôi luôn mong rằng nếu một ngôn ngữ cung cấp thư viện regex mặc định thì cũng nên đưa vào một PEG tử tế
Xem <https://www.gnu.org/software/guile/manual/html_node/PEG-Pars...>
sporkcủa Janet có vị trí giống một kiểu libc, và cũng có tiểu module regex nên nhiều khả năng đã được cài đặtTôi lần đầu tiếp xúc với PEG qua Janet, và thích việc nó mạnh mẽ mà dễ dùng
Tôi đã đụng đến regex lắt nhắt hơn 20 năm, vậy mà chỉ sau vài tháng tôi đã hiểu PEG tốt hơn
Trong cộng đồng Janet cũng có nhiều callback liên quan đến The Good Place, và nhiều module bên thứ ba được đặt theo tên các nhân vật
elm/regexvàelm/parserkhông được tích hợp sẵn, nhưngelm/regexkhuyên dùng elm/parser thay thếTôi thích nguồn gốc cái tên, nhưng với một ngôn ngữ tên Janet thì có vẻ nó cũng có nghĩa vụ ưu tiên khả năng điều khiển
Tôi đã đọc cuốn sách, và vì nó khá thú vị, có cảm giác nghịch ngợm, nên việc học Janet trở nên vui hơn nhiều
Tuy nhiên tài liệu ngôn ngữ còn thiếu sót ở nhiều điểm
Các hàm hoặc lệnh thường chỉ được liệt kê, không có ví dụ hay giải thích, hoặc thiếu phần mô tả chúng làm gì
Có nhiều lúc tôi thấy một tính năng trong sách nhưng không tìm được trong tài liệu, và đó là một trong những lý do khiến tôi dừng học dù vẫn thích Janet
Tôi thích việc nó có nhiều giá trị mặc định hợp lý và có những điểm giống các ngôn ngữ mainstream hơn là cố bám vào các quy ước Lisp cũ kỹ
Rốt cuộc vì không phải là cons list nên thực ra nó không phải Lisp, nhưng điều đó không sao
Vấn đề là ngôn ngữ này chưa được ghi tài liệu đầy đủ
Tôi đang hoạt động ở mức nào đó trong cộng đồng Janet, nên nếu biết phần nào còn thiếu, tôi có thể góp phần cải thiện tài liệu
Thường chỉ có chữ ký hàm mà hoàn toàn không có giải thích thêm
Tôi hiểu việc tạo tài liệu bao quát tốn nhiều thời gian và công sức, nhưng chuyện này xảy ra quá thường xuyên nên tôi đã bỏ xuống và bắt đầu tìm một Lisp khác có thể biên dịch thành binary
Tôi không thích nghi được với Janet cho lắm, nhưng không biết đó có phải vấn đề của tôi không
Lisp duy nhất khác mà tôi từng dùng lâu là Emacs Lisp, còn Janet thì vừa đủ giống nhưng lại khác ở những điểm tinh tế, khiến tôi liên tục mắc lỗi nhỏ
Tính năng PEG trên tài liệu trông hấp dẫn, nhưng cú pháp khó xử lý và dễ gây nhầm lẫn
Tài liệu đầy đủ theo nghĩa là có mô tả mọi hàm, nhưng rất súc tích và thiếu ví dụ hoặc thông tin sử dụng hữu ích
Có vẻ ngay cả các chức năng cơ bản như phân tích JSON cũng không được bao gồm
Nếu với một ngôn ngữ dùng để viết script nhanh mà trước tiên phải tự viết parser JSON hoặc XML, thì công việc đó đã thất bại rồi
Đây là chuyện khoảng 4 năm trước nên hệ sinh thái có thể đã tốt hơn, và có thể chính tiêu chí đánh giá Janet cho mục đích viết script của tôi đã sai
Dù vậy, bài viết này khiến tôi muốn cài lại để thử
spork, vốn có vị trí giống một kiểu libcCó xu hướng nội bộ khá mạnh là giữ phần lõi nhẹ
Nhiều dự án phụ thuộc vào
sporknên khả năng cao nó sẽ được cài đặt từ sớmTôi nghĩ tài liệu khá ổn, nhưng đồng ý rằng vẫn còn khoảng trống về các ví dụ thực tế
Phần này đang được https://janetdocs.com bổ sung, với liên kết tới “ví dụ cộng đồng” cho từng hàm
Hơi lạc đề, nhưng nhờ một bài blog khác của tác giả gốc mà tôi đã bắt đầu dùng bàn phím cơ tách đôi
Tôi bị đau vai và cổ tay trong vài năm và nó đã giúp ích, tôi rất khuyến nghị xem thêm các bài viết khác của Ian
Cách nhấn
Escbất cứ lúc nào để mở REPL tích hợp gắn ở phía dưới có thể không phải là quyết định hayTrình duyệt đã có phím tắt mặc định cho
Esc, và Firefox sẽ thoát khỏi chế độ toàn màn hình khi nhấnEsc