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 catchAusgefallene 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.