Lisp: Buzlanma mı, Pasta mı?
(dthompson.us)- Spring Lisp Game Jam 2024'e 48 oyun gönderildi ve bu sayı yeni bir rekor oldu; katılımcıların işleri, Lisp'i üstüne ekleme yaklaşımı ile yığının tamamını Lisp'le kurma yaklaşımı arasında belirgin biçimde ayrıldı
- Buzlanma yaklaşımı, C/Rust/Lua tabanlı bir programın üzerine Lisp'i betik katmanı olarak koyup hızlıca sonuç almayı sağlıyor, ancak alttaki statik dil ve araç zincirine güçlü biçimde bağlı kalıyor
- Pasta yaklaşımı, programın büyük kısmını Lisp ile yazıp C FFI kullanımını en aza indirerek daha derin bir kontrol sağlıyor, ancak kütüphane geliştirme, wrapper yazımı ve web'e dağıtım maliyetini artırıyor
- Game Jam'de Fennel+love2d ve S7+raylib buzlanmaya daha yakınken, Guile+Chickadee pastaya karşılık geliyor; Hoot+HTML5 canvas ise Scheme tabanlı Wasm araç zinciri sayesinde pastaya daha yakın duruyor
- Lisp'in yığındaki payı arttıkça canlı hackleme, bellek güvenliği, Lisp/C sınırının azalması ve hacklenebilirlik artıyor; Guix, Trial ve Pre-Scheme gibi projeler de aynı yönü gösteriyor
Spring Lisp Game Jam 2024 gönderi durumu
- Spring Lisp Game Jam 2024 bir hafta önce sona erdi ve 48 oyun gönderilerek jam tarihinde yeni rekor kırıldı
- Katılımcılar daha sonra bir hafta boyunca birbirlerinin oyunlarını oynayıp değerlendirdi
- Gönderilerin dillere göre dağılımı şöyleydi
- Guile: 15, %31
- Fennel: 10, %21
- Clojure: 5, %10
- Common Lisp: 5, %10
- Racket: 4, %8
- Elisp: 4, %8
- S7: 3, %6
- Kawa: 1, %2
- Owl: 1, %2
- Guile oranı: {p:31}
- Scheme uygulamalarının tek bir
schemekategorisi altında toplanmamasının nedeni, Scheme belirtiminin küçük olması ve Guile, Racket, S7, Kawa'nın birbirinden farklı amaçlara sahip uygulamalar olması - Bu jam'de ilk kez Guile en fazla gönderiye sahip dil oldu
- 15 Guile oyununun 11'i Hoot ile yapılmış web oyunuydu
- Hoot, Spritely Institute tarafından geliştirilen bir Scheme-to-WebAssembly derleyicisidir
- Bu 11 oyundan 2'si resmî Spritely projesiydi
- Spritely Institute, jam başlamadan önce insanlardan Hoot ile oyun yapmayı denemelerini istedi ve birçok katılımcı buna yanıt verdi
- Normalde bu jam'deki en popüler dil Fennel olur; Fennel, Lua'ya derlenen bir Lisp'tir
- S7 kullanan 3 oyun da Lisp'in oyun geliştirmede nasıl kullanıldığıyla bağlantılı örnekler sundu
Lisp'i buzlanma olarak kullanma yaklaşımı
- Buzlanma deseni, C veya Rust gibi statik dillerle yapılmış bir “pasta”nın üstüne Lisp'i betik dili gibi ekleme yaklaşımıdır
- Genellikle daha büyük bir programın içine bir Lisp yorumlayıcısı gömülür
- Uygulamanın yüksek seviyeli kısımlarını Lisp ile yazmak istiyorsanız bu en hızlı yol olabilir
- Uygun bir yorumlayıcıya veya derleyiciye ihtiyaç vardır
- Uygulamanın ihtiyaç duyduğu hook'ları eklemenin bir yolu da olmalıdır
- Programın ana kısmı C veya Rust ile yazılmışsa emscripten ile WebAssembly'ye derlenip web'e dağıtılabilir
- Hızlıca tatmin edici sonuçlar alınabilir, ancak statik dil ve onun araç zinciriyle güçlü biçimde bağlı kalınır
- Tipik örnekler şunlardır
- S7, gömülebilir bir Scheme'dir
- Guile da C programlarını genişletmek için kullanılabilir, ancak yorumlayıcıyı çalıştırılabilir dosyanın içine koymak yerine genellikle
libguileile dinamik bağlama kullanılır - Fennel, Lua genişletme noktalarına sahip mevcut uygulamalardan yararlanarak Lisp benzeri bir dili Lua'ya derler
Lisp'i pasta olarak kullanma yaklaşımı
- Pasta deseni, yazılım yığınının olabildiğince büyük kısmını Lisp ile gerçekleştirme yaklaşımıdır
- Lisp'i Lisp olmayan bir programın içine yerleştirmek yerine, programın büyük bölümü Lisp ile yazılır
- Gerekirse dış fonksiyon arayüzü (FFI) ile paylaşılan kütüphaneler çağrılır, ancak bunu olabildiğince az kullanmak daha iyidir
- Sonuç almak daha uzun sürer
- Seçilen Lisp uygulamasında bulunmayan kütüphaneleri kendiniz gerçekleştirmeniz gerekir
- Kaçınılmaz C paylaşımlı kütüphaneleri için wrapper yazmanız gerekir
- Proje emscripten hedefi olmaya kolayca uygun olmadığı için web'e dağıtım daha zor hale gelir
- Bu yaklaşım, klasik embed vs. extend tartışmasıyla bağlantılıdır
- Guile buzlanma için de kullanılabilir, ancak pasta olarak kullanıldığında daha güçlüdür
- Guile'ın ilk vizyonu, bir Scheme yorumlayıcısı ekleyerek başka programları Emacs benzeri hale getirmekti
- Bugünün iyi pratiği, programı en baştan Scheme ile yazmaktır
- Common Lisp de pasta yaklaşımına iyi bir örnektir
- SBCL gibi uygulamalar iyi bir C FFI sağlar
- Verimli yerel çalıştırılabilir dosyalara derlenebilir, bu da performans nedeniyle C kullanma isteğini azaltır
Game Jam örneklerinde buzlanma ve pasta
-
Fennel + love2d
- love2d uzun süredir tek kişi veya küçük ekip oyun geliştirmede popüler bir seçenek oldu
- love2d, Lua yorumlayıcısı gömülü bir C++ programı olduğu için Fennel için iyi bir hedeftir
- Çoğu Linux dağıtımı love2d'yi paketlediğinden
.lovedosyalarını yerel olarak çalıştırmak kolaydır - emscripten sayesinde love2d oyunları web'e de dağıtılabilir
- Bu yüzden Fennel oyunlarının çoğu love2d kullanır
- ./soko.bin ve Gnomic Vengeance bu yığını kullanır
- Fennel+love2d, Lisp as icing için eksiksiz bir örnektir
- Fennel yığının en üstündedir ve Lisp'i aşağı katmanlara yaymanın fiilen bir yolu yoktur
- Bugüne kadar en başarılı Lisp oyun geliştirme yığınıdır
-
S7 + raylib
- Bu jam'de GhostHop ve Life Predictor adlı iki oyun S7+raylib yığınını kullandı
- Raylib, birçok üst seviye dil bağlamasına sahip bir C kütüphanesidir ve son birkaç yılda popülerliği arttı
- S7 de C ile gerçekleştirilmiştir ve kolayca gömülebilir; bu yüzden bu kombinasyonun emscripten ile web'e dağıtılması kolaydır
- S7+raylib de Lisp as icing örneğidir ve gelecek jam'lerde daha popüler olup olmayacağını izlemeye değer
-
Guile + Chickadee
- Chickadee, Guile için bir oyun kütüphanesidir ve render dahil ilginç kısımların neredeyse tamamını Scheme ile gerçekleştirir
- Son jam'lerde Turbo Racer 3000 ve Bloatrunner adlı iki oyun Chickadee ile yapıldı
- Guile+Chickadee, Lisp as cake örneğidir
- Chickadee, görsel, ses ve font yükleme gibi düşük seviyeli işler için bazı C kütüphanelerini sarar, ancak kendi kodu saf Scheme ile yazılmıştır
- Matris ve vektör matematiğinin tamamı da Scheme ile gerçekleştirilmiştir
- love2d ve raylib ile boy ölçüşebilecek bir render primitive seti sunar; bu da yine Scheme ile gerçekleştirilmiştir
- Başka Lisp oyun kütüphaneleri sıklıkla nanosvg gibi C kütüphaneleri kullanırken, Chickadee Scheme ile vektör grafik render etme konusunda da ilerleme kaydetti
- Chickadee, Guile derleyicisinin ve sanal makinesinin sınırlarını zorladı; bu süreçte Guile da iyileşti
- Ancak geliştirme büyük ölçüde tek bir kişi tarafından sınırlı boş zamanda yürütüldüğü için, daha popüler oyun geliştirme kütüphaneleriyle özellik eşdeğerliğine ulaşması uzun sürüyor
- Buna rağmen mevcut haliyle amacı için oldukça iyi çalışıyor
-
Hoot + HTML5 canvas
- Hoot, bir Scheme-to-WebAssembly derleyicisidir
- Hoot, C ile yazılmış Guile VM'yi emscripten ile Wasm'a derlemez
- Bunun yerine tam bir Wasm araç zinciri ve Wasm'ı doğrudan dışa veren Guile derleyicisi için yeni bir backend gerçekleştirir
- Hoot'un tamamı Scheme ile yazılmıştır
- emscripten ile derlenmiş C programlarının doğrusal bellek tabanlı Wasm 1.0'ı hedeflemesinin aksine, Hoot GC tarafından yönetilen heap türlerine sahip Wasm 2.0'ı hedefler
- Bu yapı sayesinde Hoot ikilileri çöp toplayıcıyı içinde taşımaz
- Bu nedenle emscripten ile derlenmiş Lisp çalışma zamanlarından çok daha küçüktür
- Bir Hoot oyununun Wasm ikilisi 2MiB'nin altındaydı; incelenen bir love2d oyununun
love.wasmdosyası ise neredeyse 6MiB idi - Hoot programları JavaScript ile kolayca birlikte çalışabilir
- Scheme nesneleri JavaScript'e kolayca geçirilebilir
- JavaScript nesneleri de Scheme'e geçirilebilir
- Çünkü iki taraftaki nesneler aynı heap üzerinde yönetilir
- Tarayıcı API'lerine Wasm import yoluyla erişilebilir; bu yüzden oyunlarda yerleşik HTML5 canvas API'si kolay bir 2D render seçeneği olur
- Bu jam'de Hoot kullanan 11 oyun vardı; bunlar arasında Cirkoban ve Lambda Dungeon da bulunuyordu
- Hoot+HTML5 canvas çoğunlukla kalın bir pasta, biraz da buzlanma içeren bir yapıdır
- Hoot'u ayağa kaldırmak 1 yıl ve kayda değer miktarda finansman gerektirdi
- emscripten kullanmadan kendi araç zincirini yaptı ve Guile derleyicisini de genişletti
- Ayrıca Guile VM üzerinde çalışan bir Wasm yorumlayıcısı da var
- Öte yandan canvas API oldukça üst seviyelidir
- Pastaya daha yakın bir yaklaşım, Hoot'un JS FFI'si ile WebGL veya WebGPU çağırmak olacaktır
- Gelecek planları WebGL/WebGPU yönünde; bunu mümkün kılmak için Wasm GC tarafında iyileştirmeler gerekiyor
- Bir başka hedef de Chickadee'yi Hoot'a taşımak ve böylece Chickadee oyunlarını love2d oyunları gibi hem yerel ortamda hem de tarayıcıda kolayca oynanabilir hale getirmek
Pasta yaklaşımının sınırlamaları ve avantajları
- Pasta yaklaşımının da açık sınırlamaları var
- Modern ortam Lisp machine dünyası değil; en yüksek Lisp pastası bile çoğu zaman C ile yapılmış daha büyük bir pastanın üstünde duruyor
- Modern Lisp sistemleri bir noktada mutlaka alt katmanlara iner
- Emacs, C çekirdeğinin üstünde çalışır
- Guile VM, C ile yazılmıştır
- Hoot, V8 gibi C++ tabanlı büyük JavaScript motorlarının üstünde çalışır
- Hoot oyunları şu anda WebGL/WebGPU yerine HTML5 canvas ile render edilir
- OpenGL kullanımı için
libGLgerekir - Chickadee,
libGLçağrıları için C FFI üzerindenguile-openglkullanır libpng, FreeType ve benzerleri de vardır
- Her şeyi yeniden Lisp ile yazmak için gereken kaynak çok büyüktür
- Yine de yığının bir kısmını C gibi dillerden geri almak küçük de olsa bir zaferdir
- Lisp ile yazılmış bölümleri hacklemek daha kolaydır; bazıları program çalışırken canlı hacklemeye de izin verir
- GC tarafından yönetilen çalışma zamanları sayesinde genellikle bellek güvenliği elde edilir
- FFI çağrıları azaldıkça Lisp/C sınırını geçmenin ek maliyeti düşer ve güvenlik artar
- Yığında Lisp'in payı arttıkça, yapı buzlanmadan çok pastaya yaklaşır
Oyun dışındaki pasta örnekleri
- Guix, pasta yaklaşımının ne kadar güçlü olabileceğini gösteren iyi bir örnektir
- Guix, Nix projesinin işlevsel paketleme modelini alıp yeniden gerçekleştirirken Nix dilini Guile ile değiştirdi
- Bunun nedeni code staging, kod paylaşımı ve daha yüksek hacklenebilirlikti
- Guix, systemd yerine Guile ile yazılmış bir init sistemi de kullanır; bu tercih de aynı nedenlere dayanır
- Başlangıçta Guix'i gereksiz yere tekerleği yeniden icat etmekle eleştirmek kolaydı, ancak 10 yıl sonra Lisp kullanımını en üst düzeye çıkarma konusundaki ısrarın projenin başarısında kilit rol oynadığı görüldü
- Kullanıcılar Guix deyimlerini ve biraz Guile öğrendiklerinde işletim sistemini istedikleri gibi yapılandırma konusunda güçlü bir yetenek kazanır
- Guix, modern donanım üzerinde Lisp machine deneyimine en çok yaklaşan sistem olarak görülebilir
- Common Lisp tarafında Trial oyun motoru, C kütüphanelerini sarmak yerine birçok bölümü Common Lisp ile gerçekleştiren bir örnektir
- Pre-Scheme gibi projeler, GC tarafından yönetilen çalışma zamanının alt katmanlarının da bir gün Lisp ile gerçekleştirilebileceğine dair umut veriyor
- Pre-Scheme, Scheme 48 içinde geliştirildi ve başarıyla kullanıldı
- NLnet grant sayesinde modern bir yeniden canlanma bekleniyor
Lisp ile daha fazla yığın kurma yönü
- Yön pasta tarafına daha yakındır
- Lisp'in yapabileceklerinin sınırlarını sürekli zorlayan daha fazla projeye ihtiyaç var
- Lisp Game Jam'de en ilginç olan şey oyunların kendisinden çok, eski ve kuru C'den pastanın küçük bir dilimini geri alma yönündeki küçük ilerlemelerdir
- Guile oyun geliştirmede Chickadee projesiyle sınırları zorlamaya devam etme niyeti var
- Sonuç Rust ile yeniden yazmak değil, Lisp ile yeniden yazmak
1 yorum
Hacker News yorumları
Nesnel olarak yazılım yaklaşımlarını karşılaştıran yazıları artık neredeyse hiç görmediğim için bunu görmek daha da sevindiriciydi
Böyle yazılar aramaya çalışsanız bile bugünlerde arama sonuçları çoğu zaman SEO spam engelini aşamıyor
Janet oyunlar için yapılmış gibi görünüyor ve web sunucusu ya da grafik gibi epey fazla “batteries included” unsur da var gibi, ama Janet kullanan oyunlar görmeyince biraz şaşırdım
Lisp ve oyun tarafında bir kez bakmaya değer bir dil olduğunu düşünüyorum
s7’nin ilgi görmesi sevindirici
Onu, Max/MSP bilgisayar müziği ortamına bir Scheme yorumlayıcısı ekleyen açık kaynak uzantı Scheme for Max’ta Scheme ile kullandım; Guile, Clojure ve Common Lisp arasında bir yerde dururken aynı zamanda çok küçük ve gömmesi kolay
Guile’dan çok daha esnek bir BSD lisansına sahip olması da güzel
Birinci sınıf environment’lara sahip Common Lisp makrolarını seviyorsanız s7’yi de sevme ihtimaliniz yüksek
WASM üzerinde de kullanması çok kolaydı, ben de onu bir müzik eğitimi projesinde bu şekilde kullanıyorum
Scheme’den JS fonksiyonlarını çağıran ve tersine JS’den Scheme’i çağıran genel amaçlı işlevler yapmak da zor değildi, bu yüzden tüm akış pürüzsüzdü
iOS ve Android yerel uygulamalarında grafikleri hariç motor olarak s7 ve SQLite’ı başarıyla gömdük
Çok hızlıydı, FFI’si iyiydi, kararlıydı ve küçüktü; uygulamalar arasında paylaşılan mobil kod, aşırı hızlı birim testleri ve temiz araç zinciri açısından büyük fayda gördük
Sonunda mobilde daha pratik bir Lisp olan Fennel’e geçtik
Mobilde s7 kullanan neredeyse sadece bizdik; buna karşılık Lua, mobil genişletme dili olarak çok daha yaygındı ve r7rs Scheme uyumluluğunun durumu da etkili oldu
Masaüstü geliştirmede Guile kullanıp dağıtımı s7 ile yapınca, parametre değerlendirme sırası gibi ince uyumsuzluklara sık sık takıldık
Hem s7 hem de Fennel harika projelere ve topluluklara sahip
Özellikle Spritely Institute’a, blogu da dahil olmak üzere bakmanızı öneririm
Ne yaptıklarını söyleyip sürprizi bozmak istemiyorum ama derinlemesine incelenmeye değer bir konu ve kurum
Sadece blogu, ilgili bağlantıları ve projeleri okumaya 10 saatten fazla harcadım
https://spritely.institute/archive/
“Biz Lisp makinelerinin dünyasında değil, güzelleştirilmiş bir PDP-11 dünyasında yaşıyoruz” özeti etkileyiciydi
Ama bunun SDL ile kullanılan bir “glazürü” olup olmadığını merak ediyorum
Etiketsiz bellek kullanan von Neumann makineleri olmaları açısından benziyorlar, ama 32 bit mikroişlemcilerin yaygınlaştığı ve Lisp derleyici teknolojisinin buna uyum sağlayacak şekilde geliştiği 80’lerin ortalarından itibaren geleneksel CPU’lar Lisp makinelerini geçmeye başladı
“Etiketsiz bellek” kısmı da CHERI gibi akımlar düşünülünce kalıcı olmayabilir ve LispM tarzı mimarinin büyük bir geri dönüş yapma ihtimali var
Birkaç yıl oturma odamda bir PDP-11/45 tuttum, sonra alan kazanmak için bunu iki adet 8 inç disket sürücülü birkaç H-11 LSI-11/2 ile değiştirdim
PDP-11 yalnızca Unix’in bir tür protoplazması değildi, kavramsal olarak da iyi tasarlanmıştı
Nasıl ki “tek ekrana sığan” rutinleri tercih ediyorsak, PDP-11’in küçük doğrudan adres alanı da aşırı büyük olmayan modülleri teşvik ediyor ve modülerliği destekliyordu
Bugün yetersiz mi? Elbette, özellikle büyük veri için acı verici
Yine de PDP-11’in başarılı olmasının ve bugün hâlâ izlerinin kalmasının kavramsal nedenleri var
Çünkü C’yi düzeltmenin başka yolu yok ve yeniden yazılmayacak çok fazla kod var
Lisp çoğunlukla listelerle çalışır ve listeler belleğin dört bir yanındaki işaretçileri takip edebilir
Eski CPU’larda bellek genel olarak benzer rastgele erişim sürelerine sahipti, bu yüzden sorun değildi; ama modern CPU’lar bellek işaretçilerini aynı hızda takip edemez ve performans için yerellik kurallarına uymak zorundadır
Bu yüzden C ya da Fortran dizileri kullanan algoritmalar, Lisp’in liste tabanlı sürümlerinden her zaman daha hızlı olacaktır
Son dönemde Guile Scheme’deki ilerleme umut verici
En son baktığımdan beri bir yorumlayıcı dilden gerçek bir derleyicisi olan bir dile dönüşmüş ve artık Hoot ile WASM’a derleme de mümkün olmuş
Clojure, uLisp ve Common Lisp’e aşinayım ama Guile Scheme, Common Lisp’in fazlalıklarının çoğunu atmış gibi hissettiriyor; özellikle Guix ve Shepard yerleşirse, elimin altında derlenen bir Lisp olmasını isterim
Little Lisper ve SICP dışında Guile Scheme’i etkili biçimde öğrenmek için iyi kaynaklar olup olmadığını merak ediyorum
İleride yapacaklarımda Guile kullanmayı düşündüğüm için bunu keyifle okudum
WASM tarafındaki çalışmalar da iyi gitmiş gibi görünüyor
https://wingolog.org/archives/2024/05/16/on-hoot-on-boot
Kısa süre önce Clojure ile bir 3D boss savaşı prototipi yaptım: https://prototype-game.pages.dev
Eskiden web geliştirmenin her türünden nefret ederdim ama ClojureScript bunu gerçekten keyifli hâle getirdi; keşke daha yaygın kullanılsa
Daha sonra PC başına geçtiğimde tekrar deneyeceğim
Hangi kütüphaneleri kullandığını merak ediyorum
Çocukken gerçekten çok sevdiğim oyunlardan biriydi
https://www.youtube.com/watch?v=dcJFldES9dg
Bunun tabloya eklenmesini istemiştim ama artık eski bir haber olabilir
Referans:
https://lispy-gopher-show.itch.io/logos-lisp-legend/devlog/7...
https://itch.io/post/10013482
https://ianthehenry.com/posts/janet-game/ varken Janet'ın eksik olması dikkat çekiyor
Yazının telif yılı 1899~1907 olarak görünüyor ama vintage gibi durmaması biraz hayal kırıklığı
Betikleme için yeniden Fennel'e döndüm; çünkü çok daha fazla Lua kütüphanesini doğrudan kullanabiliyor ve neredeyse her yerde, hatta iPad'deki a-Shell'de bile sorunsuz çalışıyor
Bu başlıkta faydalı referanslar vardı ve daha sonra tekrar deneyebilirim: https://janet.zulipchat.com/#narrow/stream/409517-help/topic...
Zaten kanıtlanmış bir prodüksiyon yolu olmasına rağmen, zamanında zar zor oynanabilir bir şey yapabildim; hatta “oynanabilir” demek bile biraz cömertçe
Emacs Lisp ile nasıl bir oyun yapıldığını çok merak ediyorum
Oyun programlama denince akla gelen ilk seçenek değil
Dunnet, aslında Ron Schnell tarafından 1982'de TOPS-20 üzerinde çalışan bir Maclisp programı olarak yazıldı
1992'de Emacs Lisp'e portlandı ama bu sadece basit bir taşıma değildi; yeni odalar, öğeler ve bulmacalar eklendi, MIT merkezli içerikler çıkarıldı
Örneğin oyunun son kısmındaki “endgame” bilgisayarı aslında MIT'te bulunan ve Chaosnet üzerinden erişilen MIT-SALLY adında bir sistemdi, ancak GNU Emacs sürümünde bu eski MIT referansları kaldırıldı
Bunun yerine, VAX 11/780 gibi daha yaygın tanınabilecek ama yine de dönem hissi veren ögelere bilerek yer verildi
https://en.wikipedia.org/wiki/Dunnet_(video_game)
Orijinali burada: https://github.com/Quogic/DunnetPredecessor/blob/master/foo....
https://lcolonq.itch.io/slgj2024-game-boy-gizmo
https://asquared31415.itch.io/disassembly
https://grindingstone.itch.io/pendulum