2 poin oleh GN⁺ 2024-06-03 | 1 komentar | Bagikan ke WhatsApp
  • Spring Lisp Game Jam 2024 menerima 48 game dan mencetak rekor baru, dengan karya peserta terbelah jelas antara pendekatan menambahkan Lisp di atas stack yang ada dan pendekatan membangun stack itu sendiri dengan Lisp
  • Pendekatan lapisan gula menempatkan Lisp sebagai lapisan scripting di atas program berbasis C/Rust/Lua untuk cepat menghasilkan sesuatu, tetapi sangat terikat pada bahasa statis dan toolchain di bawahnya
  • Pendekatan kue menulis sebagian besar program dalam Lisp dan meminimalkan C FFI untuk mendapatkan kendali yang lebih dalam, tetapi biayanya lebih besar untuk implementasi library, penulisan wrapper, dan deployment web
  • Dalam Game Jam, Fennel+love2d dan S7+raylib lebih dekat ke lapisan gula, Guile+Chickadee adalah kue, dan Hoot+HTML5 canvas lebih dekat ke kue berkat toolchain Wasm berbasis Scheme
  • Semakin besar porsi Lisp, semakin besar pula live hacking, keamanan memori, berkurangnya batas Lisp/C, dan kemungkinan untuk diutak-atik; proyek seperti Guix, Trial, dan Pre-Scheme juga menunjukkan arah yang sama

Status pengiriman Spring Lisp Game Jam 2024

  • Spring Lisp Game Jam 2024 berakhir seminggu lalu, dan 48 game dikirimkan, mencetak rekor baru untuk jam ini
  • Setelah itu para peserta menghabiskan seminggu untuk memainkan dan menilai game satu sama lain
  • Distribusi bahasa dari karya yang dikirim adalah sebagai berikut
    • 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%
  • Porsi Guile: {p:31}
  • Alasan berbagai implementasi Scheme tidak digabung ke dalam satu kategori scheme adalah karena spesifikasi Scheme itu kecil, dan Guile, Racket, S7, serta Kawa adalah implementasi dengan tujuan yang berbeda-beda
  • Dalam jam kali ini, Guile untuk pertama kalinya mencatat jumlah karya terbanyak
    • Dari 15 game Guile, 11 adalah game web yang dibuat dengan Hoot
    • Hoot adalah compiler Scheme-to-WebAssembly yang sedang dikembangkan oleh Spritely Institute
    • 2 dari 11 itu adalah proyek resmi Spritely
    • Sebelum jam dimulai, Spritely Institute meminta orang untuk mencoba membuat game dengan Hoot, dan banyak peserta menanggapinya
  • Biasanya bahasa paling populer di jam ini adalah Fennel, yaitu Lisp yang dikompilasi ke Lua
  • Tiga game yang memakai S7 juga menjadi contoh yang terhubung dengan cara menggunakan Lisp untuk pengembangan game

Menggunakan Lisp sebagai lapisan gula

  • Pola lapisan gula adalah pendekatan menaruh Lisp seperti bahasa scripting di atas “kue” yang dibuat dengan bahasa statis seperti C atau Rust
  • Biasanya ini dilakukan dengan menanamkan interpreter Lisp ke dalam program yang lebih besar
  • Jika ingin menulis bagian tingkat tinggi dari aplikasi dalam Lisp, ini bisa menjadi jalur tercepat
    • Dibutuhkan interpreter atau compiler yang sesuai
    • Juga harus ada cara untuk menambahkan hook yang dibutuhkan aplikasi
  • Jika bagian utama program ditulis dalam C atau Rust, program itu bisa dikompilasi ke WebAssembly dengan emscripten lalu dideploy ke web
  • Hasil yang memuaskan bisa didapat dengan cepat, tetapi pendekatan ini sangat terikat pada bahasa statis dan toolchain terkait
  • Contoh yang mewakili antara lain
    • S7 adalah Scheme yang bisa ditanamkan
    • Guile juga bisa dipakai untuk memperluas program C, tetapi alih-alih memasukkan interpreter ke dalam executable, biasanya ia ditautkan secara dinamis ke libguile
    • Fennel memanfaatkan titik ekstensi Lua pada aplikasi yang sudah ada dan mengompilasi bahasa mirip Lisp ke Lua

Menggunakan Lisp sebagai kue

  • Pola kue adalah pendekatan mengimplementasikan sebanyak mungkin software stack dalam Lisp
  • Alih-alih menaruh Lisp di dalam program non-Lisp, sebagian besar program ditulis dalam Lisp
  • Jika perlu, shared library dipanggil lewat foreign function interface (FFI), tetapi sebaiknya penggunaannya dibuat seminimal mungkin
  • Butuh waktu lebih lama sampai hasilnya terlihat
    • Library yang tidak ada pada implementasi Lisp yang dipilih harus diimplementasikan sendiri
    • Wrapper harus ditulis untuk shared library C yang tidak bisa dihindari
    • Proyek tidak mudah menjadi target emscripten, sehingga deployment web menjadi lebih sulit
  • Pendekatan ini bersinggungan dengan perdebatan klasik embed vs. extend
  • Guile bisa dipakai sebagai lapisan gula, tetapi lebih kuat saat dipakai sebagai kue
    • Visi awal Guile adalah menambahkan interpreter Scheme untuk membuat program lain menjadi seperti Emacs
    • Praktik yang baik saat ini adalah menulis program dalam Scheme sejak awal
  • Common Lisp juga merupakan contoh bagus dari pendekatan kue
    • Implementasi seperti SBCL menyediakan C FFI yang baik
    • Bisa dikompilasi menjadi executable native yang efisien, sehingga mengurangi situasi di mana orang ingin memakai C demi performa

Lapisan gula dan kue dilihat dari contoh Game Jam

  • Fennel + love2d

    • love2d sudah lama menjadi pilihan populer untuk pengembangan game solo atau tim kecil
    • love2d adalah program C++ dengan interpreter Lua tertanam, sehingga menjadi target yang bagus untuk Fennel
    • Karena sebagian besar distro Linux memaketkan love2d, file .love mudah dijalankan secara native
    • Berkat emscripten, game love2d juga bisa dideploy ke web
    • Karena itu, sebagian besar game Fennel memakai love2d
    • ./soko.bin dan Gnomic Vengeance memakai stack ini
    • Fennel+love2d adalah contoh utuh dari Lisp sebagai lapisan gula
    • Fennel berada di puncak stack, dan praktis tidak ada jalur untuk menyebarkan Lisp ke lapisan di bawahnya
    • Sejauh ini ini adalah stack pengembangan game Lisp yang paling sukses
  • S7 + raylib

    • Dalam jam kali ini, dua game yaitu GhostHop dan Life Predictor memakai stack S7+raylib
    • Raylib adalah library C dengan binding untuk banyak bahasa tingkat tinggi dan popularitasnya meningkat dalam beberapa tahun terakhir
    • S7 juga diimplementasikan dalam C dan mudah ditanamkan, sehingga kombinasi ini mudah dideploy ke web dengan emscripten
    • S7+raylib juga merupakan contoh Lisp sebagai lapisan gula, dan menarik untuk dilihat apakah nanti akan menjadi lebih populer di jam mendatang
  • Guile + Chickadee

    • Chickadee adalah library game untuk Guile, dan hampir semua bagian menarik termasuk rendering diimplementasikan dalam Scheme
    • Dalam jam-jam terbaru, dua game Turbo Racer 3000 dan Bloatrunner dibuat dengan Chickadee
    • Guile+Chickadee adalah contoh Lisp sebagai kue
    • Chickadee memang membungkus beberapa library C untuk tugas tingkat rendah seperti memuat gambar, audio, dan font, tetapi kodenya sendiri ditulis dalam Scheme murni
    • Matematika matriks dan vektor juga semuanya diimplementasikan dalam Scheme
    • Ia menyediakan sekumpulan rendering primitive yang sebanding dengan love2d dan raylib, dan ini juga diimplementasikan dalam Scheme
    • Sementara banyak library game Lisp lain memakai library C seperti nanosvg, Chickadee juga telah membuat kemajuan dalam mengimplementasikan rendering grafis vektor dalam Scheme
    • Chickadee mendorong batas compiler dan virtual machine Guile, dan dalam proses itu Guile juga ikut membaik
    • Namun, karena pengembangannya sebagian besar dilakukan oleh satu orang di waktu luang yang terbatas, butuh waktu lama untuk menyamai kelengkapan fitur library pengembangan game yang lebih populer
    • Bahkan dalam kondisi sekarang, ia sudah bekerja cukup baik untuk tujuan tersebut
  • Hoot + HTML5 canvas

    • Hoot adalah compiler Scheme-to-WebAssembly
    • Hoot tidak mengompilasi Guile VM yang ditulis dalam C ke Wasm dengan emscripten
    • Sebaliknya, Hoot mengimplementasikan toolchain Wasm lengkap dan backend baru untuk compiler Guile yang mengekspor Wasm secara langsung
    • Hoot ditulis seluruhnya dalam Scheme
    • Tidak seperti program C yang dikompilasi dengan emscripten dan menargetkan Wasm 1.0 berbasis linear memory, Hoot menargetkan Wasm 2.0 dengan heap type yang dikelola GC
    • Berkat struktur ini, biner Hoot tidak menyertakan garbage collector saat didistribusikan
    • Karena itu ukurannya jauh lebih kecil daripada runtime Lisp yang dikompilasi dengan emscripten
    • Biner Wasm untuk salah satu game Hoot berukuran kurang dari 2MiB, sementara love.wasm dari game love2d yang diperiksa hampir 6MiB
    • Program Hoot bisa berinteroperasi dengan JavaScript dengan mudah
      • Objek Scheme dapat dengan mudah dikirim ke JavaScript
      • Objek JavaScript juga dapat dikirim ke Scheme
      • Karena objek di kedua sisi dikelola pada heap yang sama
    • API browser dapat diakses sebagai Wasm import, sehingga untuk game, API HTML5 canvas bawaan menjadi pilihan rendering 2D yang mudah
    • Dalam jam kali ini ada 11 game yang memakai Hoot, termasuk Cirkoban dan Lambda Dungeon
    • Hoot+HTML5 canvas sebagian besar adalah kue tebal dengan sedikit campuran lapisan gula
    • Booting Hoot memakan waktu satu tahun dan pendanaan yang cukup besar
    • Tanpa memakai emscripten, proyek ini membangun toolchain sendiri dan juga memperluas compiler Guile
    • Ada juga interpreter Wasm yang berjalan di atas Guile VM
    • Di sisi lain, API canvas sangat tingkat tinggi
    • Pendekatan yang lebih dekat ke kue adalah memanggil WebGL atau WebGPU lewat JS FFI milik Hoot
    • Rencana ke depan mengarah ke WebGL/WebGPU, dan agar itu memungkinkan dibutuhkan peningkatan pada Wasm GC
    • Tujuan lain adalah mem-porting Chickadee ke Hoot agar game Chickadee bisa dimainkan dengan mudah di native maupun browser seperti game love2d

Batasan dan keunggulan pendekatan kue

  • Pendekatan kue juga jelas punya batasan
  • Lingkungan modern bukan dunia mesin Lisp, dan bahkan kue Lisp tertinggi pun kebanyakan tetap diletakkan di atas kue yang lebih besar yang terbuat dari C
  • Sistem Lisp modern pada titik tertentu tetap mencapai lapisan di bawahnya
    • Emacs berada di atas inti C
    • Guile VM ditulis dalam C
    • Hoot berjalan di atas mesin JavaScript besar berbasis C++ seperti V8
    • Game Hoot saat ini dirender dengan HTML5 canvas, bukan WebGL/WebGPU
    • Penggunaan OpenGL membutuhkan libGL
    • Chickadee memakai guile-opengl yang memanggil libGL lewat C FFI
    • Ada juga libpng, FreeType, dan lain-lain
  • Menulis ulang semuanya dalam Lisp menghadapi kendala sumber daya yang besar
  • Meski begitu, merebut kembali sebagian stack dari bahasa seperti C tetap merupakan kemenangan kecil
  • Bagian yang ditulis dalam Lisp lebih mudah diutak-atik, dan sebagian bahkan memungkinkan live hacking saat program berjalan
  • Berkat runtime yang dikelola GC, secara umum didapat keamanan memori
  • Jika panggilan FFI berkurang, overhead melintasi batas Lisp/C ikut berkurang dan keamanan juga meningkat
  • Semakin besar porsi Lisp dalam stack, semakin dekat posisinya ke kue daripada lapisan gula

Contoh kue di luar game

  • Guix adalah contoh bagus yang menunjukkan seberapa kuat pendekatan kue bisa menjadi
  • Guix mengambil model packaging fungsional dari proyek Nix lalu mengimplementasikannya ulang dengan mengganti bahasa Nix menjadi Guile
  • Alasannya adalah code staging, berbagi kode, dan peningkatan kemampuan untuk diutak-atik
  • Guix juga memakai init system yang ditulis dalam Guile sebagai pengganti systemd, dan pilihan ini berangkat dari alasan yang sama
  • Pada awalnya Guix mudah dikritik karena dianggap menemukan ulang roda tanpa alasan, tetapi setelah 10 tahun, keteguhan untuk memaksimalkan penggunaan Lisp justru menjadi inti keberhasilan proyek ini
  • Pengguna yang mempelajari idiom Guix dan sedikit Guile mendapatkan kemampuan kuat untuk mengonfigurasi sistem operasi sesuai keinginan mereka
  • Guix dapat dilihat sebagai pengalaman yang paling mendekati mesin Lisp di perangkat keras modern
  • Di sisi Common Lisp, game engine Trial adalah contoh implementasi banyak bagian dalam Common Lisp alih-alih hanya membungkus library C
  • Proyek seperti Pre-Scheme memberi harapan bahwa bahkan lapisan di bawah runtime yang dikelola GC suatu hari juga bisa diimplementasikan dalam Lisp
    • Pre-Scheme dikembangkan di Scheme 48 dan telah berhasil digunakan
    • Berkat NLnet grant, kebangkitan modernnya diharapkan terjadi

Arah untuk membangun lebih banyak stack dengan Lisp

  • Arah ini lebih dekat ke kue
  • Harus ada lebih banyak proyek yang terus mendorong batas dari apa yang bisa dilakukan Lisp
  • Hal paling menarik dari Lisp Game Jam bukan game-nya sendiri, melainkan kemajuan kecil dalam merebut kembali sepotong kue dari C yang tua dan kering
  • Dalam pengembangan game Guile, upaya mendorong batas itu akan terus dilakukan lewat proyek Chickadee
  • Kesimpulannya bukan menulis ulang dengan Rust, melainkan menulis ulang dengan Lisp

1 komentar

 
GN⁺ 2024-06-03
Opini Hacker News
  • Secara objektif, belakangan ini hampir tidak pernah melihat tulisan yang membandingkan pendekatan perangkat lunak, jadi tulisan ini terasa makin menyenangkan
    Bahkan ketika mencoba mencari tulisan seperti itu, sekarang hasil pencarian sering kali tidak bisa melewati spam SEO
    Janet tampaknya dibuat untuk game, dan secara tak terduga juga terlihat punya cukup banyak unsur “batteries included” seperti server web atau grafis, jadi saya agak terkejut tidak melihat game yang memakai Janet
    Menurut saya, di ranah Lisp dan game, bahasa ini layak dilihat

  • Senang melihat s7 mendapat perhatian
    Saya memakainya untuk menulis Scheme for Max, ekstensi open source yang memasukkan interpreter Scheme ke lingkungan musik komputer Max/MSP; posisinya seperti berada di antara Guile, Clojure, dan Common Lisp, tetapi sangat kecil dan mudah di-embed
    Saya juga suka karena lisensinya BSD yang jauh lebih permisif daripada Guile
    Jika Anda menyukai makro Common Lisp dengan lingkungan kelas satu, besar kemungkinan Anda juga akan menyukai s7
    Di WASM pun sangat mudah digunakan, dan saya memakainya seperti itu dalam proyek pendidikan musik
    Membuat fungsi umum untuk memanggil fungsi JS dari Scheme dan sebaliknya memanggil Scheme dari JS juga tidak sulit, sehingga keseluruhan alurnya mulus

    • Saya juga memberi satu suara lagi untuk s7
      Kami berhasil meng-embed s7 dan SQLite sebagai engine selain grafis di aplikasi native iOS dan Android
      Sangat cepat, FFI-nya bagus, stabil, kecil, dan kami mendapat banyak manfaat dari code sharing antar-aplikasi mobile, unit test yang luar biasa cepat, serta toolchain yang rapi
      Pada akhirnya, di mobile kami pindah ke Fennel, Lisp yang lebih praktis
      Hampir hanya tim kami yang memakai s7 di mobile, sementara Lua jauh lebih umum sebagai bahasa ekstensi mobile, dan status kompatibilitas r7rs Scheme juga berpengaruh
      Karena untuk pengembangan desktop kami memakai Guile lalu distribusinya memakai s7, kami sering tersandung inkompatibilitas halus, misalnya urutan evaluasi parameter
      Baik s7 maupun Fennel adalah proyek dan komunitas yang luar biasa
  • Saya sangat menyarankan melihat Spritely Institute, terutama sampai blognya
    Saya tidak ingin membocorkan apa yang mereka lakukan, tetapi ini topik dan institusi yang layak digali dalam-dalam
    Saya menghabiskan lebih dari 10 jam hanya untuk membaca blog, tautan terkait, dan proyeknya
    https://spritely.institute/archive/

    • Tampaknya mereka menarik orang-orang baik dan mengerjakan hal yang cukup keren
  • Ringkasan “kita tidak hidup di dunia mesin Lisp, melainkan di dunia PDP-11 yang dimuliakan” terasa berkesan
    Namun saya penasaran apakah ada “icing” yang dipakai bersama sdl

    • Sulit menyebut CPU tradisional sebagai PDP-11 yang dimuliakan
      Memang mirip dalam arti sama-sama mesin von Neumann dengan memori tanpa tag, tetapi sejak sekitar pertengahan 80-an, ketika mikroprosesor 32-bit menjadi umum dan teknologi compiler Lisp berkembang menyesuaikannya, CPU tradisional mulai melampaui mesin Lisp
      Bagian “memori tanpa tag” itu pun mungkin tidak akan terus bertahan jika melihat arus seperti CHERI, dan ada peluang arsitektur gaya LispM kembali secara besar
    • Saya benar-benar menyukai PDP-11
      Selama beberapa tahun saya menaruh PDP-11/45 di ruang tamu, lalu belakangan menggantinya dengan beberapa H-11 LSI-11/2 yang dilengkapi dua floppy 8 inci untuk menghemat ruang
      PDP-11 bukan hanya semacam protoplasma Unix, tetapi juga dirancang dengan baik secara konseptual
      Seperti kita lebih menyukai routine yang “muat dalam satu layar”, ruang alamat langsung PDP-11 yang kecil mendorong modul yang tidak terlalu besar dan menganjurkan modularitas
      Apakah kurang memadai hari ini? Tentu saja, terutama menyakitkan untuk big data
      Meski begitu, ada alasan konseptual mengapa PDP-11 sukses dan jejaknya masih tersisa sampai sekarang
    • Ironisnya, sekarang kita bergerak menuju mesin C yang memiliki hardware memory tagging
      Karena tidak ada cara lain untuk memperbaiki C, dan terlalu banyak kode yang tidak akan ditulis ulang
    • Bagian akhirnya lebih saya suka: “Disuruh menulis ulang dengan Rust? Sama sekali tidak! Tulis ulang dengan Lisp!
    • Lisp tidak cocok untuk CPU modern karena hierarki memori
      Lisp terutama menangani list, dan list dapat mengikuti pointer yang tersebar di seluruh memori
      Pada CPU lama, memori umumnya punya waktu akses acak yang sama sehingga ini bukan masalah, tetapi CPU modern tidak bisa mengikuti pointer memori dengan kecepatan yang sama dan harus mengikuti aturan locality demi performa
      Karena itu, algoritme yang memakai sesuatu seperti array C atau Fortran pasti selalu lebih cepat daripada versi berbasis list Lisp
  • Kemajuan terbaru Guile Scheme membuat saya antusias
    Tidak seperti terakhir kali saya melihatnya, ia sudah berubah dari bahasa interpreter menjadi bahasa dengan compiler yang layak, dan sekarang bahkan bisa dikompilasi ke WASM dengan Hoot
    Saya familier dengan Clojure, uLisp, dan Common Lisp, tetapi Guile Scheme terasa seperti mengurangi banyak embel-embel Common Lisp, dan terutama jika Guix dan Shepard makin mapan, saya ingin punya Lisp yang bisa dikompilasi
    Saya penasaran apakah ada materi bagus untuk mempelajari Guile Scheme secara efektif selain Little Lisper dan SICP

  • Saya sedang mempertimbangkan memakai Guile untuk sesuatu yang akan saya buat ke depan, jadi ini menarik dibaca
    Pekerjaan di sisi WASM juga tampaknya berjalan baik

  • Baru-baru ini saya membuat prototipe boss fight 3D dengan Clojure: https://prototype-game.pages.dev

    • Bagus sekali
      Dulu saya membenci semua bentuk pengembangan web, tetapi ClojureScript benar-benar membuatnya menyenangkan, dan saya berharap lebih banyak digunakan
    • Di mobile kontrolnya tidak berfungsi
      Nanti akan saya coba lagi saat berada di depan PC
    • Keren
      Penasaran library apa yang dipakai
    • Dengan rasa sayang terhadap karya yang dibuat, ini mengingatkan saya pada Avatar - Legends of the Arena
      Salah satu game yang benar-benar saya sukai saat kecil
      https://www.youtube.com/watch?v=dcJFldES9dg
  • Saya memang sempat meminta agar dimasukkan ke tabel, tapi mungkin sekarang sudah jadi berita lama
    Referensi:
    https://lispy-gopher-show.itch.io/logos-lisp-legend/devlog/7...
    https://itch.io/post/10013482

  • Janet tidak masuk, padahal ada https://ianthehenry.com/posts/janet-game/
    Tahun hak cipta tulisannya tercantum 1899–1907, tapi sayang tampilannya tidak terasa vintage

    • Sepertinya Janet terlewat
      Untuk scripting, saya kembali lagi ke Fennel, karena bisa langsung memakai jauh lebih banyak library Lua dan berjalan tanpa masalah hampir di mana saja, bahkan di a-Shell di iPad
    • Saya sempat mempertimbangkan Janet dengan sangat serius, tetapi tidak melihat jalur langsung menuju target saya untuk memakai aplikasi web dan WebGL (ThreeJS)
      Ada referensi berguna di thread ini, dan mungkin nanti bisa saya coba lagi: https://janet.zulipchat.com/#narrow/stream/409517-help/topic...
      Walau sudah ada jalur produksi yang terbukti, saya nyaris tidak berhasil membuat sesuatu yang playable tepat waktu, dan sebutan “playable” pun rasanya agak murah hati
  • Saya sangat penasaran game seperti apa yang dibuat dengan Emacs Lisp
    Itu bukan pilihan pertama yang terlintas saat memikirkan pemrograman game