- Bộ chọn và khai báo CSS về mặt cấu trúc khá tương đồng với Datalog, ở chỗ chúng chọn ra một tập phần tử đã tồn tại và áp thuộc tính lên kết quả đó, giống như cách Datalog truy vấn quan hệ và tạo ra sự kiện
- CSS thông thường không hỗ trợ tính toán đệ quy dùng lại kết quả chọn làm điều kiện chọn tiếp theo, nên không thể trực tiếp biểu đạt việc trạng thái như theme dark lan truyền xuống hậu duệ rồi dừng lại ở ranh giới light
- Trong CSSLog giả định, ta cho phép thêm class ảnh hưởng đến việc khớp bộ chọn, nhờ đó có thể lan truyền đệ quy trạng thái suy ra như
.effectively-dark và lặp tính toán cho đến khi không còn kết quả mới
- Cách tính này được giải thích bằng fixpoint và monotonicity của Datalog; muốn việc đánh giá lặp kết thúc hữu hạn thì chỉ được thêm sự kiện mới chứ không được xóa sự kiện cũ
- Container queries của CSS thực tế cũng có thể đọc trạng thái của tổ tiên, nhưng không thể truy vấn trạng thái đệ quy đã được suy ra, nên dù CSS có tiến gần đến Datalog thì vẫn không vượt qua ranh giới của engine render trình duyệt
Tương ứng cơ bản giữa CSS và Datalog
- CSS giả định có sẵn các đối tượng đã tồn tại, và trong bài này các đối tượng đó là phần tử HTML
- Các phần tử như
h1, a, div đã tồn tại bên ngoài CSS; CSS không khai báo mới chúng
- Ví dụ đưa ra các phần tử có thuộc tính như
class, id, data-custom-attribute
- Bộ chọn CSS chỉ tới một tập có chung điều kiện, và có thể thu hẹp đối tượng bằng tên thẻ, id, class, giá trị thuộc tính
- Các bộ chọn như
div, #child, .awesome, [data-custom-attribute="foo"] xuất hiện làm ví dụ
- Cũng có thể biểu diễn đối tượng bằng quan hệ vị trí trong phân cấp tài liệu, và tạo giao bằng cách kết hợp bộ chọn
- Bộ chọn kết hợp như
div.awesome thực hiện phép giao tập hợp, chỉ chọn các phần tử vừa là div vừa có .awesome
- Khái niệm giao này về sau trở thành điểm then chốt tương ứng với join trong Datalog
- Quy tắc CSS gắn bộ chọn với khai báo để áp giá trị thuộc tính lên tập đã chọn
- Trong ví dụ
div.awesome { color: red; font-size: 24px }, color và font-size được đặt cho các phần tử đó
- Trên trình duyệt, kết quả là văn bản lớn màu đỏ được render
Giới hạn của CSS và bài toán truy vấn đệ quy
- CSS thông thường mạnh ở chỗ thay đổi thuộc tính nằm ngoài ngôn ngữ, nhưng không thể trực tiếp dùng kết quả thay đổi đó làm điều kiện chọn tiếp theo
- Ta có thể đặt màu cho phần tử, nhưng ví dụ như
div[color=red] dùng chính màu làm điều kiện bộ chọn sẽ bị trình duyệt từ chối
- Một quy tắc áp lại
color: blue lên phần tử đang có color: red sẽ trở nên mơ hồ về ý nghĩa
- Ví dụ dark mode trong design system được nêu như một bài toán cần lan truyền trạng thái bắc cầu
- Ta muốn áp viền focus màu trắng cho mọi phần tử tương tác bên trong một card có
data-theme="dark"
- Tuy nhiên, nếu ở giữa có
data-theme="light" thì việc lan truyền phải dừng ở bên dưới điểm đó
- Trong CSS thực tế, chỉ có thể xử lý một phần bằng cách chồng thêm các ngoại lệ
- Dùng
[data-theme="dark"] :focus { outline-color: white; } để tạo quy tắc cơ bản
- Và
[data-theme="dark"] [data-theme="light"] :focus { outline-color: black; } để đảo lại tại ranh giới light
- Nhưng cách này đòi hỏi phải tiếp tục thêm quy tắc khi độ lồng tăng lên
- Bài toán này cần định nghĩa quan hệ đệ quy, nhưng CSS không biểu đạt được điều đó
- Ta cần một định nghĩa kiểu “effectively-dark nếu bản thân nó là dark, hoặc có tổ tiên effectively-dark mà giữa chúng không có tổ tiên effectively-light”
- Bài gốc gọi đây là recursive relational definition và khẳng định CSS không thể biểu đạt nó
Cú pháp giả định của CSSLog
- CSSLog được đưa ra như một phiên bản giả định, vẫn giữ bộ chọn và thiết lập thuộc tính như CSS thường nhưng còn có thể thay đổi cả các thuộc tính ảnh hưởng đến việc khớp bộ chọn
- Ví dụ có cú pháp như
class: +bar để thêm class
- Cũng giả định có dạng như
+<div class="baz"> để tạo phần tử con mới
- Việc xóa phần tử chỉ được nói là “có lẽ không nên được phép”, không có giải thích thêm
- Sau khi quy tắc
div.foo chạy, cùng phần tử đó có thể bắt đầu khớp cả div.bar, nghĩa là kết quả thực thi quy tắc ảnh hưởng đến lần khớp tiếp theo
- Từ điểm này, tính toán không còn kết thúc bằng một lượt áp xuôi duy nhất mà cần lặp
- Khi chuyển ví dụ dark mode sang CSSLog, ta có thể lan truyền đệ quy class suy ra
- Bắt đầu với
[data-theme="dark"] { class: +effectively-dark; }
- Lan sang phần tử con bằng
.effectively-dark > :not([data-theme="light"]) { class: +effectively-dark; }
- Và áp style cuối cùng bằng
.effectively-dark :focus { outline-color: white; }
- Quy tắc thứ hai được mô tả là lan truyền đệ quy cho đến ranh giới light, rồi dừng khi đạt tới trạng thái mong muốn
- Bài gốc nói rõ rằng CSS hiện tại không thể làm được việc này, và ở cuối bài sẽ quay lại một vài cách lách gần giống
Cấu trúc của Datalog và sự giống nhau với CSS
- Trong Datalog, các đối tượng được gọi là atom, và chúng tồn tại ngay từ lúc được nhắc tới
- Các tên như
alice, bob có thể dùng trực tiếp mà không cần khai báo riêng
- Có một câu so sánh kèm theo với
:symbols của Ruby
- Tập hợp và quan hệ được biểu diễn bằng relations và tuples
parent(alice, bob) là một tuple trong quan hệ parent
parent được mô tả là tập các cặp “đối tượng thứ nhất là cha/mẹ của đối tượng thứ hai”
- Biến được dùng cho khớp truy vấn và chọn tập
parent(bob, X) nghĩa là mọi X mà Bob là cha/mẹ
- Trong ví dụ này,
X được đánh giá thành carol và dave
- Theo quy ước, biến viết hoa còn atom và relation viết thường
- Khi cùng một tên biến lặp lại, sẽ có join
mother(X, Y) :- parent(X, Y), woman(X). tạo quan hệ mẹ từ giao của tập cha mẹ và tập phụ nữ
- Bài viết giải thích đây là giao giữa “mọi phụ huynh” và “mọi phụ nữ”
:- trong quy tắc Datalog được đọc là if; khi mọi điều kiện ở phần thân bên phải đều đúng thì sự kiện ở phần đầu bên trái sẽ được thêm là đúng
- Dấu phẩy trong body được đọc là and
ancestor(X, Y) :- parent(X, Y). có nghĩa là nếu X là cha/mẹ của Y thì X là tổ tiên của Y
- CSS và Datalog được so sánh là có cấu trúc tương tự nhưng đảo chiều hình thức
color(X, red) :- div(X), class(X, awesome). tương ứng với “màu của X là đỏ nếu X là div và có class awesome”
- Nó được đối chiếu về nghĩa với CSS
div.awesome { color: red; }
- Bài gốc tóm lại rằng selector là body còn declaration là head
Đệ quy và sự kiện suy ra
- Trong Datalog, “làm” một điều gì đó có nghĩa là suy ra sự kiện mới
- Hệ thống hoạt động bằng cách thêm tuple mới vào quan hệ dựa trên các sự kiện hiện có
- Ví dụ
ancestor là hình mẫu điển hình của quy tắc đệ quy
ancestor(X, Y) :- parent(X, Y). biến quan hệ cha/mẹ trực tiếp thành quan hệ tổ tiên
ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y). mở rộng lên phía trên theo quan hệ tổ tiên của cha/mẹ
- Quy tắc thứ hai chứa đệ quy tự tham chiếu vì
ancestor xuất hiện ở cả head lẫn body
- Từ quy tắc này, các quan hệ tổ tiên gián tiếp như
alice -> bob -> carol, alice -> bob -> dave được suy ra
- Kết quả chạy ví dụ đưa ra năm sự kiện sau
ancestor(alice, bob)
ancestor(bob, carol)
ancestor(bob, dave)
ancestor(alice, carol)
ancestor(alice, dave)
- SQL trước
WITH RECURSIVE cũng không làm được loại tính toán này; bài viết nói tính năng đó xuất hiện vì nhu cầu tính toán đệ quy
- Tuy vậy, bài gốc cũng nói cú pháp và ngữ nghĩa đệ quy của SQL không phải lúc nào cũng kết hợp tốt với các phần khác
- Datalog không cần
for loop mà engine vẫn tiếp tục tính cho đến khi mọi kết quả cần thiết đều xuất hiện
- Phần tiếp theo nối điều này với khái niệm fixpoint
Fixpoint và tính đơn điệu
- Cascade của CSS thông thường được mô tả là một lượt áp xuôi duy nhất
- Trình duyệt đọc quy tắc, tính khớp selector, áp declaration rồi kết thúc
- Không có vòng phản hồi
- Trong CSSLog và Datalog thực tế, kết quả của quy tắc có thể lại thỏa điều kiện của quy tắc khác
- Một quy tắc thay đổi thuộc tính, thuộc tính đó khiến quy tắc khác chạy lại, rồi lại ảnh hưởng về quy tắc đầu tiên
- Một engine Datalog ngây thơ sẽ lặp áp quy tắc cho đến khi không còn sự kiện mới
- Bắt đầu từ các base fact đã khai báo
- Khớp body của mọi quy tắc với tập sự kiện hiện tại
- Nếu khớp thì thêm sự kiện ở head
- Có sự kiện mới thì lặp lại, không có thì dừng
- Điểm dừng này được gọi là fixpoint
- Tức là trạng thái mà áp lại mọi quy tắc cũng không tạo ra kết quả mới
- Ví dụ
ancestor được tóm tắt thành ba vòng
- Ở vòng đầu, ba quan hệ tổ tiên trực tiếp được thêm từ các sự kiện
parent
- Ở vòng hai, hai quan hệ tổ tiên gián tiếp của
alice được thêm vào
- Ở vòng ba, không còn sự kiện mới nên đạt fixpoint
- Lý do có thể kết thúc nằm ở monotonicity
- Vì không xóa sự kiện mà chỉ thêm vào, tập sự kiện đã biết chỉ có thể lớn dần
- Với tập sự kiện ban đầu hữu hạn và số khả năng suy ra hữu hạn, hệ thống sẽ dừng sau hữu hạn bước
- Ngược lại, nếu cho phép xóa sự kiện, ta sẽ có tình huống kết quả về sau lật ngược kết quả trước đó, và tính chất này bị phá vỡ
- Bài gốc gọi đó là Infinite Loop Land, và từ đó liên hệ rằng tốt hơn CSSLog không nên cho phép xóa phần tử
- Bài còn chú thích thêm rằng trong hệ phân tán, monotonicity cũng liên quan đến khả năng đạt nhất quán mà không cần điều phối tốn kém
Vì sao điều này quan trọng
- Việc so sánh CSS với Datalog cho thấy cùng một cấu trúc trong những lĩnh vực khác nhau
- Cả hai đều có đối tượng, có cách truy vấn tập các đối tượng đó, rồi áp một điều gì đó hoặc tạo ra sự kiện mới từ kết quả
- Datalog và Prolog đã xuất hiện từ thập niên 1970 trong cơ sở dữ liệu quan hệ và nghiên cứu AI thời kỳ đầu, rồi sau đó được tái tạo dưới nhiều hình thức khác nhau
- Bài viết đưa ra nhận xét rằng nếu xây dựng một hệ thống có đối tượng, mô tả được tập hợp và làm được việc gì đó với các đối tượng đó, nó sẽ có xu hướng hội tụ về những điểm tương tự
- Lĩnh vực cơ sở dữ liệu, logic programming và phát triển web frontend không thường xuyên được kết nối với nhau
- Bài viết bày tỏ kỳ vọng rằng nếu chúng được kết nối nhiều hơn, có thể tạo ra điều gì đó mới
Container Queries và ranh giới của CSS thực tế
- Thảo luận này cũng chạm tới tính năng CSS thực tế là Container Queries
- Ta có thể áp style cho phần tử hiện tại dựa trên style của phần tử cha hoặc tổ tiên
- Ví dụ được đưa ra là
@container style(--theme: dark) { .card { background: royalblue; color: white; } }
- Tuy nhiên, bài toán dark mode bắc cầu cần một phép tính mạnh hơn việc chỉ nhìn tổ tiên
- Mỗi phần tử phải biết liệu chính nó có effectively dark hay không
- Trạng thái đó phải lan truyền bắc cầu xuống hậu duệ
- Và phải dừng lại ở ranh giới
data-theme="light"
- Container queries không thể đọc trạng thái suy ra
- Ta có thể truy vấn giá trị custom property của tổ tiên, nhưng không thể hỏi trạng thái như effectively-dark đã được quy tắc khác tính sẵn
- Nó chỉ đọc được trạng thái đã có trong DOM, chứ không thấy kết quả của tính toán đệ quy
- Vì vậy, các truy vấn kiểu “áp dụng nếu có tổ tiên nào đó là dark theo quan hệ bắc cầu, và không có tổ tiên light gần hơn” là không thể triển khai vì cần đệ quy
- Bài gốc nói rõ rằng container queries không có đệ quy
- Bài viết năm 2015 nói về lý do element queries liên tục thất bại vì nguyên nhân tương tự
- Nếu cho phép truy vấn lại thuộc tính mà truy vấn đó vừa thiết lập, có thể phát sinh loop, thậm chí vòng lặp vô hạn
- CSS Working Group được mô tả là đã giải loại vấn đề này bằng việc giới hạn hướng luồng thông tin
- Hậu duệ có thể truy vấn thông tin của tổ tiên nhưng chiều ngược lại thì không được phép
- Nhờ vậy vẫn giữ được tính hữu hạn mà không cần ngữ nghĩa fixpoint
- Thông tin chỉ lan theo chiều đi xuống của cây và không tạo thêm base fact mới
- Bài gốc mô tả dòng tiến hóa này như việc CSS tiến gần đến một Datalog engine nhưng cố ý không đi đến tận đó
- CSSLog đứng về phía cho phép chu trình và đánh giá đến fixpoint
- Còn CSS thực tế dừng lại ở chỗ nó là engine render của trình duyệt chứ không phải incremental relational database engine
Khả năng theo hướng khác
- Thay vì đưa ngữ nghĩa Datalog vào trình duyệt, ta cũng có thể đi theo hướng đặt cú pháp kiểu CSS lên trên Datalog
- Cú pháp Datalog như
:-, dấu chấm câu, quy ước chữ hoa chữ thường, hay việc không có câu lệnh gán, có thể là rào cản với người dùng ngôn ngữ hiện đại
- CSS vốn đã có một cú pháp xử lý trực tiếp cấu trúc cây
- Nó có các combinator hậu duệ, con trực tiếp, anh chị em, nên biểu diễn quan hệ cha-con rất tự nhiên
- Trong Datalog thông thường, các cấu trúc này thường phải được mã hóa sang dạng quan hệ theo cách hơi rườm rà
- Bài viết nhấn mạnh rằng rất nhiều dữ liệu thực tế có dạng cây
- JSON
- AST
- Hệ thống tệp
- Sơ đồ tổ chức
- XML
- Nếu có một công cụ kết hợp đệ quy fixpoint, cú pháp kiểu CSS và quan hệ cha-con ngầm định, ta sẽ có thể viết truy vấn cây đệ quy bằng một ký pháp quen thuộc hơn
- Theo bài gốc, dường như vẫn chưa ai thực sự tạo ra một công cụ như vậy
- Bài khép lại bằng ý rằng có lẽ ai đó nên làm một thứ kiểu “CSSLog”, với một cái tên hay hơn
Chú thích
- Có một chú thích về việc đơn giản hóa phần tử HTML
- Tác giả lường trước phản biện rằng đối tượng CSS xử lý không nhất thiết chỉ là phần tử HTML, nhưng trong bài dùng phần tử HTML để đơn giản hóa giải thích
- naive evaluation là không hiệu quả vì ở mỗi lần lặp lại tính cả những sự kiện đã biết
- Cách cải tiến tiêu chuẩn được nhắc tới là semi-naive evaluation
- Điểm chính là ở mỗi bước chỉ xét các sự kiện mới được suy ra
- Bài cũng nói thêm rằng bản thân vòng lặp vô hạn không phải chuyện lạ với ngôn ngữ Turing-complete
- Trong JavaScript ta cũng có thể viết
while true {}
- Nhưng trong ngữ cảnh hệ thống render của trình duyệt, ta muốn tránh việc trình duyệt treo vĩnh viễn chỉ vì logic của một website bị rối
- Một chú thích khác bàn về cách lách bằng custom property inheritance trong CSS
[data-theme="dark"] { --effective-theme: dark; }
[data-theme="light"] { --effective-theme: light; }
@container style(--effective-theme: dark) { :focus { outline-color: white; } }
- Cách này nhìn chung hoạt động cho trường hợp cụ thể này, nhưng cơ chế kế thừa không giống với transitive closure thực sự
- Với các bài toán phức tạp hơn cần transitive closure dọc theo chuỗi thuộc tính khác ngoài cha-con, nó sẽ bị phá vỡ
1 bình luận
Ý kiến trên Hacker News
Bộ chọn CSS dễ viết hơn XPath rất nhiều
Gần đây cũng có một bài nói về việc API DOM mới của PHP cho phép xử lý HTML và bộ chọn CSS một cách native rất dễ dàng. Trước đây phải chuyển CSS sang XPath
[1] https://speakerdeck.com/keyvan/parsing-html-with-php-8-dot-4...
Vì nó đã phát triển xoay quanh việc tạo kiểu cho trình duyệt, nên khá tiếc là không có các tính năng như chọn dựa trên nội dung văn bản kiểu XPath
Tôi nhớ là trước đây đã từng có đề xuất, nhưng do có thể gây ra vấn đề hiệu năng trong ngữ cảnh render của trình duyệt nên không được đưa vào đặc tả
Khi làm một agent chỉnh sửa tài liệu, tôi hiển thị tài liệu dưới dạng HTML và để LLM chỉ định CSS selector để kéo những mảnh cần thiết vào ngữ cảnh, và nó hoạt động gần như kỳ diệu
Mọi người có thể dùng đúng theo cách quen thuộc của mình
Sẽ hay hơn nếu có một cái tên để gọi tách biệt giữa cú pháp CSS và toàn bộ hệ thống gồm quy tắc, hàm, đơn vị... do CSSWG định nghĩa
Mảng này có khá nhiều tiềm năng, nhưng nếu muốn bàn hoặc tìm hiểu các trường hợp ứng dụng khác thì có vẻ cuối cùng vẫn chỉ còn cách lục mã trên GitHub có nhúng parser CSS để xem mọi người đang làm ra những thứ kỳ lạ nào
Tôi cũng đang nghịch một thứ giống engine template kỳ quặc, trộn giữa một ngôn ngữ markup nhẹ dựa trên node, bộ chọn CSS để biểu đạt thứ gì sẽ đi vào template, và một cú pháp na ná CSS để điều khiển cách ghép các mảnh này lại với nhau
https://www.w3.org/TR/selectors-3/
Đặc tả DOM cũng tham chiếu tới nó
https://dom.spec.whatwg.org/#selectors
Vì vậy cách gọi chung CSS selector đã là đúng sẵn rồi, hoặc chỉ gọi là selector cũng được
Tên DOM selector có thể nghe gọn hơn, nhưng nếu tính cả selector dùng trong CSS tĩnh hay trong các engine DOM khác ngoài JS engine (XML parser, PHP DOM API, v.v.) thì ngược lại có thể còn gây rối hơn
Ngoài ra cũng có những selector đặc biệt gắn trực tiếp với việc render/điều hướng của trình duyệt như
:hoverhay::target-textTuy vậy, sẽ hữu ích nếu có một tên riêng cho tập con cú pháp truy vấn tối thiểu ít gắn với trình duyệt hoặc CSS hơn
Tôi nhớ tới https://github.com/braposo/graphql-css mà tôi từng thấy ở một hội nghị trước đây
Dù là một dự án đùa vui, nó cho thấy rất rõ rằng việc mang một pattern sang ngữ cảnh khác rồi tái sử dụng có thể mở ra những điều bất ngờ
Tôi đúng là đang thử mang pattern giữa các ngữ cảnh khác nhau theo kiểu như vậy
Dù phần lớn sẽ chẳng đi đến đâu, nhưng theo tinh thần hacker thì khá là hấp dẫn
pyastgrep như ở https://pyastgrep.readthedocs.io/en/latest/ cho phép dùng bộ chọn CSS để truy vấn cú pháp Python
Mặc định là XPath, ví dụ có thể dùng như
pyastgrep --css 'Call > func > Name#main'Nó gần như chạm đúng chính xác hướng mà tôi muốn chỉ tới
Tôi không rõ thứ này giải quyết kịch bản nào
Ngay bây giờ cũng đã có thể thay đổi cha một cách có điều kiện dựa trên con. Ví dụ
precó padding mặc định là 16px, và nếu con trực tiếp làcodethì có thể dùng&:has(> code)để đưa về 0Kết luận cũng không phải là "phải sửa giới hạn của CSS hiện đại", mà gần hơn với việc liệu có thể đặt một cú pháp giống CSS lên trên một hệ thống giống Datalog để khiến việc làm việc với dữ liệu dạng cây trở nên quen thuộc hơn với nhiều kỹ sư hay không
Tức là đang nói tới chuyện thêm phần tử con hoặc thuộc tính mới vào DOM
LLM hiện tại thật ra không giỏi xử lý CSS lắm, nên ngược lại tôi lại muốn thử việc này để xem liệu nó có giúp LLM suy luận đơn giản hơn không
Chưa nghĩ ra giá trị sử dụng thực tế nào rõ ràng, nhưng dù sao vẫn ngầu
Ừm... tôi thấy cái này chẳng phải chỉ là JQ sao
Tôi có thích CSS ở một mức độ nào đó, nhưng ghét việc complexity creep ngày càng nặng
Tôi hiểu lập luận rằng ngôn ngữ lập trình sẽ mạnh hơn ngôn ngữ không phải lập trình, nhưng thay vì cứ tiếp tục làm HTML, CSS và JavaScript ngày càng phức tạp hơn, tôi cảm thấy thà có một thứ khác thay thế toàn bộ còn hơn
Tôi cũng gần như không dùng các phần tử mới của HTML5 vì phần lớn tôi không hiểu chúng cần để làm gì. Cuối cùng tôi lại nghĩ nhiều container chỉ đơn giản là
divcó ID riêng, thậm chí còn từng muốn có một kiểu bí danh cho các ID đó để điều hướnghrefnội bộNhững thứ như
[data-theme="dark"] [data-theme="light"] :focus { outline-color: black; }làm tôi mất quá nhiều thời gian để diễn giải trong đầu nên tôi không còn thấy nó thanh lịch và đơn giản nữaTrong khi đó
h2 { color: red; }thì vẫn đơn giảnNhững biểu thức như
ancestor(X, Y) :- parent(X, Y).thì tôi đã không muốn nghĩ tới rồi.:-rốt cuộc là cái gì vậy, nhìn như mặt cườiTôi đã dừng đọc ở
@container style(--theme: dark) { .card { background: royalblue; color: white; } }Thật kỳ lạ khi một tiêu chuẩn từng hoạt động tốt lại có vẻ như ngày càng trở nên hỏng hóc theo thời gian
Ví dụ, nếu diễn giải
[data-theme="dark"] [data-theme="light"] :focus { outline-color: black; }thành giả mã kiểu tiếng Anh, thì nó gần với ý: nếu có X vớidata-theme="dark", và con của nó là Y vớidata-theme="light"đang ở trạng thái focus, thì đặtoutline-colorcủa Y thành blackVì vậy có thể viết kiểu Datalog là
outline-color(Y, black) if data-theme(X, "dark") and parent(X, Y) and data-theme(Y, "light") and focused(Y)Tức là thay
:-bằngif, và dấu phẩy bằngandĐi xa hơn nữa, cũng có thể viết như
Y.outline_color := black if X.data-theme == dark and Y.parent == X and Y.data-theme == dark and Y.focusedđể làm choattr(X, val)trông giống syntactic sugar kiểu UFCS nhưX.attr == valNếu muốn trông giống họ ALGOL hơn nữa thì cũng có thể viết như
forall Y { Y.outline_color := black if Y.data_theme == "dark" and Y.focused and Y.parent.data_theme == "light" }Ở đây Y được đưa vào một cách tường minh và một phép join được ngầm hóa để trông giống lập trình phổ thông hơn, nhưng trên thực tế, engine Datalog chỉ đang chạy kiểu vòng lặp này một cách hiệu quả mỗi khi phụ thuộc thay đổi thôi`