3 điểm bởi GN⁺ 2024-05-03 | 1 bình luận | Chia sẻ qua WhatsApp
  • Cognition là một dự án nghiên cứu ngôn ngữ chọn antisyntax hậu tố hoàn toàn (postfix) để tránh vấn đề đọc trước (read-ahead) của Lisp và các ngôn ngữ concatenative
  • Các cơ chế cốt lõi là delimiter, ignore, singlet, falias, crank, metacrank cho phép chương trình tự thay đổi quy tắc token hóa và chu kỳ thực thi của chính nó
  • Bootstrap bắt đầu từ trạng thái mọi ký tự đều được đọc như một token đơn lẻ, rồi tự chuyển sang môi trường dùng khoảng trắng và xuống dòng làm delimiter
  • crankmetacrank kiểm soát khi nào token được đánh giá và khi nào chỉ được chất đống lại, nhờ đó định nghĩa được cú pháp prefix như chú thích #, escape \\, quote [, macro ( bên trong một hệ thống hậu tố
  • Ngay cả một phương ngữ Brainfuck cũng được hiện thực bằng các từ Cognition và quy tắc token hóa thay vì parser riêng, cho thấy hướng biến chính cú pháp thành mã và tự động hóa nó

Những điểm Cognition xem là vấn đề trong cú pháp hiện có

  • Lisp cung cấp metaprogramming mạnh nhờ s-expression và hệ macro, nhưng vẫn chịu ảnh hưởng của cú pháp cố định
    • Dấu ngoặc trái là tín hiệu phải đọc cho đến khi gặp ngoặc phải, nên rất khó hoặc trong một số triển khai là không thể thay đổi vai trò của ngoặc từ bên trong ngôn ngữ
    • Nếu muốn thay đổi cách phân tách các token đã đọc rồi ở thời điểm sau thì cần rất nhiều xử lý chuỗi
  • Quá trình nhìn vào đầu vào hiện tại rồi phải đọc thêm phía sau chính là syntax; một khi đã giả định đọc trước ở mức cơ bản thì sẽ bị ràng buộc vào một số dạng cú pháp nhất định
  • Cognition dùng antisyntax hậu tố hoàn toàn để tránh điều này
    • Nó giống các ngôn ngữ concatenative, nhưng tác giả cho rằng ngay cả các ngôn ngữ concatenative thông thường cũng gặp vấn đề đọc trước do dấu ngoặc vuông hoặc ký tự quote chuỗi
    • Hệ macro của Racket được xem là khác biệt vì nó dùng tiền xử lý chứ không phải thay đổi cú pháp động khi chạy

Dự án và ý tưởng cơ bản

  • Cognition là một dự án nghiên cứu đang hoạt động được thực hiện trong vài tháng cùng Matthew Hinton
  • Kho mã triển khai nằm tại cognition-rust, và kho này cũng có bài báo về ngôn ngữ
  • Việc hiểu parsing, tokenization và cú pháp sẽ giúp theo dõi dễ hơn
  • Phần giải thích bắt đầu từ mã “baremetal cognition” rồi phát triển dần theo hướng cú pháp tương tự Stem

Baremetal Cognition và token hóa

  • Nhìn bề ngoài, baremetal Cognition khá giống Brainfuck, nhưng có khả năng metaprogramming mạnh hơn
  • Mã bootstrap rất nhỏ dùng cả khoảng trắng và xuống dòng như những ký hiệu có ý nghĩa, và ở trạng thái ban đầu mọi ký tự đơn đều được đọc thành token
  • Cognition về cơ bản là thiết kế dựa trên stack, nhưng dùng thuật ngữ container theo nghĩa tổng quát hơn stack
  • Trong môi trường mặc định, ngoài falias đặc biệt ra thì không có từ nào tự động được thực thi
  • delimiter, ignore, singlet

    • delimiter cho tokenizer biết đâu là cuối một token và đâu là đầu token tiếp theo
    • Danh sách delimiter ký tự đơn có thể được sửa và đọc ngay trong mã Cognition
    • Ký tự ignore bị bỏ qua ở giai đoạn bắt đầu thu thập token của mỗi vòng read-eval-print loop
    • Mặc định là mọi ký tự đều là delimiter và không có ký tự ignore nào
    • Các danh sách delimiter, singlet, ignore có thể đổi cách hoạt động bằng cờ whitelist/blacklist
    • Cấu hình mặc định là blacklist delimiter rỗng, không có singlet được whitelist và không có ký tự ignore nào được whitelist
    • singlet là nhóm token hóa thứ ba: nó tự chèn chính nó vào token rồi kết thúc việc thu thập token
  • falias

    • falias là danh sách các từ được thực thi ngay khi được đưa lên container
    • f là falias mặc định; nó không được đẩy vào container mà sẽ thực thi từ ở đỉnh container
    • Trong ví dụ, khi f thực thi d, thì d sẽ đổi danh sách delimiter thành giá trị chuỗi của từ đó
    • Sau đó bootstrap tiếp tục bằng cách từng bước biến các ký tự như l, g, t, d thành non-delimiter, rồi đổi khoảng trắng và xuống dòng thành delimiter và ignore

Môi trường thực thi do bootstrap tạo ra

  • Bootstrap ban đầu thay đổi quy tắc delimiter và ignore để cuối cùng tạo ra môi trường trong đó khoảng trắng và xuống dòng là delimiter token, và chúng bị bỏ qua ở bước bắt đầu token
  • Sau đó nó đọc 1crank, rồi f thực thi crank để đi vào môi trường crank 1
  • Cốt lõi của quá trình này là có thể thay đổi cách token hóa ngay trong lúc chạy
    • Việc thay đổi delimiter, singlet, ignore có thể được tự động hóa bằng chương trình
    • Vì là hậu tố và không có đọc trước, không cần parse sẵn một hay nhiều token trước khi đánh giá biểu thức
  • falias cho phép thực thi một số từ nhất định mà không cần từ prefix hay cơ chế tự thực thi từ cơ bản

crank và metacrank

  • crank là cơ chế quyết định token trên stack sẽ được thực thi theo chu kỳ nào
  • Từ crank nhận một số làm tham số, rồi cứ mỗi từ thứ n tiếp theo được đưa vào container thì sẽ thực thi phần tử trên đỉnh stack
    • 1 crank ở cuối bootstrap tạo ra môi trường đánh giá mọi token
    • Ở trạng thái 5 crank, các từ có thể được tích lại cho đến khi token thứ năm đi vào
  • Mã ví dụ dùng unglue, swap, quote, prepose, def để tạo một từ tên là 2crank
    • unglue lấy ra giá trị của từ, kể cả function pointer của builtin như crank
    • prepose giống compose của Stem nhưng gắn ở phía trước và đưa vào VMACRO
    • def định nghĩa để 2crank đặt 2 lên stack rồi gọi builtin crank
  • Container và macro trong Cognition

    • Trong Stem có thể đặt từ trực tiếp lên stack, còn trong Cognition các từ chưa được đánh giá nằm trong container
    • Nhờ thiết kế này, các từ như compose có thể xử lý nhất quán giữa container chứa một từ đơn lẻ và các container khác thông qua cùng một API
    • Macro của Cognition khác với quote của Stem
    • Khi macro được đánh giá, nó bỏ qua crank và mọi phần tử bên trong đều được đánh giá
    • Nếu đánh giá một macro được bind vào từ, toàn bộ macro sẽ chạy không phụ thuộc crank, còn cranker chỉ tăng một lần
    • Macro hữu ích cho mã độc lập với crank và cho các expansion phục vụ tối ưu hóa
  • metacrank

    • n m metacrank thiết lập việc đánh giá theo chu kỳ m cho phần tử nằm sâu n phần tử dưới đỉnh stack
    • crank tương đương với 0 m metacrank
    • Mỗi token chỉ có thể có một metacrank được áp dụng để đánh giá, và metacrank thấp hơn có ưu tiên cao hơn
    • metacrank và crank không chỉ áp dụng với token trong file mà còn cả quá trình đánh giá đệ quy các định nghĩa từ
    • metacrank cho phép thao tác trực tiếp lên cú pháp kiểu như “đọc thêm n token rồi mới thực thi token này”
    • Sau khi lập trình xong các từ prefix thì có thể undef chúng nếu không còn cần nữa
    • Có thể tạo ký tự prefix dừng sau một số lượng token nhất định thay vì chờ một ký tự kết thúc cụ thể
    • Có thể đưa đầu vào người dùng vào một chương trình toán học, rồi chuyển đầu ra của nó cho một hệ cú pháp như metacrank

Quá trình phát triển thành phương ngữ Stem

  • Sau bootstrap, Cognition dần dần xây dựng từ bên trong ngôn ngữ một cú pháp gần với Stem v2
  • Trước hết, f bị xóa khỏi danh sách falias và chỉ để lại ing
    • Nếu đặt trực tiếp f lên stack thì nó sẽ bị thực thi, nên người ta tạo ff rồi cắt chuỗi làm đôi để lấy ra hai f
    • Sau đó f được định nghĩa thành một từ rỗng tương ứng với false
  • Chú thích #

    • Ký tự # là ví dụ mã đầu tiên hoạt động như một prefix thực sự
    • Ký tự chú thích này hoạt động như một prefix bỏ đi toàn bộ văn bản cho đến trước newline, tạo nên dạng cú pháp mà parser phải nhìn về phía trước
    • Cách hiện thực kết hợp geti, getd, gets, crankbase, halt, VMACRO cast, singlet, delim v.v.
    • geti, getd, gets lần lượt lấy ra chuỗi ignore, delimiter, singlet
    • halt đưa mọi metacrank về 0
    • VMACRO cast biến container trên đỉnh stack thành macro
    • Định nghĩa # thay đổi quy tắc token hóa, rồi gọi # trên từ sẽ được token hóa trong tương lai, bỏ phần chú thích đó đi và sau cùng quay lại crank cùng metacrank ban đầu
  • escape, quote, macro

    • \\ được định nghĩa thành ký tự escape cho phép đưa cả những từ lẽ ra sẽ được đánh giá lên stack
    • Sau đó thêm định nghĩa quote [ rồi lại dùng chính quote đó để tự định nghĩa lại một [ tốt hơn có hỗ trợ quote đệ quy
    • Nhờ def hậu tố, có thể dùng định nghĩa cũ để tạo ra định nghĩa mới
    • Đây là kiểu phát triển thường gặp trong Cognition mức thấp
    • ( được định nghĩa làm dấu ngoặc macro
    • Macro được thiết kế để tự động expand, và tác giả cho rằng bind một macro đã được expand sẵn vào từ sẽ hiệu quả hơn
    • Về mặt chức năng thì nó vẫn được đánh giá theo cùng cách
    • expand mở rộng đệ quy các định nghĩa từ bên trong quote hoặc macro bằng unglue
    • Trước tiên định nghĩa expand cơ bản, rồi dùng chính expand để định nghĩa lại nó cho các trường hợp tổng quát hơn

Phương ngữ Brainfuck

  • Trên phương ngữ Stem đã phát triển, Cognition định nghĩa một phương ngữ Brainfuck
  • Ví dụ chạy là ../crank -s 2 bootstrap.cog helloworld.bf brainfuck.cog
  • brainfuck.cog không phải parser Brainfuck theo nghĩa thông thường
    • Nó định nghĩa các từ Brainfuck
    • Nó token hóa Brainfuck
    • Nó chạy Brainfuck trong môi trường native của Cognition
  • Ví dụ này cho thấy cú pháp Cognition có thể định nghĩa cú pháp thay thế rất dễ dàng
  • Thay vì đọc ký hiệu rồi quyết định hành động theo ký hiệu đó, Cognition dùng metacrank để định nghĩa chính các ký tự prefix thành từ, qua đó đặt cú pháp vào trong định nghĩa từ

Ý tưởng dialect dialect

  • Có thể tưởng tượng ra một từ như mkprefix
    • Ví dụ, đó là từ nhận hai từ đầu vào [] cùng một phép toán nào đó, rồi tự động định nghĩa để [ áp dụng phép toán cho đến khi gặp ]
  • Ý tưởng này khả thi vì cả metacrank lẫn def đều là từ thông thường
  • Vì mọi thứ, kể cả d, i, s, đều là từ, nên có thể tạo ra những phương ngữ trừu tượng hơn để tự động hóa quá trình hiện thực cú pháp
  • Dù thư viện chuẩn chưa triển khai, đây là các mục đã được bàn với Matthew Hinton như khả năng cho thư viện chuẩn
    • metaword tự động tạo và gọi các từ trừu tượng
    • tìm kiếm word-generator để tự động trừu tượng hóa wordlist hiện tại
    • một cách chỉ dẫn framework trừu tượng hóa nhằm giải quyết vấn đề

Khả năng coi cú pháp như mã

  • Trong Cognition, xử lý chuỗi tương đương với hậu xử lý tokenizer, nên các phép toán chuỗi mang ý nghĩa rất mạnh
  • Các lĩnh vực ứng dụng tiềm năng gồm Symbolic AI, nghiên cứu cú pháp và grammar, thử nghiệm prototype cho ngôn ngữ và metalanguage
  • Cũng có các ý tưởng như chương trình đọc file cấu hình, shell dựa trên Cognition, hay hệ điều hành dựa trên Cognition
  • Cốt lõi là Cognition cho phép biến “syntax as code” thành hiện thực
    • Có thể lập trình cú pháp một cách động
    • Có thể tự động hóa chính việc sinh ra cú pháp
  • Các khái niệm như Metastack và cd chưa được đề cập, và được để lại cho các bài viết tiếp theo

1 bình luận

 
GN⁺ 2024-05-03
Ý kiến trên Hacker News
  • Tôi vẫn chưa bị thuyết phục rằng cách này tốt hơn thiết lập tầng reader của Racket
    Ví dụ, trong Racket có thể tạo một triển khai Datalog nhúng, dùng cú pháp Datalog nhưng vẫn tương tác được với các mô-đun Racket khác, và mô hình dữ liệu cơ bản không thay đổi
    Đây là cách cho phép metaprogramming mà không bị mắc kẹt trong S-expression, đồng thời xử lý ở mức cao hơn
    Kiểu bootstrap cú pháp như vậy rất hay và có giá trị nghiên cứu, nhưng tôi không rõ nó có tốt hơn về căn bản so với cách tiếp cận của Racket hay không
    Macro của Lisp, Scheme, Racket thường hoạt động trên AST, nhưng Rhombus hoạt động trên “shrubbery”, thứ giống AST nhưng trì hoãn một số quyết định parsing về sau, nhờ đó cho việc mở rộng cú pháp thêm chút linh hoạt
    Tham khảo: https://docs.racket-lang.org/guide/hash-reader.html, https://docs.racket-lang.org/datalog/datalog.html, bài báo Rhombus https://doi.org/10.1145/3580417
    • Tôi cũng không chắc nó tốt hơn readtable của Common Lisp, và tôi cho rằng #lang của Racket dễ dùng hơn readtable của CL
      Chỉ riêng readtable cũng đủ mạnh để triển khai cả một trình biên dịch C: https://github.com/vsedach/Vacietis
    • Nhìn việc dùng Brainfuck làm ví dụ cơ bản, tôi không rõ họ có thật sự muốn được nhìn nhận nghiêm túc hay không
      Cá nhân tôi đã bật cười ở đoạn “metacrank” xuất hiện
    • Nói macro Lisp hoạt động trên AST là không đúng với Lisp
      Trong Emacs Lisp, Common Lisp, ISLISP, macro chỉ nhận dữ liệu nào đó và trả về dữ liệu nào đó; không có khái niệm như AST
      Khi gọi (foo-macro ...), ... có thể là dữ liệu tùy ý
      Ví dụ, (defmacro rev (&rest items) (reverse items)) chỉ nhận danh sách đối số nguồn của lời gọi macro rồi đảo ngược nó
      Có thể dùng như (rev 1 2 3 4 +) hoặc (rev (rev 10 n -) (+ a 20 b) (rev 30 a *) list), và thực tế thứ được truyền vào là list, số và symbol
      Nó không phải văn bản, cũng không phải AST; ngay cả khi truyền dữ liệu đã tính toán cho eval thì nó vẫn hoạt động theo cùng cách
      Reader của Lisp về cơ bản đọc symbolic expression, tức tầng dữ liệu, còn EVAL, macro và các chức năng khác chủ yếu nhận dữ liệu
      Trình biên dịch có thể tạo biểu diễn AST nội bộ, nhưng đó là quyền tự do triển khai; ngôn ngữ Lisp thường được định nghĩa trên cú pháp dữ liệu chứ không phải cú pháp văn bản
      Trình thông dịch Lisp là “List Processor” xử lý S-expression trong lúc chạy chứ không xử lý văn bản, và COMPILE cũng nhận S-expression chứ không nhận văn bản
      Racket và Scheme có hệ thống macro riêng
  • Nếu góp ý cho tác giả, bài viết có thể vững hơn nhiều nếu đặt nội dung quan trọng nhất lên trước
    Phải hơn 300 từ mới nhắc đến dự án thực tế là Cognition; phần nói về Lisp cũng hay, nhưng tôi nghi ngờ đó có phải phần quan trọng nhất của dự án không
    Khi đọc một bài viết cung cấp thông tin, tôi luôn tự hỏi “có đáng bỏ thời gian không?”, nên tài liệu cần cho biết ngay từ đầu nó nói về gì
    Chỉ cần kiểu như “Cognition là một ngôn ngữ mới khám phá cú pháp do người dùng chỉnh sửa được” là đủ, nhưng sau bốn đoạn đầu tôi vẫn khó đánh giá liệu có đáng đọc tiếp hay không
    • Khả năng tôi dùng ngôn ngữ này cũng thấp, và kể cả có dùng thì tôi sẽ lấy thông tin từ tài liệu chứ không phải bài viết này
      Nếu thời gian là tiền bạc, thì có thể xem thời gian đọc bài này là lãng phí
      Thay vì kỳ vọng mọi nội dung trên Internet phải phù hợp với sở thích cá nhân, tôi nghĩ tốt hơn là thích nghi với các hình thức đã có
      Văn bản không phải phương tiện buộc phải tiêu thụ tuần tự như video, nên có thể đọc lướt để tìm phần thú vị; nếu không có thì bỏ, còn nếu có thì quay lại đầu để đọc
      Các lối viết đa dạng tốt hơn vì buộc ta phải có ý thức lọc thông tin mình tiêu thụ; nếu chỉ tiêu thụ thụ động thì đầu óc sẽ lười đi
      Tuy nhiên nếu là video thì tôi sẽ đồng ý
      Với video, phải quyết định có đầu tư thời gian trước khi xem hay không; xem tốc độ 2x hoặc tua 5–10 giây có giúp chút ít nhưng không giải quyết được vấn đề
    • Thứ tự bài viết với tôi trông khá hợp lý
      Cấu trúc là giải thích vấn đề trước rồi sau đó giới thiệu giải pháp
      Chỉ đọc vài câu là tôi đã hiểu đây là một giải pháp kiểu Don Quixote cho một “vấn đề” mà 99,999% người, kể cả người như tôi từng nghe về Lisp nhưng chưa dùng ngoài file cấu hình Emacs, sẽ chẳng quan tâm; dù vậy tôi vẫn cứ đọc tiếp
    • Phần liên quan đến Lisp không phải yếu tố quan trọng nhất của dự án, nhưng rõ ràng nó có vai trò cho thấy loại vấn đề mà dự án muốn giải quyết
      Nếu không có đoạn như vậy, phần sau sẽ khó hiểu hơn
    • Tôi quan tâm đến khái niệm này, nhưng câu đầu có vẻ biện minh cho sự cần thiết của nó như một phản ứng với cú pháp S-expression của Lisp, nên tôi lo mình sẽ bỏ lỡ bối cảnh
      Nếu không biết nền tảng đó, có thể bỏ lỡ ngữ cảnh của toàn bài, và cũng khó đánh giá đây có phải lập luận người rơm hay không
      Vì vậy toàn bộ thứ này tạo cảm giác như tồn tại cho một nhu cầu rất hẹp, trong khi tiêu đề thì tổng quát hơn nhiều và trông như một khái niệm khá thú vị
    • Tôi thấy bài hiện tại hoàn toàn ổn
      Chỉ trong hai câu đầu đã lộ ra vấn đề cần giải quyết là gì, và với tôi điều đó hữu ích hơn nhiều so với phần mở đầu được đề xuất để tự đánh giá mức độ quan tâm
  • Bài viết thú vị, và tôi hy vọng các tác giả đừng để ý những lời châm biếm ở đây mà cứ tiếp tục nghi thức hắc thuật của mình
    Tuy vậy, cá nhân tôi khi nhìn lên chiếc thang của sự thuần khiết trong lập trình thì Forth có lẽ là giới hạn độ thuần khiết triết học mà tôi chịu nổi
    • Là tác giả của bài này, tôi không bận tâm đến những lời châm biếm; trái lại còn thấy khá buồn cười nên hoan nghênh
      Chúng tôi dự định sẽ tiếp tục bàn về nhiều hắc thuật hơn nữa
  • Metaprogramming và programming là một
    Chỉ có điều hầu như mọi ngôn ngữ, kể cả tất cả các Lisp, đều xử lý quotation sai, và buồn cười là m4 lại là ngoại lệ

Lisp обход qua vấn đề này bằng macro, cho phép xử lý các câu lệnh của ngôn ngữ meta được biểu diễn bằng câu lệnh của ngôn ngữ đối tượng mà bỏ qua việc trích dẫn
Vấn đề này phát sinh từ việc cả ngôn ngữ đối tượng lẫn ngôn ngữ meta đều coi khoảng trắng là điểm kết thúc của nguyên tử, nhưng lại không phân biệt hai bên
Cách tiếp cận của Cognition, một loại phản cú pháp hoàn toàn hậu tố, trông giống các ngôn ngữ lập trình nối kết, nhưng ngôn ngữ hậu tố là đối ngẫu của ngôn ngữ tiền tố và gặp cùng vấn đề
Hoặc phải định trước số ngôi của mọi symbol và không dùng hàm bậc cao, hoặc cần một cặp dấu phân cách để có thể tuần tự hóa cây
Dựa vào stack bậc 0 ngầm định thì giống như phẫu thuật cắt thùy trán để chữa trầm cảm vậy

  • Cảm ơn phản hồi, nhưng nếu bạn chưa đọc toàn bộ bài thì nên đọc thử
    Chúng tôi cũng không biết mình đã tạo ra thứ mới đến mức nào, và nếu bạn nghĩ Lisp có thể làm được việc chúng tôi làm thì cứ chứng minh rằng chúng tôi sai
  • Tôi muốn xem ví dụ về việc trích dẫn khác nhau thế nào giữa Lisp và m4
    Bản thân lập luận thì thú vị, nhưng cần cụ thể hơn
  • Phép ví von về stack ngầm định nghe khá hoa mỹ, nhưng stack ngầm định đã có từ thời máy tính và máy tính bỏ túi đời đầu
    Cũng có thể xem việc quay lại cách nguyên thủy nhất để tính toán chuỗi lệnh là tương tự, giống như phẫu thuật cắt thùy trán làm giảm năng lực xử lý bậc cao
    https://www.hpmuseum.org/rpnvers.htm
  • Tôi thấy việc chương trình Cognition có thể định nghĩa và tái định nghĩa cấu trúc cú pháp trong lúc chạy, rồi đi vào và đi ra khỏi chúng, thật sự rất đẹp
    Đặc biệt tôi thích việc cơ chế đó rất nhỏ gọn
    Tôi không phải chuyên gia ngôn ngữ nên không biết nó có mới hay không, nhưng trong suốt lúc đọc bài, tôi cảm nhận được niềm vui của các tác giả khi mỗi lần vượt qua một ngọn đồi lại phát hiện ra cả một dãy núi khả năng mới
    Nếu tôi hiểu đúng, câu chuyện là với Cognition có thể thực sự tạo ra một cỗ máy biết suy nghĩ
    Chương trình không cần bị dừng rồi khởi động lại bằng lệnh mới; nó có thể tự viết và thực thi các subroutine mới dựa trên đầu vào mới
    Tức là chương trình có thể học và thích nghi bằng cách tạo ra các abstraction mới và kết nối với API mới
    Với tôi, hướng này thú vị hơn các mạng nơ-ron lớn hơn hay những kỹ thuật học mới
  • Tiền đề này không đúng
    Common Lisp có reader macro, nên bạn có thể thay đổi cú pháp tùy ý, và còn có cả compiler Fortran đọc cú pháp Fortran bằng reader macro
    Common Lisp có reader macro ở thời điểm đọc, macro, compiler macro ở thời điểm biên dịch, và tất cả các ngôn ngữ macro này đều là Common Lisp
    Metaprogramming không liên quan nhiều đến macro hay cú pháp, mà chỉ khả năng thao tác ngữ nghĩa và ý nghĩa của type, interface, class, method, v.v.
    Nếu bản thân CL chưa đủ mạnh cho việc đó thì có CLOS, tức Common Lisp Metaobject Protocol
    • Điều đang nói ở đây là reader macro của CL
      Với reader macro của CL, có thể dùng tokenizer khác, nhưng phải báo việc chuyển tokenizer bằng một biểu thức trong read table
      Trong Cognition, có vẻ như khi gọi một hàm thì tokenizer của ngữ cảnh caller thay đổi
  • Trông như một ví dụ thực dụng về việc bootstrap một cỗ máy tối thiểu thành interpreter của một ngôn ngữ cấp cao
    Lý do tôi được học rằng những việc như thế này với máy Turing hay lambda calculus là quan trọng, là để cho thấy ngôn ngữ cấp cao tương đương với ngôn ngữ nền tảng, từ đó những gì suy luận được về cái trước cũng có thể áp dụng cho cái sau
    Ví dụ đầu tiên và duy nhất tôi nghĩ đến là bài toán dừng
    Ở quy mô thực dụng, nếu chứng minh được ngôn ngữ cơ sở không bị rò rỉ bộ nhớ, liệu có thể nói các ngôn ngữ phái sinh cũng không bị rò rỉ không?
    Tôi tò mò việc bootstrap kiểu này có lợi ích gì
    Nếu câu trả lời đơn giản là kiểu leo Everest vì "nó ở đó", thì tôi cũng tôn trọng
  • Đến đoạn nói rằng khoảng trắng sau df, khoảng trắng ở dòng 3, và dấu xuống dòng là quan trọng, tôi lập tức "cảm ơn nhưng xin kiếu"
    Ba ký tự khoảng trắng ở cuối dòng trước biểu thị sự mỉa mai; ở những nơi không thể dễ dàng phân biệt khoảng trắng cuối dòng, cứ diễn giải theo nghĩa đen là được
    • Điểm chính của thí nghiệm này có vẻ là: Forth có một ký tự không thể tái định nghĩa, tức khoảng trắng, vậy nếu bỏ hạn chế đó thì sẽ ra sao
      Phần bootstrap được nhắc tới thực ra là đoạn nói với người đọc hãy coi khoảng trắng và xuống dòng là dấu phân cách
      Nói cách khác, bạn đang phàn nàn rằng khoảng trắng có ý nghĩa trong đoạn khai báo nó là dấu phân cách
      Tất nhiên bạn có quyền nghĩ vậy, nhưng tôi tự hỏi liệu có cách nào làm tốt hơn không
    • Những ký tự khoảng trắng đó là cách biến khoảng trắng, vốn trước đó không khác gì các ký tự khác, thành đúng thứ gọi là khoảng trắng
      Tôi không nghĩ ra cách nào làm được việc này mà không có một lần khoảng trắng literal mang ý nghĩa theo kiểu đó
  • Nói là "cái bẫy của việc có một dạng cú pháp nào đó", nhưng cú pháp cung cấp cấu trúc
    Bạn có nghĩ mình có thể đọc một câu như "sentence this without you syntax read can" mà không có cú pháp không?
    Cognition nói là dùng phản cú pháp hoàn toàn hậu tố, nhưng hậu tố cũng là cú pháp
    Cứ hỏi người nói tiếng Đức về động từ ở cuối câu là biết
    Ngay trong ví dụ đầu tiên, thứ tự của toán hạng và toán tử cũng quan trọng, và đó chính là cú pháp
    Đây có vẻ là một nỗ lực tạo ra một ngôn ngữ nén đến mức phi lý, khiến tôi nhớ nhiều đến APL
    Gợi ý cho các tác giả: các bạn không loại bỏ cú pháp, mà chỉ làm nó khó đọc và khó hiểu hơn đối với con người; khả năng đọc và khả năng hiểu là các yếu tố quan trọng trong lập trình
  • Đọc hơi vất vả
    Cảm giác như luật dưới chân cứ liên tục thay đổi, các luật và từ được đưa vào rồi bị tái định nghĩa tùy tiện
    Nhìn chung có vibe giống Numberwang, nên đó có vẻ là một trong những lý do nó được tiếp nhận như một tác phẩm châm biếm
    Một lý do lớn khác là giai đoạn bootstrap được viết đến mức buồn cười, mà có vẻ là có chủ ý
    Rõ ràng có điều gì đó sâu sắc ở đây, nhưng tôi sẽ phải đọc lại sau khi uống cà phê đậm hơn
    • Có rất nhiều thứ cần giải thích, và tôi cũng nghĩ cách giải thích hiện tại chưa tối ưu
      Tôi là tác giả bài này, vấn đề là có thật sự rất nhiều nội dung cần truyền đạt
      Tôi đã trao đổi với Matthew về thiết kế ngôn ngữ này vài giờ mỗi ngày trong suốt 3 tuần, và cũng có nhiều ngữ cảnh cần bổ sung cho những người thực sự không biết tôi