Pretty C ist eine neue Skriptsprache, die mit C kompatibel ist. Pretty C erweitert Ihre Programme durch dynamische Typisierung, generische Iteration, Ressourcenverfolgung und andere Feinheiten. Und es ist abwärtskompatibel mit C und allen seinen Bibliotheken! Inspiriert von Lua, Python, JavaScript und Lisp. So könnte eine naive Neuimplementierung des head
-Dienstprogramms mit Pretty C aussehen:
#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 ;
}
Die Ziele für Pretty C sind:
#include
-able aus einer beliebigen C-Datei!), um jede Codebasis in eine anfängerfreundliche Codebasis zu verwandeln.Schauen Sie sich das Repository an
git clone https://github.com/aartaka/pretty.c
Oder kopieren Sie einfach die Datei pretty.h
– Pretty C ist eine reine Header-Bibliothek, das können Sie also
#include "pretty.h"
aus einer beliebigen Datei in dem Verzeichnis, in das Sie pretty.h
ablegen. Oder eigentlich aus einer beliebigen Datei, wenn Sie den Pfad zu Pretty C als Include-Pfad ( -I
) angeben.
Hier sind all die hübschen Veränderungen, die C wieder hip machen.
true
, false
und bool
.uint64_t
.and
für &&
und or
für ||
. Sauber! Jeder definiert diese, warum also nicht sie bereitstellen?
max
und min
zweier Zahlen.len
für Array-Länge.default
für die Bereitstellung eines Fallback-Werts.limit
um den richtigen Wertebereich sicherzustellen.between
um zu prüfen, ob die Zahl in einen Bereich fällt.divisible
um zu prüfen, ob eine Zahl moduloteilbar durch eine andere Zahl ist. Geben Sie Aliase ein:
string
== char*
.byte
== char
.bytes
== char*
.any
== void*
.uchar
.ushort
.uint
.ulong
. Hauptsächlich nach Lua und Lisp modelliert:
eq
, weil iso646.h
nur not_eq
hat.is
==
auch.bitnot
und bitxor
für Vorgänge, die früher in iso646.h
inkonsistent aufgerufen wurden ( compl
bzw. xor
).success
und fail
/ failure
für success == 0
.below
, above
, upto
und downto
-Vergleichsoperatoren.even
, odd
, positive
, negative
, zero
und empty
als Prädikate für Zahlen/Daten.nil
für NULL
.until
für negiert while
.elif
für else if
.ifnt
für if(!...)
und elifnt
(Sie haben es erraten.)repeat
von Lua als Alias für do
.done~/~finish
und pass
als Aliase für break
bzw. continue
.always
, forever
, loop
und indefinitely
sodass Sie Endlosschleifen (Ereignis? Server?) erstellen können always println ( "After all this time?" );
never
und comment
um Code mit nur einem Schlüsselwort auszukommentieren, während der Compiler ihn dennoch analysieren/optimieren kann (ähnlich der Clojure- comment
): never println ( "This never runs, but never gets outdated, because compiler will shout at you if it does." );
Ja, das können Sie
var t = time ( 0 );
let lt = localtime ( & t );
local at = asctime ( lt );
println ( at );
Mit Pretty C.
print
druckt alles, was Sie ihm geben. println
fügt danach eine neue Zeile hinzu.
println ( 3.1 );
print ( "Hello world!n" );
Vergleichen Sie alle Dinge!
equal ( "NA" , line ); // true
equal ( 0.3 , 0.2 + 0.1 ); // true
Ternäre sind beängstigend, daher kann es nicht schaden, etwas Klartext hinzuzufügen. if
und else
werden verwendet, aber es gibt geeignete sprachliche Alternativen, die ziemlich Python/Lisp-ähnlich aussehen:
return when some_condition
then do_something ()
other do_something_else ();
Es sind Ternäre darunter:
when
es zu einer leeren Zeichenfolge erweitert wird, dient es nur der besseren Lesbarkeit.unless
wird dahingehend erweitert, dass es not
negative Version von when
ist.then
erweitert sich zu ?
.other
/ otherwise
wird erweitert zu :
. Es gibt auch only
dann, wenn die otherwise
Klausel unnötig ist:
return when done ()
then 42 only ;
und otherwhen
für die nächste Bedingung
return when c is 'A'
then 'a'
otherwhen c is 'B'
then 'b' only ;
for
Makros Diese Makros sind Aliase für bestimmte for
Schleifenmuster, die jeweils einige der häufigen for
Schleifenverwendungen abstrahieren.
foreach (var, type, length, ...)
Dieser durchläuft ein Array oder einen Speicherbereich, der mit dem vararg-Ausdruck initialisiert wurde. Bei jeder Iteration wird var
auf einen Zeiger auf das entsprechende Array-Element gesetzt. Ja, Zeiger – damit Sie das Element bei Bedarf ändern können.
foreach ( i , int , 10 , vector ( 10 , int , 1 , 2 , 3 , 3 , 4 , 5 ))
println ( * i );
Zeigt auch die Verwendung von vector
.
forthese (var, type, ...)
Iteriert über die bereitgestellten Varargs und bindet diese jeweils an type
-d var
. Die obige Schleife kann wie folgt übersetzt werden:
forthese ( i , int , 1 , 2 , 3 , 3 , 4 , 5 )
println ( i );
fortimes (var, times)
Ein häufiger Fall, bei dem von 0 auf eine positive Zahl übergegangen wird. Spart Ihnen viel Zeit für Ihre
for ( int i = 0 ; i < 28 ; i ++ )
println ( i + 1 );
es in ein einfaches verwandeln
fortimes ( i , 28 )
println ( i + 1 );
println ( "28 stab wounds, you didn't want to leave him a chance, huh?" );
forrange (var, init, target)
Iterieren Sie über einen Zahlenbereich von init
bis target
. Pythonesk. Hier ist die Umrechnungsschleife von Celsius in Fahrenheit mit forrange
:
forrange ( c , -10 , 20 )
printf ( "Celsius %i = Fahrenheit %fn" , c , ( 32 + ( c * 1.8 )));
Beachten Sie, dass init
und target
beliebige Ganzzahlen mit und ohne Vorzeichen sind. Und init
könnte größer als target
sein. In diesem Fall verringert der Iterationsschritt die Variable.
forrangeby (var, type, init, target, by)
Iterieren Sie type
-d var
von iter
bis target
und gehen Sie by
jedes Mal vorbei. Pythonesk.
forrangeby ( x , double , 1.0 , 10.0 , 0.5 )
println ( x );
Diese ermöglichen eine schnelle Zuordnung typischer Muster. Größtenteils nach C++ modelliert.
new (type, ...)
new
C++-Operator ist nett, also kann es nicht schaden, etwas Ähnliches in C zu haben, oder? Fragen Sie nicht mehr:
struct ListNode {
int val ;
struct ListNode * next ;
};
struct ListNode * node = new ( struct ListNode , 2 , new ( struct ListNode , 1 , nil ));
Wenn Sie möchten, können Sie auch noch mehr Syntax hinzufügen:
#define cons ( val , ...) new(struct ListNode, val, __VA_ARGS__)
cons ( 2 , cons ( 1 , nil ));
vector (length, type, ...)
Wieder C++. std::vector
ist eine äußerst nützliche und vielseitige Datenstruktur, über die man leicht nachdenken kann. Obwohl dieses Makro nicht annähernd so funktionsfähig ist wie das C++-Gegenstück, vereinfacht es ein häufiges Muster: „Ein Array mit so vielen Elementen und diesen Inhalten zuweisen“:
double * vec = vector ( 10 , double , 1 , 2 , 3 , 4 , 5 );
delete (...)
Für den Fall, dass Sie die Ressourcen nicht free
möchten und einen ausgefalleneren C++-Namen bevorzugen.
Sonst das Gleiche wie free
.
Diese stellen neue lokale Bindungen her, sorgen für verzögerte Berechnungen oder wirken auf andere Weise auf den Block nach ihnen ein.
lambda (ret, name, ...)
(GCC, Clang oder C++)Verschachtelte Funktionen/Lambdas/Abschlüsse, jetzt in 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, ...)
Dies stellt sicher, dass Sie nie wieder ein „Use-After-Free“-Verfahren haben, da Sie den Freigabevorgang ( close
) im Voraus durchführen. Besonders nützlich für dynamisch zugewiesene Objekte und Dateibezeichner.
with ( file , fclose , fopen ( "hello.txt" , "w" ))
fprintf ( file , "Hello world!n" );
Einer der Nachteile besteht darin, dass die gebundene var
ein void *
ist, sodass Sie sie möglicherweise vor der Verwendung in Ihren Typ umwandeln müssen.
defer (...)
Lädt den Code aus, der nach dem folgenden Block ausgeführt werden soll. Nicht am Ende der Funktion wie in Go, denn das ist unmöglich in C schwer zu implementieren. Dennoch ist Pretty C defer
nützlich genug.
try
es zu catch
Ausgefallene Fehlerbehandlung, jetzt in C. Überarbeitetes Beispiel aus der Errno-Referenz:
try log ( 0.0 );
catch ( NOERR )
println ( "No error." );
catch ( EDOM , ERANGE )
println ( "Math error!" );
NOERR
und NOERROR
werden ebenfalls von Pretty C bereitgestellt, um die Fehlerumschaltung zu erleichtern.
make indent
vor dem Festschreiben aus. Dadurch sollten die meisten Stildetails verarbeitet werden.