Pretty C 是一種與 C 相容的新腳本語言。而且它向後兼容 C 及其所有庫!受到 Lua、Python、JavaScript 和 Lisp 的啟發。以下是使用 Pretty C 簡單地重新實作head
實用程式的樣子:
#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 ;
}
Pretty C 的目標是:
#include
include - 可來自任意 C 檔案!),將任何程式碼庫變成初學者友好的程式碼庫。簽出儲存庫
git clone https://github.com/aartaka/pretty.c
或直接複製pretty.h
檔案-Pretty C 是僅包含頭檔的函式庫,因此您可以
#include "pretty.h"
從您將pretty.h
放入的目錄中的任何檔案。或實際上來自任何文件,如果您將 Pretty C 的路徑指定為包含 ( -I
) 路徑。
以下是讓 C 再次流行的所有漂亮變化。
true
、 false
和bool
。uint64_t
。&&
的and
和||
的or
。整潔的! 每個人都定義了這些,那麼為什麼不提供它們呢?
max
和min
。len
為數組長度。default
提供後備值。limit
以確保正確的值範圍。between
檢查數字是否在某個範圍內。divisible
檢查一個數字是否可以被另一個數字模整除。 輸入別名:
string
== char*
。byte
== char
。bytes
== char*
。any
== void*
。uchar
。ushort
。uint
。ulong
. 主要模仿Lua和Lisp:
eq
,因為iso646.h
只有not_eq
。is
也意味著==
。bitnot
和bitxor
用於在iso646.h
中呼叫不一致的操作(分別為compl
和xor
)。success == 0
模式的success
與fail
/ failure
。below
、 above
、 upto
和downto
比較運算子。even
、 odd
、 positive
、 negative
、 zero
和empty
作為數字/資料的謂詞。nil
代表NULL
。until
取反while
。elif
為else if
。ifnt
代表if(!...)
和elifnt
(你猜對了。)repeat
Lua 作為do
的別名。done~/~finish
和pass
分別作為break
和continue
別名。always
、 forever
、 loop
和indefinitely
以便您可以進行無限(事件?伺服器?)循環 always println ( "After all this time?" );
never
和comment
只用一個關鍵字註解掉一些程式碼,同時仍然允許編譯器分析/最佳化它(類似於 Clojure comment
形式): never println ( "This never runs, but never gets outdated, because compiler will shout at you if it does." );
是的,你可以做
var t = time ( 0 );
let lt = localtime ( & t );
local at = asctime ( lt );
println ( at );
和漂亮的C.
print
列印你輸入的任何內容。 println
在其後加上一個換行符。
println ( 3.1 );
print ( "Hello world!n" );
比較所有的事情!
equal ( "NA" , line ); // true
equal ( 0.3 , 0.2 + 0.1 ); // true
三元數很可怕,所以添加一些純文字也沒什麼壞處。 if
和else
被採用,但是有一些看起來很像 Python/Lisp 的適當的語言替代方案:
return when some_condition
then do_something ()
other do_something_else ();
下面是三元組:
when
擴展為空字串,僅為了可讀性而提供。unless
擴展為not
when
的負版本。then
擴展到?
。other
/ otherwise
擴充為:
. only
當不需要otherwise
子句時才適用:
return when done ()
then 42 only ;
和otherwhen
為下一個條件
return when c is 'A'
then 'a'
otherwhen c is 'B'
then 'b' only ;
for
宏這些巨集是某些for
迴圈模式的別名,每個巨集都抽象化了一些頻繁的for
迴圈使用。
foreach (var, type, length, ...)
此函數遍歷初始化為 vararg 表達式的陣列或記憶體區域。每次迭代時, var
都會被設定為指向對應數組元素的指標。是的,指標-這樣您就可以在必要時修改元素。
foreach ( i , int , 10 , vector ( 10 , int , 1 , 2 , 3 , 3 , 4 , 5 ))
println ( * i );
也展示了vector
的使用。
forthese (var, type, ...)
迭代提供的可變參數,將每個可變參數綁定到type
-d var
。上面的循環可以翻譯為:
forthese ( i , int , 1 , 2 , 3 , 3 , 4 , 5 )
println ( i );
fortimes (var, times)
從 0 到某個正數的常見情況。為您節省相當多的時間
for ( int i = 0 ; i < 28 ; i ++ )
println ( i + 1 );
把它變成一個簡單的
fortimes ( i , 28 )
println ( i + 1 );
println ( "28 stab wounds, you didn't want to leave him a chance, huh?" );
forrange (var, init, target)
迭代從init
到target
的一系列數字。蟒蛇式的。這是使用forrange
攝氏溫度到華氏溫度的轉換循環:
forrange ( c , -10 , 20 )
printf ( "Celsius %i = Fahrenheit %fn" , c , ( 32 + ( c * 1.8 )));
注意, init
和target
是任意整數,有符號和無符號。且init
可能大於target
,在這種情況下迭代步驟會減少變數。
forrangeby (var, type, init, target, by)
將type
-d var
從iter
迭代到target
,每次by
逐步執行。蟒蛇式的。
forrangeby ( x , double , 1.0 , 10.0 , 0.5 )
println ( x );
這些允許對典型模式進行快速而骯髒的分配。主要模仿 C++。
new (type, ...)
C++ new
運算子很好,所以在 C 中擁有類似的東西不會有什麼壞處,對吧?別再問了:
struct ListNode {
int val ;
struct ListNode * next ;
};
struct ListNode * node = new ( struct ListNode , 2 , new ( struct ListNode , 1 , nil ));
或者,如果您願意,您可以在上面添加更多語法:
#define cons ( val , ...) new(struct ListNode, val, __VA_ARGS__)
cons ( 2 , cons ( 1 , nil ));
vector (length, type, ...)
又是C++。 std::vector
是一種非常有用且通用的資料結構,很容易推理。雖然這個宏的功能遠遠不如 C++ 對應的宏,但它簡化了「分配這麼多元素和這些內容的陣列」的常見模式:
double * vec = vector ( 10 , double , 1 , 2 , 3 , 4 , 5 );
delete (...)
如果您不喜歡free
資源並且更喜歡更漂亮的 C++ 名稱。
否則與free
一樣。
它們建立新的本地綁定,確保延遲計算,或以其他方式作用於它們之後的區塊。
lambda (ret, name, ...)
(GCC、Clang 或 C++)巢狀函數/lambdas/閉包,現在用 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, ...)
這可以確保您永遠不會出現釋放後使用,因為您預先提供了釋放過程( close
)。對於動態分配的物件和文件指示符特別有用。
with ( file , fclose , fopen ( "hello.txt" , "w" ))
fprintf ( file , "Hello world!n" );
缺點之一是綁定的var
是void *
,因此您可能需要在使用它之前將其強制為您的類型。
defer (...)
卸載要在下一個區塊之後執行的程式碼。不像 Go 中那樣在函數末尾,因為那是不可能的在 C 中很難defer
。
try
並catch
花哨的錯誤處理,現在在 C 中。
try log ( 0.0 );
catch ( NOERR )
println ( "No error." );
catch ( EDOM , ERANGE )
println ( "Math error!" );
Pretty C 還提供了NOERR
和NOERROR
,以方便錯誤切換。
make indent
,這應該可以處理大部分樣式細節。