3 poin oleh GN⁺ 2024-10-25 | 1 komentar | Bagikan ke WhatsApp
  • Pretty C adalah bahasa scripting baru yang kompatibel dengan C, yang menambahkan fitur kemudahan seperti dynamic typing, iterasi generik, dan pelacakan resource ke program C
  • Cara menggunakannya adalah sebagai library header-only yang cukup menyertakan satu pretty.h, dan dapat dipakai bersama file C serta library C yang sudah ada
  • Fitur yang disediakan mencakup alias seperti string, any, nil, inferensi tipe var/let, output generik print/println, perbandingan generik equal, serta makro ekspresi ternary yang lebih mudah dibaca
  • Untuk mengurangi pekerjaan iterasi dan memori, tersedia sintaks berbasis makro seperti foreach, forthese, fortimes, forrange, new, vector, delete, with, lambda, try/catch
  • Beberapa fitur memiliki syarat seperti GCC, Clang, C23+, C11+, dan variabel yang dibungkus dengan with bertipe void * sehingga mungkin perlu dikonversi tipe sebelum digunakan

Tujuan dan Cara Penggunaan Pretty C

  • Pretty C adalah bahasa scripting yang kompatibel dengan C, yang menambahkan dynamic typing, iterasi generik, pelacakan resource, dan berbagai kemudahan sintaks ke program C
  • Mempertahankan kompatibilitas mundur dengan C dan library C yang sudah ada
  • Terinspirasi oleh Lua, Python, JavaScript, dan Lisp
  • Instalasi dapat dilakukan dengan meng-clone repository atau cukup menyalin file pretty.h
    • Dapat disertakan dari file C mana pun dengan #include "pretty.h"
    • Juga dapat digunakan dengan menentukan path Pretty C pada include path

Header Bawaan dan Makro Sederhana

  • Pretty C menyertakan header standar agar tipe yang sering digunakan dan ekspresi pengganti operator bisa langsung dipakai
    • stdbool.h: true, false, bool
    • stdint.h: tipe integer fixed-width seperti uint64_t
    • iso646.h: operator alternatif seperti and sebagai pengganti &&, or sebagai pengganti ||
  • Juga menyediakan makro sederhana yang sering didefinisikan
    • max, min: nilai maksimum dan minimum dari dua angka
    • len: panjang array
    • default: menyediakan nilai fallback
    • limit: membatasi rentang nilai
    • between: memeriksa apakah angka berada dalam rentang
    • divisible: memeriksa apakah habis dibagi oleh angka lain

Tipe dan Alias

  • Pretty C menyediakan alias tipe pendek untuk tipe C
    • string adalah char*
    • byte adalah char
    • bytes adalah char*
    • any adalah void*
    • Menyediakan singkatan integer uchar, ushort, uint, ulong
  • Juga mencakup alias sintaks yang dipengaruhi oleh Lua dan Lisp
    • eq, is: ==
    • bitnot, bitxor: alias operasi bit
    • success, fail, failure: alias untuk pola success == 0
    • below, above, upto, downto: operator perbandingan
    • even, odd, positive, negative, zero, empty: predicate untuk angka dan data
    • nil: NULL
    • until: while negatif
    • elif: else if
    • ifnt, elifnt: ekspresi keluarga if(!...)
    • repeat: alias do ala Lua
    • done, finish, pass: alias break, continue
    • always, forever, loop, indefinitely: ekspresi loop tanpa batas
    • never, comment: ekspresi yang tidak menjalankan kode tetapi tetap memungkinkan compiler menganalisisnya

Inferensi Tipe, Output, Perbandingan, Ekspresi Ternary

  • Inferensi tipe dapat digunakan di GCC, Clang, atau C23+
    • Contohnya menyediakan bentuk seperti var t = time(0);, let lt = localtime(&t);, local at = asctime(lt);
  • Output generik dapat digunakan di C11+
    • print mencetak nilai yang diberikan
    • println menambahkan baris baru setelah output
  • Perbandingan kesetaraan generik juga disediakan sebagai fitur C11+
    • Perbandingan string seperti equal("NA", line)
    • Termasuk contoh perbandingan seperti equal(0.3, 0.2 + 0.1)
  • Operator ternary dapat dibuat lebih mudah dibaca dengan makro berbasis teks
    • when diekspansi menjadi string kosong untuk keterbacaan
    • unless diekspansi menjadi not dan berfungsi sebagai bentuk negatif dari when
    • then adalah ?
    • other dan otherwise adalah :
    • only digunakan ketika klausa otherwise tidak diperlukan
    • otherwhen digunakan untuk menyambungkan kondisi berikutnya

Makro Iterasi

  • Pretty C mengabstraksikan pola loop for yang sering digunakan menjadi makro
  • foreach (var, type, length, ...)
    • Menelusuri array atau area memori
    • Pada setiap iterasi, var menjadi pointer ke elemen array tersebut
    • Karena berupa pointer, elemen dapat dimodifikasi langsung di tempat bila perlu
  • forthese (var, type, ...)
    • Menelusuri argumen variadik yang diberikan dan mengikat setiap nilai ke var bertipe type
  • fortimes (var, times)
    • Mempersingkat pola umum yang mengulang dari 0 hingga jumlah positif tertentu
  • forrange (var, init, target)
    • Menelusuri rentang angka dari init hingga target
    • init dan target dapat berupa integer signed atau unsigned apa pun
    • Jika init lebih besar dari target, langkah iterasi akan menurun
  • forrangeby (var, type, init, target, by)
    • Menelusuri var bertipe type dari init hingga target dengan interval by

Alokasi dan Utilitas Blok

  • Makro alokasi menyederhanakan pola alokasi memori umum dalam bentuk yang dipengaruhi oleh C++
    • new (type, ...): membuat struct dan sejenisnya dalam bentuk yang mirip C++ new
    • vector (length, type, ...): menyederhanakan pola untuk mengalokasikan array dengan panjang dan tipe tertentu lalu mengisi konten awalnya
    • delete (...): sama dengan free, tetapi dapat digunakan bila lebih menyukai nama ala C++
  • Utilitas blok menyediakan makro untuk binding lokal, eksekusi tertunda, dan pekerjaan berbasis blok
    • lambda (ret, name, ...): memungkinkan penggunaan nested function, lambda, dan closure di C pada GCC, Clang, atau C++
    • with (var, close, ...): berguna untuk objek yang dialokasikan secara dinamis atau file handle dengan menyediakan fungsi pelepas resource close terlebih dahulu
      • Kekurangannya, var yang di-binding bertipe void *, sehingga mungkin perlu dikonversi ke tipe yang diinginkan sebelum digunakan
    • defer: telah dihapus, dan diarahkan untuk menggunakan defer baru yang tersedia
    • try dan catch: memungkinkan penulisan error handling di C dalam bentuk yang lebih bergaya
    • NOERR, NOERROR: disediakan untuk kemudahan switch-case error

Cara Berkontribusi

1 komentar

 
GN⁺ 2024-10-25
Opini Hacker News
  • Tradisi membuat bahasa khusus domain di dalam C sudah lama ada
    Stephen Bourne ingin menulis shell dengan gaya ALGOL, jadi ia terus-menerus “menghajar” preprosesor C sampai akhirnya tampak seperti bahasa yang ia sukai
    https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh...

  • Saya bertanya-tanya apakah ada yang bisa menjelaskan apakah ini lelucon, atau penulisnya benar-benar bingung
    Tidak ada yang masuk akal. Ini bukan “scripting”, katanya memperkenalkan “strong typing” tetapi tidak melakukan apa pun pada tipe, dan alias operator yang katanya meniru Lua dan Lisp justru tidak ada di kedua bahasa itu. Namun ini juga tidak terlihat seperti parodi yang jelas, jadi benar-benar membingungkan

    • Sepertinya memang serius. Katanya, “Buang Lua, Python, JavaScript, Ruby, dan puluhan bahasa lain. Pretty C adalah bahasa scripting pamungkas, secepat kilat, dan bahkan punya strong typing!!”
    • Saya sama sekali tidak berpikir penulisnya sedang bingung. Tentu saja, menjadi membingungkan itu sendiri tidak apa-apa
  • Mengklaim sebagai bahasa scripting, tetapi programnya tetap harus dikompilasi. Patut disoraki sinis
    Kalau dipasangi CINT(https://root.cern.ch/root/html534/guides/users-guide/CINT.ht...), bisa langsung dijalankan dan REPL juga memungkinkan

    • Kalau tujuan repositori ini adalah menimbulkan penderitaan, bukankah bisa menambahkan shebang ke file agar bisa dieksekusi? [0]
      Dulu saya pernah membaca posting blog yang membahas secara detail bagaimana ./foo bekerja dan bagaimana file ELF dieksekusi. Dengan cara yang sama, tampaknya program .c juga bisa didaftarkan agar dikompilasi lalu dijalankan
      [0] https://gist.github.com/jdarpinian/1952a58b823222627cc1a8b83...
    • Lebih baik pakai tcc saja [0]. Jauh lebih ringan daripada monster itu, dan ini C, bukan C++
      [0] https://bellard.org/tcc/tcc-doc.html
    • CERN sekarang memakai cling (https://github.com/root-project/cling)
    • Siapa yang menentukan bahwa bahasa scripting tidak boleh dikompilasi? Dan Clang-REPL juga cara lain untuk membuatnya ramah REPL
  • “Memberikan syntactic sugar yang cukup untuk membuat developer C terkena serangan jantung diabetik.”
    Saya sangat suka kalimat ini

  • Saya melihat beberapa hal yang perlu ditambahkan ke CNoEvil[0] dan ogw[1]. Setiap kali proyek ini muncul lagi setiap beberapa bulan, sepertinya selalu ada tambahan baru
    [0] https://git.sr.ht/~shakna/cnoevil3/
    [1] https://git.sr.ht/~shakna/ogw

    • “Mengambil banyak sekali ide buruk dan menjejalkannya menjadi monster menjijikkan.”
      Ini kalimat yang dengan tulus saya cintai dari lubuk hati
  • Ini mengulangi kesalahan yang sama seperti Python 2. String dan byte bukan tipe yang sama, dan tidak boleh diperlakukan seperti itu

    • Teks shell, yaitu nilai di dalam argv atau keluaran subprocess, sebaiknya dianggap bertipe apa?
      Di sana bisa berisi nilai sampah arbitrer, jadi bukan string UTF-8 yang valid, tetapi alat seperti awk dan grep dipakai di mana-mana
      String dan byte bisa dianggap sebagai tipe umum yang sama, hanya saja kadang berguna memberi tipe internal yang berbeda untuk byte UTF-8 yang valid. Rust menangani bagian ini dengan cukup baik lewat OsString dan String
    • Karena proyek ini pretty.c dan katanya dimaksudkan untuk “kompatibel ke belakang dengan C serta semua library”, pilihan apa yang lebih masuk akal daripada mempertahankan string multibyte C?
      https://en.cppreference.com/w/c/string/multibyte
    • Saya tidak setuju. Prinsip ini mengandaikan semua premis berikut: data string dienkode dengan benar, hanya ada satu encoding string (biasanya UTF-8), data string harus divalidasi saat dibuat, memotong code point logis sama sekali tidak boleh, operasi string tidak boleh dilakukan pada byte yang “tidak valid”, dan encoding yang benar adalah awal sekaligus akhir dari validasi
      Tidak satu pun dari itu selalu benar. Membungkus urutan byte yang tervalidasi dalam tipe yang hanya bisa dibuat lewat validasi memang berguna, tetapi setelah itu Utf8String dan EmailAddress pada dasarnya berada dalam kategori yang sama. Tidak ada alasan untuk memperlakukan encoding secara istimewa dalam sistem tipe
    • Tergantung bagaimana Anda mendefinisikan “string”
      Jika maksudnya “teks yang bisa dibaca manusia”, saya setuju bahwa string tidak sama dengan array byte arbitrer. Namun banyak bahasa tidak memaksakan definisi itu
  • Teringat sebuah codebase C++ yang dulu harus saya periksa. Seluruhnya dibuat seolah-olah ditulis dalam Java: camel case untuk semuanya, getter/setter untuk setiap variabel kelas, dan interface di mana-mana

    • Berarti belum melihat yang benar-benar parah. Lihat source Bourne shell dari Unix Seventh Edition
      https://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd...
      Sulit dipercaya bahwa itu bukan ALGOL
    • Camel case, getter/setter, dan interface dalam banyak kasus tidak jauh berbeda dari pedoman. Misalnya kode Windows seperti itu, tentu saja tidak sampai semua variabel. Banyak bagian desain Java juga disalin dari C++
    • Saya pernah melihat codebase serupa yang ditulis oleh orang-orang yang terlalu lama memakai Java. Bahkan ada kelas String buatan sendiri yang sebenarnya hanya membungkus std::string, tetapi diberi metode ala Java
    • Sepertinya untung tidak memakai MSVC
      https://learn.microsoft.com/en-us/cpp/cpp/property-cpp?view=...
    • Saya juga pernah mengalami yang seperti itu, ditambah lagi string dikirim seperti Java sebagai f(String *), jadi kode C++-nya berbentuk f(new String("Hello")
  • Kalau ini menarik, mungkin Anda juga akan suka libcello.h
    https://www.libcello.org

    • Benar, itu salah satu inspirasinya
  • Nama-nama tipenya bagus, dan pilihan makro fungsi bawaan seperti min juga sempurna. Saya juga suka Len
    Operator boolean bernama mungkin agak berlebihan, tetapi layak dicoba, dan operator ternary memang sulit dibaca, jadi masih banyak ruang untuk perbaikan. Saya belum sepenuhnya yakin dengan semua definisi loop, tetapi sebagian masuk akal. Pelacakan resource mengesankan, dan bentuk for... agak kurang enak dilihat, jadi mungkin bisa diberi nama lain
    Secara keseluruhan ini upaya yang cukup solid. Untuk desainnya saya ingin memberi sekitar 8/10. Cara mensketsanya dengan makro C benar-benar elegan dan tampak seperti kode yang memang bagus. Entah apakah saya akan memakainya langsung. Ini bahasa baru, dan saya sudah menyukai C. Meski begitu, cara implementasinya sangat jelas, jadi bisa membantu orang belajar C dan memikirkan desain bahasa

    • Tidak perlu memakai semuanya. Proyek-proyek saya umumnya hanya memakai boolean, len(), max/min, dan beberapa makro operator. Soalnya saya belum terlalu membutuhkan banyak fitur lezat lainnya. Jadi sebaiknya coba saja beberapa makro operator dulu
  • Kalau ifnt untuk if(!...), unless tampaknya lebih mudah dibaca daripada ifnt

    • Sebagai bahan perdebatan nama lain, loop tak hingga for(;;) juga bisa disebut always
      Di bahasa lain saya pernah melihat loop. Tapi Qt menyebutnya forever, dan itu benar-benar cantik. Sangat khas Qt juga
    • Sebaliknya, ifnt lucu kalau diucapkan keras-keras
    • Benar. Tapi unless saya sisakan untuk kondisi ternary. Karena di sana bagaimanapun lebih berguna
      Ah, tunggu, ini John Tromp. Pembuat BLC! Saya penggemarnya