1 poin oleh GN⁺ 2 jam lalu | 2 komentar | Bagikan ke WhatsApp
  • Janet adalah dialek Lisp kecil, tetapi memiliki bahasa imperatif, fungsi kelas satu, namespace pengenal tunggal, dan lexical block scope sehingga mudah untuk mulai secara sederhana
  • Bahasa inti hanya terdiri dari 8 perintah: do, def, var, set, if, while, break, fn, dan macro membuat pembungkus control flow yang lebih kuat atau lebih praktis
  • Kemudahan distribusi dicapai dengan mengompilasi program Janet menjadi executable native yang ditautkan secara statis dengan runtime Janet, sehingga pengguna tidak perlu memasang Janet atau dependensi apa pun
  • Parsing Expression Grammar (PEG) lebih sederhana, lebih kuat, dan lebih mudah diprediksi daripada regular expression, sementara sh memungkinkan pipe dan redirection diekspresikan di dalam Janet sehingga memperluas cakupan penulisan CLI
  • Eksekusi saat waktu kompilasi menjalankan perintah tingkat teratas terlebih dahulu lalu menyimpan snapshot status program ke disk, sehingga nilai, referensi bersama, generator, dan status closure dapat diteruskan ke runtime bahkan tanpa macro

Inti yang sederhana

  • Janet adalah bahasa imperatif dengan fungsi kelas satu, namespace pengenal tunggal, dan lexical block scope
  • Inti bahasanya dijaga tetap kecil dengan 8 perintah: do, def, var, set, if, while, break, fn
  • Macro memungkinkan pembungkus control flow tingkat tinggi yang lebih kuat atau lebih praktis
  • Semantik runtime-nya terasa familier, dan bagian bahasa lainnya juga kecil sampai seluruh standard library muat dalam satu halaman

Distribusi native dan embedding

  • Program Janet dapat dengan mudah dikompilasi menjadi executable native yang ditautkan secara statis dengan runtime Janet
  • Pengguna yang menerima distribusinya tidak perlu memasang Janet, dependensi proyek, atau komponen tambahan lainnya
  • Janet mengompilasi dirinya menjadi bytecode, lalu menuliskan bytecode tersebut ke dalam file .c yang memulai runtime Janet, kemudian mengompilasi file C itu dengan compiler C sistem
  • Biner native “hello world” yang sederhana berukuran kurang dari 1MB, dan pada Janet 1.27.0 untuk aarch64 macOS ukurannya adalah 784K
  • Biner ini juga memuat seluruh runtime Janet, garbage collector, hingga compiler bytecode, sehingga program yang mengevaluasi kode Janet saat runtime pun bisa dibuat
  • Runtime Janet adalah library C kecil, sehingga setelah ditautkan Anda dapat memanipulasi nilai Janet dengan memanggil fungsi C biasa
  • Ia juga dapat di-embed ke situs web, dan dapat digunakan untuk membuat situs statis dengan DSL terprogram kustom seperti Toodle

Parsing teks dan DSL subprocess

  • Pemrosesan teks di Janet berbasis Parsing Expression Grammar, bukan regular expression
  • Parsing Expression Grammar lebih sederhana, lebih kuat, dan lebih mudah diprediksi daripada regular expression, serta tidak terikat pada baris sehingga dapat mem-parsing teks multi-baris
  • Ia dapat mem-parsing HTML, JSON, dan bahasa non-reguler lainnya, serta menangani format berkas biner yang mengandung null byte arbitrer
  • sh adalah DSL scripting shell pihak ketiga yang memungkinkan pipe dan redirection diekspresikan langsung di dalam kode Janet
($ find . -name *.janet | say)
  • DSL ini mengangkat Janet dari alternatif yang masuk akal untuk Perl menjadi alternatif yang masuk akal untuk Bash pada rentang program yang cukup luas

Koleksi dan nuansa sintaks

  • Tipe koleksi Janet memiliki bentuk mutable dan immutable
  • Koleksi immutable memiliki value semantics, sehingga vektor immutable [1 2] tidak dapat dibedakan dari (take 2 [1 2 3]) meskipun alamat memorinya berbeda
  • Koleksi mutable memiliki reference semantics, sehingga hash table @{:x 1 :y 2} hanya sama dengan dirinya sendiri, dan hash table lain dengan key dan value yang sama tetap merupakan objek terpisah
  • Sintaksnya banyak memakai tanda kurung, tetapi membedakan bentuk dengan menggunakan [] untuk list dan {} untuk table
  • Literal mutable selalu memakai prefiks @, seperti @"mutable string"
  • Fungsi anonim ditulis sebagai (fn [x] (+ 1 x)), dan juga tersedia notasi singkat yang mengangkat ekspresi menjadi fungsi dengan |, seperti |(+ 1 $)
  • Splat atau spread menggunakan ;, seperti pada (+ ;args)
  • String backtick dapat dibuka dengan sejumlah backtick sesuai keinginan dan ditutup dengan jumlah yang sama; di dalam string backtick, escape sequence seperti \n tidak diterapkan
  • Parameter sisa memakai & alih-alih ., sehingga ditulis seperti (defn foo [first & rest] ...)
  • Janet tidak mendukung reader macro, sehingga sintaksnya sendiri tetap tetap, dan jika Anda bisa membaca Janet maka Anda bisa membaca semua program Janet

Macro dan status saat waktu kompilasi

  • Macro Janet adalah kode yang menulis kode, dan pada waktu kompilasi ia menangani sekaligus alur eksekusi saat ini yang memanipulasi nilai dan abstract syntax tree, serta alur kode aplikasi yang akan dijalankan di masa depan
  • Macro Janet tidak hygienic, dan juga tidak memiliki namespace terpisah untuk fungsi
  • Namun, fungsi literal dapat di-unquote sehingga macro yang sepenuhnya referentially transparent tetap dapat ditulis
  • Saat program Janet dikompilasi, perintah tingkat teratas, pernyataan biasa, dan deklarasi fungsi dijalankan terlebih dahulu, lalu snapshot status program ditulis ke disk
  • Snapshot ini mempertahankan referensi bersama, sehingga setelah dijalankan kembali, nilai mutable masih bisa terus diubah
  • Generator mengingat perintah yang harus dijalankan saat dilanjutkan berikutnya, dan closure juga mempertahankan nilai yang telah ditutupinya
  • Macro adalah bentuk khusus dari eksekusi kode saat waktu kompilasi, tetapi kemampuan ini juga dapat digunakan tanpa macro
  • Dalam game, spline dapat diproses lebih dahulu, berkas dapat dibaca saat waktu kompilasi untuk memasukkan aset ke dalam biner akhir, dan efek samping arbitrer pun bisa dijalankan
  • Janet for Mortals menunjukkan contoh pembuatan binding database otomatis berdasarkan berkas skema SQL, dan menilai bahwa pekerjaan seperti ini cukup sulit di kebanyakan bahasa

Lebih nyaman daripada tradisi Lisp

  • Janet tidak begitu saja mengikuti konvensi Lisp lama
  • CAR diberi nama first, PROGN menjadi do, LAMBDA menjadi fn, dan SETQ menjadi def
  • nil bukan list kosong melainkan tipe tersendiri, dan boolean adalah nilai kelas satu
  • Ia menghindari keluarga EQ, EQL, EQUAL, EQUALP, dan linked list pun hampir tidak terlihat

2 komentar

 
GN⁺ 2 jam lalu
Komentar Hacker News
  • Janet punya beberapa kekurangan. Terutama penentuan versi manajemen paket yang masih kurang, dan juga ekosistem library yang belum lengkap untuk hal-hal seperti routing HTTP tingkat lanjut.
    Meski begitu, saya sangat suka bahwa dengan JPM kita bisa membuat biner dan skrip, dan portabilitasnya juga sangat bagus. Dulu saya bahkan pernah mencoba menjalankan bahasa pemrograman Janet di konsol game Playdate sebagai proof of concept.
    Saya senang menulis kode dengan Janet, tapi setiap kali begitu, agak merepotkan karena orang-orang mengira saya yang membuat bahasa ini

    • Ada tulisan menarik dari Julia Evans yang memvisualisasikan Gunzip dengan Julia: https://jvns.ca/blog/2013/10/24/day-16-gzip-plus-poetry-equa...
      Akan seru kalau ada versi “Janet menulis Janet” juga
    • Penasaran apakah sudah pernah mencoba jeep: https://github.com/pyrmont/jeep/
      Tool ini melakukan vendoring dependensi dan memudahkan pemasangan bundle Janet modern tanpa jpm
    • Kalau butuh sisi server, seperti kata veqq, ada joy, yang mengimplementasikan server HTTP ringan sendiri. Kalau butuh klien, membungkus libcurl atau klien HTTP lain lewat Janet C API cukup mudah.
      Jika terbuka pada pengembangan dengan LLM, Anda bisa membiarkan wrapper ditulis oleh LLM dan menulis logika sebenarnya dalam Janet
    • Saya penasaran apa yang dimaksud secara spesifik dengan routing HTTP tingkat lanjut. Untuk semua pekerjaan web saya memakai https://github.com/joy-framework/joy, jadi kalau ada fitur yang kurang, mungkin bisa ditambahkan dalam seminggu
  • Ada juga bahasa serupa yang dibuat lebih awal oleh pengembang yang sama, yaitu Fennel. Bahasa ini dikompilasi ke Lua dan implementasinya juga seluruhnya ditulis dalam Lua.
    Karena tidak punya standard library sendiri, banyak hal bagus seperti library parser Janet yang tidak ada, tetapi tetap bagus untuk menulis skrip di lingkungan yang menanamkan Lua.
    https://fennel-lang.org/

    • Fennel memang sangat bagus, dan juga cara yang baik untuk mulai masuk ke keluarga Clojure. Keluhan terbesar saya adalah debugging-nya merupakan ladang ranjau transpiler yang sangat khas.
      Keterhubungan antara Fennel dan Lua VM sangat rapuh, dan kualitasnya bahkan tidak sampai setengah dari debugger dan REPL Janet. Sayang sekali, karena Fennel jauh lebih portabel dan dengan LuaJIT bahkan bisa mengungguli SBCL.
      Tapi pengalaman transpile itu sendiri menurut saya benar-benar menjadi hambatan besar. Ada beberapa jalan memutar, tetapi bahkan jika debug.setinfo diimplementasikan, Anda tetap akan menemui kasus batas yang kurang menyenangkan seperti blok match.
      Saya rasa ada nilai besar dalam mem-fork LuaJIT2 untuk memperbaiki struktur debugging dan error agar lebih sesuai dengan transparansi bahasa. Kalau itu dilakukan, bahasa seperti Fennel akan terlihat jauh lebih menarik
  • Penulis artikel ini dulu juga membuat tool-tool ini dengan Janet, yang pernah dibahas di HN
    https://bauble.studio
    https://toodle.studio
    Dua tool seni yang menarik ini sempat membuat saya cukup berharap pada Janet untuk beberapa waktu

  • Saya selalu senang melihat Janet mendapat perhatian. Salah satu fitur modern yang ingin saya soroti adalah sandbox
    “Menonaktifkan kumpulan kemampuan agar interpreter tidak dapat menggunakan resource sistem tertentu. Kemampuan yang sudah dinonaktifkan tidak bisa diaktifkan kembali.”
    https://janet-lang.org/api/misc.html#sandbox

    • Fitur yang sangat keren, tetapi saya penasaran situasi seperti apa yang membuat programmer rata-rata membutuhkan sandboxing seperti ini
  • Saat melihat “SETQ is def”, reaksi pertama saya adalah berkata keras-keras, “Apa?” Itu karena SETQ tidak membuat binding, melainkan hanya memperbaruinya.
    Setelah membaca dokumentasinya (https://janet-lang.org/docs/bindings.html), ternyata penulis memang salah, dan di sana tertulis bahwa “binding yang dibuat dengan def bersifat immutable”. Mungkin yang dimaksud sebenarnya adalah “SETQ is set”.
    Saya benar-benar ingin menyukai Janet, karena terlihat seperti titik yang pas di antara Guile, Tcl, dan CL, tetapi saya punya penolakan naluriah terhadap penggunaan vektor kurung siku untuk lambda dan operator alur kontrol. Saya juga merasakan hal yang sama pada Clojure sehingga sulit sekali melewatinya, tetapi mungkin dengan cukup usaha saya bisa terbiasa.
    Dan saya juga penasaran bagaimana keadaan LSP/SLIME saat ini. Sekarang itu cukup penting

    • Penggunaan kurung siku dalam sintaks Clojure sangat konsisten dan cukup logis.
      Jika memakai kurung biasa, elemen pertama dari daftar menentukan bagaimana sisa daftar ditafsirkan. Misalnya, (func a b c) berarti pemanggilan fungsi, (macro x y z) berarti ekspansi makro, dan ([p q r] …) adalah tubuh fungsi “telanjang” yang dimulai dengan vektor parameter lalu diikuti ekspresi-eksekusi.
      Kurung siku dipakai ketika elemen-elemennya memiliki “jenis” yang sama dan elemen pertama tidak istimewa. Misalnya, (defn f [a b c] …) adalah kumpulan parameter yang sejenis dan parameter pertama tidak punya peran khusus, dan (let [a 1 b 2] …) juga merupakan kumpulan binding di mana binding pertama tidak istimewa.
      Satu-satunya pengecualian yang terpikir adalah saat case mengelompokkan beberapa elemen pencocokan, tetapi itu demi kenyamanan. Setelah saya memahami logika ini, pandangan saya berubah, dan sejak itu saya justru merasa sintaks ini indah
    • Anda bahkan tidak perlu memakai kurung siku dan kurung kurawal. Alih-alih [1 2 3], Anda bisa menulis (array 1 2 3), dan alih-alih (fn [x] (+ 1 x)), Anda bisa menulis (f (x) (+ 1 x))
      Itu tidak wajib
    • Jika Anda memahami bagaimana destructuring bekerja di Clojure, peran kurung siku menjadi jauh lebih jelas
  • Untuk skrip sistem yang melebihi panjang tertentu, Janet bagiku menggantikan sh, Python, awk, dan lainnya
    Waktu startup eksekusi skripnya sangat cepat, dan di sistemku menurut hyperfine sekitar 1,4 ms, mirip dengan 1 ms milik dash. Ini berdasarkan skrip, bukan executable yang dikompilasi
    Berkat modul sh-dsl, perintah shell bisa ditulis dengan sangat elegan seperti ($ cmda w x | cmdb y z). Fitur untuk memuat image demi debugging juga sangat membantu
    Aku baru mulai memakainya belum lama ini, tapi rasanya ini sudah akan jadi salah satu bahasa favoritku, dan Lisp lain yang pernah kupakai sebelumnya cuma MIT Scheme untuk SICP

    • Bagiku babashka yang menggantikan sh, Python, awk, dan lainnya
  • Tulisan ini terasa segar. Masih ada aroma diskusi pra-AI di internet
    Ada bahasa baru, sintaks baru, dan perdebatan sengit dari orang-orang yang sudah bertahun-tahun menulis kode. Akan bagus kalau ada seseorang yang memulai komunitas online yang tidak mengizinkan AI

    • Kalau tidak mengikuti perkembangan belakangan ini, peluncuran ulang terbaru digg.com gagal karena tidak mampu menghadapi serbuan bot
      Sebenarnya mungkin lebih tepat menyebutnya peluncuran ulang sebelumnya, dan sekarang sepertinya sudah ada homepage baru lagi. Orang pertama yang menemukan cara andal untuk memblokir AI di komunitas online kemungkinan besar akan menjadi sangat kaya
      https://www.techspot.com/news/111698-digg-relaunch-fails-two...
    • Aku sering memikirkan bagaimana caranya membangun komunitas online yang tidak mengizinkan AI. Yang sulit terutama adalah melakukannya tanpa merusak anonimitas online
      Semacam “bukti kemanusiaan” adalah masalah yang sulit dipecahkan
    • Hal menakjubkan tentang AI adalah, bahkan kalau kamu bukan pendukung fanatik AI, AI tetap bisa disisipkan ke percakapan yang tidak ada hubungannya dengan AI. Para penentangnya yang melakukannya untukmu
    • Tempat seperti itu mungkin lobsters. Setelah diskusi besar, mungkin yang terbesar dalam sejarah situs itu, dengan lebih dari 300 komentar, tulisan AI pun dilarang
      Aturan persis yang ditetapkan admin adalah “karya manusia yang bermakna”, tapi jangan terkecoh. Di lobsters banyak orang yang secara ideologis menentang LLM. Seberapa “bermakna” teknologi itu diterapkan tidak terlalu penting
      Karyaku dikategorikan sebagai sampah hanya karena pernah tersentuh AI, dan ada juga orang yang menyebutku ekshibisionis atau punya fetish ketika aku bilang bahwa aku memakai AI. Rasanya ini perlu diberi tahu lebih dulu kepada orang yang mempertimbangkan untuk mendaftar
    • Ironisnya, komentar teratas ini sekarang malah jadi tentang AI
  • Kalimat seperti “dengan memungkinkan unquote pada fungsi literal, Janet bisa menulis macro yang sepenuhnya referentially transparent” membuat orang-orang Lisp tampak benar-benar bersemangat pada hal-hal yang sangat abstrak
    Kalau kamu mengatakan itu kepada orang biasa di jalan, mereka mungkin akan langsung kabur

    • Contoh macro C dengan literal yang tidak memiliki referential transparency seperti ini
      #define MULTIPLY(x, y) x * y
      int result = MULTIPLY(2 + 3, 4); // 14
      Hanya karena kamu tidak tahu arti suatu istilah bukan berarti istilah itu buruk. Dari ungkapannya, sepertinya memang itu maksud yang hendak disampaikan
      Punya bahasa bersama untuk pola dan masalah yang berulang dalam pemrograman adalah hal yang baik. Mengejek istilah dengan nada “kelompok programmer itu aneh sekali” tidak ada gunanya dan malah kontraproduktif
    • Aku penasaran apakah kamu pernah mencoba menjelaskan bahasa pemrograman berorientasi objek dan kelebihannya kepada orang biasa di jalan
    • Sekitar setahun lalu aku mulai menulis interpreter Scheme dan sudah berjalan cukup jauh. Beberapa bulan lalu aku berhenti setelah mendapat pekerjaan baru
      Aku sedang berpikir untuk melanjutkannya lagi, tapi masih ragu apakah fitur-fitur niche layak diimplementasikan. Bagiku itu juga sulit dibuat. Mungkin lebih baik melewati dynamic-unwind, mungkin juga membuang call/cc, lalu fokus pada kemudahan debugging, ekosistem, performa, dan manajemen paket
    • Hampir setiap kali aku ditanya “kerja apa?”, aku biasanya mendapat reaksi seperti itu
      Jadi aku bilang sangat samar seperti “saya kerja di bidang komputer”, atau “pekerjaannya tidak terlalu menarik”, lalu mencoba mengganti topik. Begitu sedikit lebih spesifik, orang-orang mulai mencari jalan keluar
    • Programmer rata-rata pun mungkin akan begitu
      Sejujurnya, menurutku komunitas keluarga Lisp justru mendapat manfaat karena ukurannya kecil. Misalnya, bahkan buku tua seperti Design Patterns sudah memperingatkan agar lebih memilih komposisi daripada pewarisan, tapi programmer berorientasi objek tetap saja membuat hierarki sedalam 15 tingkat
  • Saat pertama kali mengenal Janet, dokumen-dokumen ini sangat membantu
    https://janetdocs.org/tutorials
    https://janet.guide/ dibuat oleh penulisnya

  • Aku tertarik tiap kali ada tulisan tentang Janet yang sesekali muncul di HN, tapi Janet for Mortals yang sangat dipuji orang sama sekali tidak terasa seperti buku untuk manusia fana

    • Ada juga materi pengantar yang lebih ramah: https://janetdocs.org/tutorials
    • Mengejutkan. Bahasa ini sangat intuitif dan sederhana, dan aturan yang harus diingat juga sangat sedikit. Memang Lisp, tapi permukaannya sangat kecil
      Dibandingkan bahasa lain, Janet benar-benar termasuk yang mudah dipelajari, jadi mengejutkan kalau buku itu terasa sulit. Aku belum membaca bukunya, tapi cukup akrab dengan bahasanya, dan sejujurnya yang bisa kulakukan hanya memujinya
    • Secara pribadi, aku tersendat karena sintaks macro muncul terlalu awal, tapi setelah itu benar-benar banyak hal yang berharga
    • Aku merasakan hal seperti itu pada Haskell. Haskell terlalu sulit bagiku, tapi aku suka sintaksnya
      Janet terlihat seperti Lisp 2.0, jadi sintaksnya pun bergaya Lisp
 
GN⁺ 2 jam lalu
Komentar Lobste.rs
  • Setelah 10 bulan memakai Janet, saya sampai nyaris melupakan semua bahasa non-keluarga APL karena begitu tenggelam di dalamnya, dan sambil mengelola situs dokumentasi komunitas, saya juga sedang menulis tutorial
    Dalam 3 minggu pertama saya menulis ulang semua skrip pribadi saya, dan software operasional baru yang saya buat juga saya tulis dengan Janet
    Secara implementasi, hampir seluruh bahasa Janet bekerja seperti hash map, jadi simbol lokal bisa dilihat dengan (keys (curenv)), simbol inti dengan (keys (getproto (curenv))), dan kalau mau bahkan bisa membuat sesuatu yang mirip CLOS berbasis hash map; ada juga implementasinya
    Dengan framework web Joy, saya menjalankan sekitar 20 situs web dan beberapa layanan di satu VPS gratis 512MB, dan saya juga menulis tutorial terkait
    Namun, istilah “koleksi immutable” agak kurang tepat dengan kenyataannya; pustaka standarnya umumnya mengembalikan nilai yang mutable, jadi saat ini tidak banyak alasan untuk ngotot mengejar immutability
    Fitur yang meneruskan nilai waktu kompilasi ke waktu eksekusi terasa sangat kuat. Misalnya, jika .tsv Alkitab dimasukkan ke biner sebagai hash map saat kompilasi, maka saat runtime tinggal dilakukan lookup saja, dan hasilnya bahkan dua kali lebih cepat dibanding versi Go yang memakai embed
    Jika hal yang sama diimplementasikan manual di Go dalam bentuk hash map, kodenya jadi jauh lebih panjang, tetapi dengan Janet saya bahkan bisa membuat kompiler Lisp ke Go hanya dalam 46 baris
    Bagian yang menurut Ian Henry lebih menarik adalah bahwa Janet mempertahankan state closure antar image/sesi; jika lingkungan terkait disimpan di hash map (curenv) lalu dipulihkan di sesi REPL baru, state internal closure tetap berlanjut

    • Contoh keren yang dibuat dengan Janet adalah https://bauble.studio, dan ada juga tulisan proses pembuatannya di https://ianthehenry.com/posts/bauble/building-bauble/. Pemanfaatan WASM cukup menonjol
      Ada juga DSL musik berbasis Lisp di https://lisp.trane.studio/, serta paper https://dl.acm.org/doi/abs/10.1145/3677996.3678285 dan contoh hasilnya di https://x.com/greg_ash/status/1824218993118388708 yang layak dilihat
      Saya juga punya library buatan sendiri yang menyediakan sintaks query mirip SQL di atas berbagai struktur data
      Library itu mendukung insert·update dataframe serta simpan/muat CSV, dan juga mencakup Datalog dan miniKanren, plus operasi tervektorisasi ala APL
      Ada juga jnj yang memungkinkan memakai J langsung di Janet, dan Joy Web Framework punya DSL query DB seperti (var account (db/find-by :account :where {:login (auth-result :login)})), yang juga dipakai di kode autentikasi situs web nyata
    • Sepertinya ungkapan “koleksi immutable” di tulisan asli memang kurang akurat. Yang dimaksud lebih dekat ke tipe nilai komposit dan tipe referensi daripada koleksi
      Kalau mendengar “koleksi immutable”, yang terbayang biasanya struktur data persisten, dan meskipun itu berguna, itu bukan fitur dasar Janet
      Yang sebenarnya saya sukai adalah kesimetrian antara tipe nilai dan tipe referensi, dan meskipun di akhir tulisan tertulis “immutable composite values”, kalau itu bukan tulisan saya sendiri mungkin saya juga tidak akan langsung menangkap maksudnya
  • Janet terasa segar dan merupakan bahasa yang bisa di-embed, jadi saya ingin mencobanya untuk scripting bawaan di proyek seperti game engine
    Bahasa ini tampak cocok untuk tempat yang membutuhkan hot reload demi iterasi cepat tanpa mengganti DLL; Lua juga hebat, tetapi dalam beberapa hal Janet terlihat lebih ekspresif

  • Janet benar-benar keren sebagai bahasa, dan suatu hari saya ingin memakainya sebagai bahasa skrip di proyek Zig. Senang melihat semakin banyak orang membicarakan Janet

  • Kelihatannya bagus, tetapi saya sudah terbiasa dengan scripting Clojure lewat babashka, jadi rasanya mirip. Saya penasaran apakah ada kelebihan besar lain yang saya lewatkan selain kemampuan embed
    Bagian seperti “destructuring array dengan argumen sisa berpotensi menimbulkan copy yang mahal” membuatnya secara umum terasa kurang fungsional, dan saya kurang suka itu

    • Menurut saya, salah satu fitur killer Janet adalah dukungan bawaan untuk PEG. Itu benar-benar sangat praktis saat membuat DSL textbox untuk side project pengembangan game
      Setiap kali saya mem-parsing teks di bahasa lain, saya jadi merasa kehilangan fitur itu
    • Destructuring seperti itu bukan gaya yang sering dipakai, dan array/tuple Janet bukan linked list
      Daripada Clojure kecil yang bisa di-embed, Janet lebih mirip Lua dengan dukungan functional programming yang lebih baik