Pretty C は、C と互換性のある新しいスクリプト言語です。Pretty 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
できるヘッダーのみのライブラリです!)、あらゆるコードベースを初心者に優しいコードベースに変えます。リポジトリをチェックアウトする
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
のような固定幅整数型の場合は stdint.h 。&&
and
や||
のor
など、通常の演算子の読み取り可能な代替演算子です。 。きちんとした! これらは誰もが定義しているので、なぜそれらを提供しないのでしょうか?
max
とmin
。len
。default
。limit
。between
使用して、数値が範囲内にあるかどうかを確認します。divisible
数値が別の数値で割り切れるかどうかを確認します。 タイプエイリアス:
string
== char*
。byte
== char
。bytes
== char*
。any
== void*
。uchar
。ushort
。uint
。ulong
。 主に Lua と Lisp をモデルにしています:
iso646.h
にはnot_eq
しかないため、 eq
。is
==
も意味します。iso646.h
で一貫性なく呼び出されていた操作 (それぞれcompl
とxor
) のbitnot
とbitxor
。success
とfail
/ 成功のパターンのfailure
success == 0
。below
、 above
、 upto
、およびdownto
比較演算子。even
、 odd
、 positive
、 negative
、 zero
、およびempty
使用します。NULL
の場合はnil
。while
until
。else if
のelif
。if(!...)
およびelifnt
の場合はifnt
(ご想像のとおりです。)do
のエイリアスとしてrepeat
。done~/~finish
とpass
、それぞれbreak
とcontinue
のエイリアスとして使用されます。always
、 forever
、 loop
、およびindefinitely
使用すると、無限 (イベント?サーバー?) ループを作成できます。 always println ( "After all this time?" );
comment
はnever
、コンパイラーによる分析/最適化を可能にします (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
空の文字列に展開され、読みやすくするためにのみ提供されます。when
の否定バージョンにならnot
ように展開するunless
除外されます。then
?
に展開されます。 。other
/ otherwise
:
に展開されます。 otherwise
句が不要な場合にonly
for もあります。
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, ...)
これは、可変長引数式に初期化された配列またはメモリ領域を調べます。反復するたびに、 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++)ネストされた関数/ラムダ/クロージャが 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" );
欠点の 1 つは、バインドされたvar
がvoid *
であるため、使用する前に型を強制する必要があることです。
defer (...)
次のブロックの後に実行されるコードをオフロードします。 Go のように関数の最後ではありません。不可能C で実装するのは難しいですが、それでも、Pretty C のdefer
は十分役に立ちます。
try
てcatch
派手なエラー処理が C になりました。errno リファレンスからのリファクタリングされた例:
try log ( 0.0 );
catch ( NOERR )
println ( "No error." );
catch ( EDOM , ERANGE )
println ( "Math error!" );
NOERR
とNOERROR
、エラー スイッチ ケースの便宜のために Pretty C によっても提供されています。
make indent
実行すると、ほとんどのスタイル詳細が処理されるはずです。