1 puan yazan GN⁺ 4 일 전 | 1 yorum | WhatsApp'ta paylaş
  • Seçiciler ve kurallar ile hedef kümesini seçip özellik uygulayan CSS yapısı, kümeler ve kurallarla çalışan Datalog ile biçimsel olarak benzeşir
  • div.awesome gibi seçici birleşimleri bir kesişim oluşturur; Datalog'da ise aynı değişkeni tekrar etme yoluyla benzer bir join gerçekleşir
  • Günümüz CSS'i, hesaplanmış stil sonucunu tekrar seçim koşulu olarak kullanamadığı için özyineli geçişli sorguları ya da türetilmiş durumların yinelemeli yayılımını doğrudan ifade etmekte zorlanır
  • Datalog, özyineli kurallar ve sabit nokta değerlendirmesi ile yeni olgular artık üretilmeyene kadar ilişkileri genişletir; monotonluk sayesinde sonlu bir kapsamda hesaplamayı tamamlayabilir
  • Gerçek CSS, Container Queries gibi özelliklerle ata bilgisini okuyabilir; ancak geri besleme döngülerini ve çevrimleri engelleme yönünü seçmiştir, buna rağmen CSS sözdizimini özyineli sorgulara uyarlamak için alan hâlâ vardır

CSS ve Datalog'un benzer yapısı

  • CSS, hedef kümesini seçme ve seçilen hedefe kural uygulama yapısına sahiptir
    • HTML öğeleri gibi "Things" önce var olur ve selector ortak özelliklere sahip kümeyi gösterir
    • div, #child, .awesome, [data-custom-attribute="foo"] gibi selector'larla kümeler tanımlanabilir
    • div.awesome gibi selector'lar birleştirilerek kesişim oluşturulabilir
  • CSS kuralları, selector ve declaration'ı bir araya getirerek seçilen öğelerde color veya font-size gibi özellikleri ayarlar
    • Ancak bu özellikler çoğunlukla dilin dışındaki durumu değiştirir ve bu sonucu tekrar selector koşulu hâline getiremez
    • div[color=red] gibi stil sonucunu yeniden sorgulayan bir biçimi tarayıcı kabul etmez
  • Datalog da benzer şekilde olgu kümesi ve kurala dayalı türetim ile çalışır
    • parent(alice, bob) gibi atomlar ve relation'lar temel birimi oluşturur
    • X, Y değişkenleri kullanılarak koşula uyan öğe kümeleri seçilebilir
    • Aynı değişken tekrar edilerek koşullar bağlandığında, CSS'teki selector birleşimine benzer bir join oluşur
  • head(X, Y) :- body1(X, Z), body2(Z, Y) yapısı, yönü ters olsa da CSS kuralına biçimsel olarak benzer
    • CSS'teki selector, Datalog'un body kısmına daha yakındır; declaration ise head'e daha yakındır
    • div.awesome { color: red; }, color(X, red) :- div(X), class(X, awesome). ile eşleşir

CSS'in yapamadığı özyineli sorgular

  • data-theme="dark" içindeki tüm odaklanmış öğelere ters stil uygulamak, ama arada data-theme="light" çıkarsa durmak koşulu bir geçişli sorgu gerektirir
    • Gerçek CSS'te bu durum [data-theme="dark"] :focus ve [data-theme="dark"] [data-theme="light"] :focus gibi kurallarla ancak kısmen ele alınabilir
    • İç içe seviye arttıkça yeni kurallar eklemek gerekir; özyineli ilişkiyi doğrudan ifade etmek zordur
  • Gerekli olan koşul, bir öğenin effectively-dark olup olmadığını özyineli biçimde belirlemektir
    • Kendisi data-theme="dark" ise effectively-dark olur
    • effectively-dark bir atanın altındaki çocuk da, arada data-theme="light" yoksa effectively-dark olur
    • Bu duruma dayanarak .effectively-dark :focus için stil uygulanmalıdır
  • Varsayımsal CSSLog sözdiziminde kurallar, class: +effectively-dark gibi türetilmiş durum ekleyebilir
    • .effectively-dark > :not([data-theme="light"]) çocuğa durumu yayar
    • Kurallar, hedef duruma ulaşılana kadar özyineli olarak tekrar uygulanmalıdır
  • Bu tür özyineli yayılımı günümüz CSS'iyle ifade etmek zordur
    • Yazının sonunda buna kısmen benzeyen bazı taklit yöntemler de verilir, ancak bunlar aynı ilkenin genel çözümü değildir

Datalog'da özyineleme ve sabit nokta

  • Datalog, mevcut olgulardan yeni olgular türetme biçiminde çalışır ve özyinelemeyi doğal olarak ele alır
    • ancestor(X, Y) :- parent(X, Y).
    • ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
  • ancestor kuralı, ebeveyn ilişkisine dayanarak ata ilişkisini adım adım genişletir
    • parent(alice, bob) üzerinden önce ancestor(alice, bob) oluşur
    • Ardından alice -> bob -> carol, alice -> bob -> dave gibi yollar da ek olarak türetilir
  • Bu hesaplama, açık bir for döngüsü olmadan bile sabit nokta değerlendirmesi ile sona kadar ilerler
    • Başta yalnızca tanımlanmış temel olgular kullanılır
    • Tüm kuralların body kısmı mevcut olgu kümesine uygulanır ve head kısmı eklenir
    • Yeni olgu artık üretilmeyince durur
  • Bu yaklaşımın sonlanma nedeni monotonluktur
    • Olgular sadece eklenir, kaldırılmaz; bu yüzden bilinen olgu kümesi sürekli büyür
    • Sonlu bir olgu kümesinden başlanırsa, türetilebilir olgu sayısı da sonlu kalır
    • Tersine, olgular kaldırılabilseydi önceki sonuçlar tersine dönebilir ve sonsuz döngü oluşabilirdi

Container Queries ve gerçek CSS'in sınırları

  • Gerçek CSS'teki Container Queries, kural uygulamak için ata ya da container stilini ölçüt alabilir
    • @container style(--theme: dark) { .card { background: royalblue; color: white; } } gibi yapıları destekler
  • Ancak geçişli dark mode örneği, basit ata sorgulamasından daha güçlü bir koşul gerektirir
    • Her öğenin kendisinin effectively-dark olup olmadığını bilmesi gerekir
    • Bu durumun tüm alt soya geçişli olarak yayılması gerekir
    • Yayılım, data-theme="light" sınırında durmalıdır
  • Container Queries ikinci koşulu karşılayamaz
    • Atanın custom property değerini okuyabilir, ama başka kuralların önceden hesapladığı türetilmiş durumu yeniden sorgulayamaz
    • DOM'da baştan var olan bilgiyi görebilir, ancak özyineli hesaplama sonucunu selector koşulu yapamaz
  • 2015 tarihli ilgili yazı da element queries'in aynı soruna çarptığını belirtir
    • Sorguyla ayarlanan özelliğin tekrar sorgulanabilmesi, döngü ve sonsuz tekrar riskini büyütür
  • CSS Working Group, bu sorundan bilgi akış yönünü sınırlayarak kaçınmıştır
    • Alt soyun ata bilgisini sorgulamasına izin verir
    • Ters yöndeki geri beslemeyi ya da öğenin kendi stiline dönen çevrimi engeller
    • Böylece sabit nokta semantiği olmadan da hesaplamayı sonlu tutar

CSS sözdizimini özyineli sorgu diline çevirebilme olasılığı

  • Datalog semantiğini CSS'e yerleştirmektense, CSS sözdizimini Datalog üzerine kurmak daha gerçekçi yeni bir yol olarak sunuluyor
    • Datalog'un :-, nokta ve deklarasyonsuz atomlar gibi sözdizimi, modern dil kullanıcıları için yüksek bir giriş eşiği oluşturur
    • CSS ise zaten ağaç yapılarıyla çalışmak için zengin bir selector sözdizimine sahiptir
  • Gerçek verilerin önemli bir kısmının ağaç biçimli olduğuna dikkat çekiliyor
    • JSON
    • AST
    • dosya sistemi
    • organizasyon şeması
    • XML
  • Bu alanlarda ebeveyn/çocuk ilişkilerini örtük olarak ele alan CSS benzeri sözdizimi ile sabit noktalı özyineleme birleştirildiğinde yararlı olabilir
    • Genel Datalog'da ağaç yapısını ilişkisel gösterime çevirmek gerektiğinden kullanım zahmetlidir
    • CSS selector sezgisini doğrudan özyineli sorgulara taşımak, daha fazla programcının buna kolayca yaklaşmasını sağlayabilir
  • Bu tür bir araç henüz belirgin biçimde görünmüyor
    • "CSSLog" adı geçici bir ad ve daha iyi isimli bir dil ortaya çıkabilir
    • Özyineli ağaç sorgularını daha tanıdık bir gösterimle ele alma alanı hâlâ açık

Ek noktalar ve referans bağlantıları

  • Datalog, 1970'lerden beri ilişkisel veritabanları ve dönemin yapay zeka araştırmaları bağlamında ortaya çıktı; sonrasında da farklı biçimlerde tekrar tekrar geri döndü
  • Sabit nokta hesaplamasının basit biçimi naive evaluation olarak tanıtılır; ancak her seferinde zaten bilinen olguları yeniden hesapladığı için verimsiz olabilir
    • Her adımda yalnızca yeni üretilen olguları kullanan semi-naive evaluation, tipik bir iyileştirme yönü olarak ayrıca anılır
  • Monotonluk, dağıtık sistemlerde de faydalı özellikler sağlar
  • custom property kalıtımıyla geçişli dark mode'u kısmen taklit etmenin bir yolu da vardır
    • [data-theme="dark"] { --effective-theme: dark; }
    • [data-theme="light"] { --effective-theme: light; }
    • @container style(--effective-theme: dark) { :focus { outline-color: white; } }
    • Bu yöntem bu özel durumda çoğunlukla çalışsa da, genel anlamda gerçek geçişli kapanış sağlamaz

1 yorum

 
GN⁺ 4 일 전
Hacker News görüşleri
  • CSS seçicileri, XPath'a göre çok daha kolay yazılıyor
    Kısa süre önce de PHP'nin yeni DOM API'sinin HTML ve CSS seçicilerini yerel olarak çok kolay ele alabildiğini anlatan bir sunum yapılmıştı. Eskiden CSS'yi XPath'e dönüştürmek gerekiyordu
    [1] https://speakerdeck.com/keyvan/parsing-html-with-php-8-dot-4...
    Tarayıcı stil verme odağıyla geliştiği için, XPath'teki gibi metin içeriğine göre seçim gibi özelliklerin olmaması üzücü
    Bildiğim kadarıyla geçmişte öneriler oldu ama tarayıcıların render bağlamında performans sorunları yaratabileceği için spesifikasyona giremedi

    • LLM'ler de CSS seçicileriyle epey iyi çalışıyor
      Belge düzenleme ajanı yaparken belgeyi HTML olarak gösterip LLM'in yalnızca CSS selector belirleyerek gerekli parçaları bağlama çekmesini sağladım; neredeyse sihir gibi iyi çalıştı
    • İstemci tarafında querySelector/querySelectorAll zaten çok yaygın kullanıldığı için, artık PHP'nin yeni DOM'una da bunun gelmiş olması sevindirici
      İnsanlar alışık oldukları yöntemi aynen kullanabiliyor
  • CSS sözdizimi ile CSSWG'nin tanımladığı kurallar, fonksiyonlar ve birimler gibi tüm sistemi ayırarak adlandırmak için bir isim olsa iyi olurdu
    Burada epey potansiyel var ama başka kullanım örneklerini konuşmak ya da araştırmak isteyince, sonunda CSS ayrıştırıcısı kullanan GitHub kodlarını kurcalayıp insanların ne tür garip şeyler yaptığını görmekten başka çare yok gibi duruyor
    Hafif bir düğüm tabanlı işaretleme dili, şablona neyin gireceğini ifade eden CSS seçicileri ve bu parçaların nasıl birleştirileceğini kontrol eden CSS benzeri bir sözdizimini karıştıran tuhaf bir şablon motoru benzeri şeylerle de oynuyorum

    • Bence standartlarda ayrım zaten oldukça net
      https://www.w3.org/TR/selectors-3/
      DOM spesifikasyonu da buna referans veriyor
      https://dom.spec.whatwg.org/#selectors
      Bu yüzden genel ad olarak CSS selector zaten doğru; hatta sadece selector da denebilir
      DOM selector adı daha derli toplu görünebilir ama statik CSS'te kullanılan seçicileri ya da JS motoru dışındaki başka DOM motorlarında (XML parser, PHP DOM API vb.) kullanılan seçicileri de düşününce, aslında daha da kafa karıştırıcı olabilir
      Ayrıca :hover ya da ::target-text gibi doğrudan tarayıcı render etme/gezinme davranışına bağlı özel seçiciler de var
      Yine de tarayıcıya ya da CSS'e daha az bağlı olan asgari sorgu sözdizimi altkümesi için ayrı bir isim faydalı olabilir
  • Eskiden bir konferansta gördüğüm https://github.com/braposo/graphql-css aklıma geldi
    Şaka amaçlı bir projeydi ama kalıpları başka bağlamlara taşıyıp yeniden kullanmanın beklenmedik şeyleri mümkün kıldığını iyi göstermesi hoşuma gitmişti

    • Bu ilginçmiş
      Ben de tam böyle, farklı bağlamlardaki kalıpları alıp kullanmayı deniyorum
      Çoğu çok ileri gitmese de hacker ruhu açısından oldukça ilgi çekici
  • pyastgrep, https://pyastgrep.readthedocs.io/en/latest/ adresinde görüldüğü gibi Python sözdizimini sorgularken CSS seçicileri kullanabiliyor
    Varsayılanı XPath; örneğin pyastgrep --css 'Call > func > Name#main' gibi kullanılabiliyor

    • Bu gerçekten çok iyiymiş
      Anlatmak istediğim yönle neredeyse tam olarak örtüşüyor
  • Bunun hangi senaryoyu çözdüğünü pek anlamadım
    Şu anda da çocuğa göre ebeveyni koşullu olarak değiştirebiliyorsunuz. Mesela pre için varsayılan padding 16px ise ve doğrudan çocuğu code ise, &:has(> code) ile bunu 0 yapabilirsiniz

    • Aslında bu ilk başta iki farklı fikrin birbirine benzemesiyle başladı; daha çok o bağlantıyı çeşitli yönlere doğru zorlamaya çalışmak gibi
      Sonuç da "modern CSS'nin sınırlarını düzeltmeliyiz"den çok, CSS benzeri bir sözdizimini Datalog benzeri bir sistemin üstüne koymanın ağaç biçimli verilerle çalışmayı daha fazla mühendis için tanıdık hale getirip getiremeyeceğine yakın
    • Burada kastedilen şey tek seferlik bir stil hesaplamasıyla çözmek değil; seçiciye eşleşen hedeflerin temel verisinin kendisini değiştiren bir sözdizimi
      Yani DOM'a yeni alt öğeler ya da nitelikler eklemekten söz ediliyor
  • Günümüz LLM'leri CSS ile çok da iyi değil; bu yüzden bunu deneyince LLM'in daha basit şekilde akıl yürütüp yürütemeyeceğini görmek istiyorum

  • Gerçek bir faydası hemen aklıma gelmiyor ama yine de havalı

  • Hmm... Bu aslında sadece JQ değil mi?

  • CSS'yi belli ölçüde seviyorum ama karmaşıklığın sürünerek artması giderek canımı sıkıyor
    Programlama dillerinin programlama dışı dillere göre daha güçlü hale gelmesi mantığını anlıyorum ama HTML, CSS ve JavaScript'i sürekli daha karmaşık hale getirmek yerine, keşke bunların tümünün yerini alacak başka bir şey çıksa diye düşünüyorum
    HTML5'in yeni öğelerinin çoğunun neden gerekli olduğunu da pek anlamadığım için neredeyse hiç kullanmıyorum. Sonunda birçok kapsayıcının benzersiz kimlik verilmiş birer div olduğu sonucuna vardım; hatta dahili bağlantılar için href gezinmesinde kullanılacak bu kimlikler için bir tür takma ad olsa iyi olurdu diye düşündüm
    [data-theme="dark"] [data-theme="light"] :focus { outline-color: black; } gibi şeyleri kafamda çözümlemek çok uzun sürdüğü için artık zarif ve basit gelmiyor
    Buna karşılık h2 { color: red; } hâlâ basit
    ancestor(X, Y) :- parent(X, Y). gibi bir ifade ise daha şimdiden düşünmek istemediğim türden. :- de ne oluyor, gülen yüz gibi duruyor
    @container style(--theme: dark) { .card { background: royalblue; color: white; } } ifadesinde okumayı bıraktım
    Eskiden iyi işleyen standartlar zamanla bozuluyormuş gibi gelmesi garip

    • Benim niyetim CSS'ye daha fazla sözdizimi ve anlam ekleyelim demek değil; daha çok CSS'den fikirler çalıp mantıksal/ilişkisel sorgu dilleriyle benzerliklerinden yararlanarak yeni bir şey yapmak
      Örneğin [data-theme="dark"] [data-theme="light"] :focus { outline-color: black; } ifadesini İngilizce benzeri sözde koda açarsak, data-theme="dark" olan bir X var ve onun çocuğu olan Y'nin data-theme="light" olup odakta olması durumunda Y'nin outline-color değerini black yap demeye yakın
      Dolayısıyla bunu Datalog tarzında outline-color(Y, black) if data-theme(X, "dark") and parent(X, Y) and data-theme(Y, "light") and focused(Y) şeklinde yazabilirsiniz
      Yani :- yerine if, virgül yerine and koymuş oluyoruz
      Daha da ileri gidip Y.outline_color := black if X.data-theme == dark and Y.parent == X and Y.data-theme == dark and Y.focused diye yazarak, attr(X, val) biçimini X.attr == val gibi UFCS benzeri bir sözdizimsel şeker halinde göstermek de mümkün
      Daha ALGOL ailesinden görünmesini isterseniz forall Y { Y.outline_color := black if Y.data_theme == "dark" and Y.focused and Y.parent.data_theme == "light" } gibi de yazılabilir
      Burada Y'yi açıkça tanıtıp bir join'i örtük hale getirerek daha genel amaçlı programlama gibi gösteriyorsunuz ama pratikte olan şey, bağımlılıklar her değiştiğinde Datalog motorunun bu tür döngüleri verimli şekilde yeniden çalıştırmasıdır