- Sintaks JavaScript mudah menjadi rumit karena tanda kurung bertingkat dan callback, dan bahkan UI kecil pun sering menarik banyak library sehingga terjadi pembengkakan
- WebAssembly membuka jalan untuk menjalankan bahasa lain di browser, tetapi seperti pada Pyodide, biaya penghubung asinkron dengan event loop JavaScript cukup besar
- Sumber daya browser dan memori WebAssembly terbatas, jadi yang dibutuhkan bukan menggantikan JavaScript melainkan pendekatan bernegosiasi dengannya
- LispE memuat lebih dari 450 fungsi dalam satu biner WASM berukuran 3.3MB, serta menyediakan string, perhitungan, matriks, dan regular expression sekaligus
- Dengan
evaljs dan asyncjs, LispE memanfaatkan fungsi JavaScript dan DOM sambil mengurangi pembengkakan kode lewat satu biner yang bisa diaudit, alih-alih banyak library eksternal
Pembengkakan JavaScript dan keterbatasan browser
- Sintaks JavaScript mudah menjadi rumit karena tanda kurung biasa, kurung kurawal, dan kurung siku saling bertumpuk dan urutan penutupannya harus tepat
- Ada contoh
forEach callback yang mengisi nilai ke beberapa objek dan memperbarui cache secara kondisional
newNames.forEach((name, i) => {
allAgentContents[name] = contents[i];
agentModes[name] = modes[i];
if (compiled[i]) agentCompiledCache[name] = compiled[i];
agentViewingCompiled[name] = viewing[i];
});
- Untuk pemrosesan yang umumnya sudah tersedia di bahasa pemrograman dasar, di JavaScript kita sering harus mengunduh banyak library
- C atau C++ juga memerlukan
include untuk bekerja, tetapi pada library JavaScript sering kali tidak jelas siapa yang mengimplementasikan dan siapa yang merawatnya
- Ada juga halaman yang terasa seperti memuat “setengah internet” hanya untuk menampilkan hello di jendela kecil
- Internet bergantung pada JavaScript, dan meski disamarkan dengan TypeScript, ia tetap menjadi penjaga gerbang yang harus dilewati setiap kali halaman dibuka di browser
- Pernah ada impian bahwa browser akan menjadi sistem operasi pamungkas yang membuat Windows atau Mac OS tidak lagi diperlukan, dan JavaScript dipilih sebagai bahasa untuk mewujudkan impian itu
Hubungan WebAssembly dan JavaScript
- WebAssembly lebih dekat ke mesin virtual dengan bahasa mesin sendiri, sehingga membuka kemungkinan menulis kode dengan cara lain di dalam browser
- Pyodide adalah pencapaian rekayasa yang mengesankan untuk menjalankan Python di browser, tetapi juga memperlihatkan biaya bekerja di dalam wilayah JavaScript
- Dunia asinkron Python
asyncio dan event loop JavaScript harus saling berbicara
- Jembatan di antara keduanya rapuh, dan kita harus selalu ingat setiap
await termasuk ke dunia yang mana
- Sumber daya browser terbatas, sehingga dibutuhkan cara berpikir seperti di awal ilmu komputer, ketika setiap instruksi dan struktur diperiksa sampai ke tingkat bit
- Dijadikan patokan bahwa pemrograman dimulai pada 1981 di komputer yang hanya menyisakan tepat 15772 bytes
- Memori browser modern memang tidak seterbatas komputer pertama itu, tetapi WebAssembly tidak bisa memiliki memori secara bebas seperti program biasa dan harus lebih dulu mendapat izin dengan cara yang terbatas
- Sikap kuncinya bukan melawan JavaScript, melainkan bernegosiasi dengannya
Alternatif yang ditawarkan LispE
- LispE menyediakan lebih dari 450 fungsi dalam satu biner tunggal
- Ukuran biner WASM adalah 3.3 MB
- Fitur pemrosesan string, perhitungan, matriks, dan regular expression dikemas dalam satu tempat
- Biner WASM tersedia di binaries/wasm
- Meski merupakan interpreter kecil, ia dapat menangani string,
Float64Array, integer, bilangan riil, dan array string sebagai nilai kembalian
- Karena berbasis Lisp, LispE memiliki struktur AST yang tetap hidup
- Jika sintaks Lisp tidak cocok, kita bisa memakai sintaks transpile untuk bahasa yang nyaris sulit dibedakan dari Python atau Basic
- Kita bisa mengubah grammar untuk membuat bahasa dengan gaya yang diinginkan
- Bahkan bisa dalam bahasa Yunani, dan sudah ada contoh bahasa Yunani
- LispE bekerja sama dengan JavaScript dengan memanfaatkan fungsi JavaScript dan kemampuan DOM, bukan melawannya
Memanggil JavaScript: evaljs dan asyncjs
- Untuk menjalankan kode JavaScript dari dalam LispE, kita bisa menggunakan
evaljs dan asyncjs
evaljs menjalankan kode JavaScript dan mengembalikan nilainya
asyncjs menghubungkan fungsi JavaScript buatan pengguna yang didefinisikan di halaman dengan callback asinkron
(setq a (evaljs "10 + 20 + 30")) ; execute some JS code
; call_llm is a user-defined JS function in the page
(asyncjs `call_llm("Implement a piece of code in Python to sort strings");` 'mycallback)
(defun mycallback(theresult) ...)
asyncjs bekerja sebagai Promise yang akan kembali setelah tugas selesai
Mengurangi pembengkakan kode
- Kutipan Wirth pada 1995 mengarah pada kesimpulan bahwa komputer yang lebih cepat dan model yang lebih besar tidak menyelesaikan masalah, dan kode harus dijaga tetap ramping
- LispE menyediakan 450 fungsi yang diekspos ke browser dalam satu biner yang bisa diaudit
- Jika tiap fungsi diimplementasikan terpisah, kita perlu memuat library seperti
mathjs untuk komputasi numerik, lodash untuk koleksi, voca untuk manipulasi string, dan simple-statistics untuk distribusi statistik
- Pendekatan ini bisa membesar menjadi ratusan MB kode dengan penulis, bug, dan jadwal pemeliharaan yang berbeda-beda
- LispE menyediakan semua fungsi itu dalam satu kode yang dipelihara, dan karena open source seluruh kodenya dapat diaudit
- Diyakini bahwa Garbage Collector tidak akan merusak performa kode pada saat terburuk
- Ia berkomunikasi secara transparan dengan JavaScript lewat pemanggilan API sederhana, dan bisa mengembalikan struktur yang sudah ditentukan sebelumnya
// floats here is a Float64Array
const floats = callEvalLispEToFloats(0, `(normal_distribution 100)`);
2 komentar
Tulisannya agak terasa tiba-tiba, jadi saya sempat meragukan sumbernya, ternyata dari Naver
Tapi ya, memang reaksinya kurang bagus... Jujur saja, JavaScript yang dibesar-besarkan sampai mengunggah WASM 3,3MB demi memakai Lisp itu terasa seperti over-engineering yang tidak mudah dipahami wkwk
Soal kenapa akunnya akun Naver, ada komentar dari pengembang proyek bernama Claudius; katanya dia bekerja di Naver Labs Europe dan ini diunggah setelah disetujui Naver sebagai proyek open source.
Sepertinya tidak terlalu berkaitan besar dengan Naver, mungkin cuma orang-orang yang benar-benar sangat mencintai Lisp...
Opini di Lobste.rs
Rasanya aneh kalau bilang ingin mengurangi bloat JavaScript tapi malah menambahkan gumpalan WASM 3,3MB yang opak dan menyuruh aplikasi ditulis dengan Lisp
Dengan JavaScript murni dan tanpa dependensi tambahan pun, kita masih bisa membuat banyak hal sebelum mendekati sepersepuluh ukuran itu
Saya juga tidak cocok dengan cara pemakaian ini, tetapi ini adalah proyek passion Lisp yang menarik dengan keanehan yang jarang terlihat akhir-akhir ini, dan saya suka karena seluruh dokumentasinya terasa jelas ditulis tangan oleh manusia dengan kalimat-kalimat yang khas
Hal-hal yang layak masuk ke standard library selalu terbuka untuk diusulkan
Beberapa tambahan terbaru mencakup union/intersection untuk himpunan,
sum,base64, dan lain-lainNamun saya hampir tidak pernah mendengar permintaan untuk fungsi kalkulus, dan untuk string yang terus diminta biasanya hanya
.reverseatau.titleCase.reversetidak punya banyak penggunaan yang benar-benar meyakinkan di luar soal-soal mainan, dan.titleCasememang memungkinkan, tetapi butuh data internasionalisasi sehingga pembahasannya masih berjalanLagipula keduanya juga tidak ada di library ini
Mereka merasa walaupun mengajukan proposal, realisasinya akan butuh 3 tahun sehingga tidak layak dicoba, dan berpikir folder
utils/memang kurang ideal tetapi bisa dibuat sekarang jugaArgumen saya lebih dekat ke model distribusi daripada soal JavaScript kekurangan fungsi
Bahkan jika standard library sudah penuh, aplikasi rata-rata tetap mengirim dependensi npm transitif dalam ukuran megabyte
LispE-as-WASM berukuran 3,3MB, punya sekitar 450 fungsi yang terdokumentasi, inti C++, serta source code publik di GitHub, sebagai eksperimen untuk melihat seperti apa runtime yang bisa diaudit
Saya benar-benar sudah membangun harness agen di atasnya, dan menjalankan aturan LispE secara ad-hoc langsung di dalam browser
JavaScript event loop-nya sangat saya sukai
Kalau seseorang bilang sintaks itu yang bikin bloat, saya jadi waspada
Sintaks minimal justru bisa jauh lebih sulit dibaca dibanding sintaks yang memakai karakter berbeda untuk pembedaan visual
Kalau melihat apa yang ditawarkan LispE sebagai alternatif, hasilnya seperti ini:
... !?
https://github.com/naver/lispe/wiki/5.3-A-la-APL
Titik masuk ke proyek ini agak aneh, dan halaman https://github.com/naver/lispe/wiki/1.-Introduction tampak lebih baik
Ini adalah proyek Lisp native yang juga menargetkan WASM, dan ada unsur-unsur menarik yang mungkin disukai para penggemar bahasa pemrograman
Kesan pertama saya adalah ini terasa seperti contoh JavaScript yang cukup dipaksakan
Sebagian besar kebencian terhadap JavaScript tampaknya berasal dari ketidakcocokan browser era awal, DOM API yang menyakitkan, dan jebakan sintaks, dan hal-hal itu praktis tidak berdampak pada keseharian saya sekarang
JavaScript modern, terutama dengan TypeScript dan aturan lint yang masuk akal, sudah cukup baik sebagai bahasa
Masih ada masalah seperti CJS vs ESM, risiko supply chain, dan perubahan ekosistem, tetapi sebagian besar itu berada di luar bahasa itu sendiri
Pengalaman yang sampai membuat orang menciptakan ekstensi editor hanya demi menyeimbangkan tanda kurung justru dianggap hebat?
Kalau yang diinginkan adalah gaya pemrograman seperti ini, yaitu kepadatan sintaks rendah dan pendekatan fungsional, lebih baik membalik arahnya dan memilih bahasa concatenative
Saya penasaran bagaimana hasil kompilasi interpreter Lisp bisa sampai 3,3MB
Apa ini yang disebut mengurangi bloat?
Meski begitu, saya setuju bahwa mendistribusikan standard library besar berikut kode yang tidak dipakai jelas jauh dari semangat mengurangi bloat
Kejutan! Kengerian!
Harus menutup tanda kurung dalam urutan yang benar, sungguh mengejutkan
Bahkan para penggemar Lisp yang muak dengan kebawelan bahasa seperti JavaScript pun sering berbalik arah saat berhadapan dengan bahasa keluarga APL, lalu mulai berdebat bahwa kejelasan dan keterbacaan jauh lebih penting daripada sekadar sependek mungkin
Penulis LispE tampaknya memang punya ketertarikan tertentu pada operasi dasar APL, tetapi tetap sulit dipahami mengapa setelah mengenal bahasa dengan notasi sepadat itu, ia masih memilih Conway's Life dalam bentuk s-expression yang lebih panjang, lebih renggang, dan bertingkat dalam dibanding versi APL, J, K, atau bahkan Q