Pretty C adalah bahasa skrip baru yang kompatibel dengan C. Pretty C meningkatkan program Anda dengan pengetikan dinamis, iterasi umum, pelacakan sumber daya, dan fasilitas lainnya. Dan itu kompatibel dengan C dan semua perpustakaannya! Terinspirasi oleh Lua, Python, JavaScript, dan Lisp. Berikut tampilan implementasi ulang utilitas head
yang naif dengan Pretty C:
#include "pretty.h"
int main ( int argc , string argv [])
{
if ( argc above 1 )
with ( f , fclose , fopen ( argv [ 1 ], "r" ))
fortimes ( line , 10 )
with ( buf , free , vector ( 200 , char , 0 ))
when ( fgets ( buf , 200 , f ))
then print ( buf )
otherwise 0 ;
else
println ( "Please provide an input file" );
return EXIT_SUCCESS ;
}
Tujuan dari Pretty C adalah:
#include
-able dari file C sembarang!) untuk mengubah basis kode apa pun menjadi basis kode yang ramah bagi pemula.Periksa repositori
git clone https://github.com/aartaka/pretty.c
Atau cukup salin file pretty.h
—Pretty C adalah perpustakaan khusus header, jadi Anda bisa
#include "pretty.h"
dari file apa pun di direktori tempat Anda meletakkan pretty.h
. Atau sebenarnya dari file apa pun, jika Anda menentukan jalur ke Pretty C sebagai jalur penyertaan ( -I
).
Inilah semua perubahan cantik yang membuat C kembali keren.
true
, false
, dan bool
.uint64_t
.and
untuk &&
dan or
untuk ||
. Rapi! Semua orang mendefinisikannya, jadi mengapa tidak menyediakannya?
max
dan min
dari dua angka.len
untuk panjang array.default
untuk memberikan nilai cadangan.limit
untuk memastikan kisaran nilai yang tepat.between
untuk memeriksa apakah angkanya berada dalam suatu kisaran.divisible
untuk memeriksa apakah suatu bilangan modulo habis dibagi bilangan lain. Ketik alias:
string
== char*
.byte
== char
.bytes
== char*
.any
== void*
.uchar
.ushort
.uint
.ulong
. Terutama dimodelkan setelah Lua dan Lisp:
eq
, karena iso646.h
hanya memiliki not_eq
.is
==
juga.bitnot
dan bitxor
untuk operasi yang dulunya dipanggil secara tidak konsisten ( compl
dan xor
masing-masing) di iso646.h
.success
dan fail
/ failure
untuk pola success == 0
.below
, above
, upto
, dan downto
.even
, odd
, positive
, negative
, zero
, dan empty
sebagai predikat angka/data.nil
untuk NULL
.until
untuk dinegasikan while
.elif
untuk else if
.ifnt
untuk if(!...)
dan elifnt
(coba tebak.)repeat
dari Lua sebagai alias untuk do
.done~/~finish
dan pass
sebagai alias untuk break
dan continue
.always
, forever
, loop
, dan indefinitely
sehingga Anda dapat membuat loop tak terbatas (event? server?). always println ( "After all this time?" );
never
dan comment
untuk mengomentari beberapa kode hanya dengan satu kata kunci, sambil tetap mengizinkan kompiler untuk menganalisis/mengoptimalkannya (mirip dengan formulir comment
Clojure): never println ( "This never runs, but never gets outdated, because compiler will shout at you if it does." );
Ya, Anda bisa melakukannya
var t = time ( 0 );
let lt = localtime ( & t );
local at = asctime ( lt );
println ( at );
Dengan Cantik C.
print
apa pun yang Anda berikan. println
menambahkan baris baru setelahnya.
println ( 3.1 );
print ( "Hello world!n" );
Bandingkan semua hal!
equal ( "NA" , line ); // true
equal ( 0.3 , 0.2 + 0.1 ); // true
Terner memang menakutkan, jadi tidak ada salahnya menambahkan beberapa teks biasa. if
dan else
diambil, tetapi ada alternatif linguistik yang tepat yang terlihat mirip Python/Lisp:
return when some_condition
then do_something ()
other do_something_else ();
Ada terner di bawahnya:
when
diperluas ke string kosong dan hanya disediakan untuk keterbacaan.unless
diperluas menjadi not
versi negatif dari when
.then
meluas menjadi ?
.other
/ otherwise
diperluas ke :
. Ada juga only
ketika klausa otherwise
tidak diperlukan:
return when done ()
then 42 only ;
dan otherwhen
untuk kondisi selanjutnya
return when c is 'A'
then 'a'
otherwhen c is 'B'
then 'b' only ;
for
Makro Makro ini adalah alias untuk pola perulangan for
tertentu, yang masing-masing mengabstraksi beberapa penggunaan perulangan for
yang sering dilakukan.
foreach (var, type, length, ...)
Yang ini menjalankan array atau wilayah memori yang diinisialisasi ke ekspresi vararg. Setiap kali diulang, var
disetel ke penunjuk ke elemen array masing-masing. Ya, penunjuk—sehingga Anda dapat memodifikasi elemen di tempatnya jika perlu.
foreach ( i , int , 10 , vector ( 10 , int , 1 , 2 , 3 , 3 , 4 , 5 ))
println ( * i );
Juga menunjukkan penggunaan vector
.
forthese (var, type, ...)
Ulangi vararg yang disediakan, ikat masing-masing vararg ini menjadi type
-d var
. Loop di atas dapat diterjemahkan sebagai:
forthese ( i , int , 1 , 2 , 3 , 3 , 4 , 5 )
println ( i );
fortimes (var, times)
Kasus yang sering terjadi dari 0 ke bilangan positif. Menghemat waktu Anda
for ( int i = 0 ; i < 28 ; i ++ )
println ( i + 1 );
mengubahnya menjadi sederhana
fortimes ( i , 28 )
println ( i + 1 );
println ( "28 stab wounds, you didn't want to leave him a chance, huh?" );
forrange (var, init, target)
Ulangi rentang angka dari init
ke target
. ular piton. Berikut loop konversi Celcius ke Fahrenheit dengan forrange
:
forrange ( c , -10 , 20 )
printf ( "Celsius %i = Fahrenheit %fn" , c , ( 32 + ( c * 1.8 )));
Perhatikan bahwa init
dan target
adalah bilangan bulat arbitrer, bertanda tangan dan tidak bertanda tangan. Dan init
mungkin lebih besar dari target
dalam hal ini langkah iterasi menurunkan variabel.
forrangeby (var, type, init, target, by)
Ulangi type
-d var
dari iter
ke target
, by
setiap saat. ular piton.
forrangeby ( x , double , 1.0 , 10.0 , 0.5 )
println ( x );
Ini memungkinkan alokasi cepat dan kotor untuk pola-pola tertentu. Sebagian besar dimodelkan setelah C++.
new (type, ...)
Operator new
C++ itu bagus, jadi tidak ada salahnya memiliki sesuatu yang serupa di C, bukan? Jangan bertanya lagi:
struct ListNode {
int val ;
struct ListNode * next ;
};
struct ListNode * node = new ( struct ListNode , 2 , new ( struct ListNode , 1 , nil ));
Atau, jika mau, Anda dapat menambahkan lebih banyak sintaksis di atasnya:
#define cons ( val , ...) new(struct ListNode, val, __VA_ARGS__)
cons ( 2 , cons ( 1 , nil ));
vector (length, type, ...)
C++ lagi. std::vector
adalah struktur data yang sangat berguna dan serbaguna yang mudah untuk dipikirkan. Meskipun makro ini bahkan tidak memiliki fitur yang sama seperti versi C++, makro ini menyederhanakan pola umum “mengalokasikan array dengan elemen sebanyak itu dan dengan konten berikut”:
double * vec = vector ( 10 , double , 1 , 2 , 3 , 4 , 5 );
delete (...)
Jika Anda tidak suka free
sumber daya dan lebih memilih nama C++ yang lebih bagus.
Kalau tidak, sama saja dengan free
.
Ini menetapkan pengikatan lokal baru, memastikan penghitungan yang ditangguhkan, atau bertindak berdasarkan blok setelahnya.
lambda (ret, name, ...)
(GCC, Dentang, atau C++)Fungsi bersarang/lambdas/penutupan, sekarang di C!
int * arr = vector ( 10 , int , 23423 , 23423 , 234 , 5233 , 6 , 4 , 34 , 643 , 3 , 9 );
lambda ( int , cmp , int * a , int * b ) {
return * a - * b ;
};
qsort ( arr , 10 , sizeof ( int ), cmp );
// arr becomes {3, 4, 6, 9, 34, 234, 643, 5233, 23423, 23423}
with (var, close, ...)
Hal ini memastikan bahwa Anda tidak pernah memiliki penggunaan setelah bebas, karena Anda menyediakan prosedur pembebasan ( close
) dimuka. Sangat berguna untuk objek dan penunjuk file yang dialokasikan secara dinamis.
with ( file , fclose , fopen ( "hello.txt" , "w" ))
fprintf ( file , "Hello world!n" );
Salah satu kelemahannya adalah var
yang terikat adalah void *
, jadi Anda mungkin perlu memaksakannya ke tipe Anda sebelum menggunakannya.
defer (...)
Membongkar kode yang akan dieksekusi setelah blok berikut. Bukan di akhir fungsi seperti di Go, karena itu mustahil sulit diterapkan di C. Namun, Pretty C defer
cukup berguna.
try
dan catch
Penanganan kesalahan yang bagus, sekarang di C. Contoh yang difaktorkan ulang dari referensi errno:
try log ( 0.0 );
catch ( NOERR )
println ( "No error." );
catch ( EDOM , ERANGE )
println ( "Math error!" );
NOERR
dan NOERROR
juga disediakan oleh Pretty C, untuk kemudahan error switch-casing.
make indent
sebelum melakukan, yang seharusnya menangani sebagian besar detail gaya.