Pretty C es un nuevo lenguaje de scripting compatible con C. Pretty C potencia tus programas con escritura dinámica, iteración genérica, seguimiento de recursos y otras sutilezas. ¡Y es compatible con versiones anteriores de C y todas sus bibliotecas! Inspirado en Lua, Python, JavaScript y Lisp. Así es como podría verse una reimplementación ingenua de la utilidad head con 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 ;
}Los objetivos de Pretty C son:
#include -able desde un archivo C arbitrario) para convertir cualquier código base en uno amigable para principiantes.Consulta el repositorio
git clone https://github.com/aartaka/pretty.c O simplemente copie el archivo pretty.h : Pretty C es una biblioteca de solo encabezados, por lo que puede
#include "pretty.h" desde cualquier archivo en el directorio al que coloques pretty.h . O realmente desde cualquier archivo, si especifica la ruta a Pretty C como una ruta incluida ( -I ).
Aquí están todos los bonitos cambios que hacen que C vuelva a estar de moda.
true , false y bool .uint64_t .and para && y or para || . ¡Limpio! Todo el mundo los define, así que ¿por qué no proporcionarlos?
max y min de dos números.len para la longitud de la matriz.default para proporcionar un valor de reserva.limit para garantizar el rango de valores adecuado.between para comprobar si el número cae dentro de un rango.divisible para comprobar si un número es módulo divisible por otro número. Alias de tipo:
string == char* .byte == char .bytes == char* .any == void* .uchar .ushort .uint .ulong . Principalmente modelado a partir de Lua y Lisp:
eq , porque iso646.h solo tiene not_eq .is significa == también.bitnot y bitxor para operaciones que solían llamarse de manera inconsistente ( compl y xor respectivamente) en iso646.h .success y fail / failure para el patrón de success == 0 .below , above , upto y downto .even , odd , positive , negative , zero y empty como predicados para números/datos.nil para NULL .until por negado while .elif para else if .ifnt para if(!...) y elifnt (lo has adivinado).repeat desde Lua como alias para do .done~/~finish y pass como alias para break y continue , respectivamente.always , forever , loop e indefinitely para que puedas hacer bucles infinitos (¿evento? ¿servidor?) always println ( "After all this time?" );never y comment para comentar algún código con una sola palabra clave, al tiempo que permite que el compilador lo analice/optimice (similar al formulario comment de Clojure): never println ( "This never runs, but never gets outdated, because compiler will shout at you if it does." );Si, puedes hacer
var t = time ( 0 );
let lt = localtime ( & t );
local at = asctime ( lt );
println ( at );Con la bonita C.
print todo lo que le das de comer. println agrega una nueva línea después.
println ( 3.1 );
print ( "Hello world!n" );¡Compara todas las cosas!
equal ( "NA" , line ); // true
equal ( 0.3 , 0.2 + 0.1 ); // true Los ternarios dan miedo, por lo que no estará de más agregar texto sin formato. Se toman if y else , pero existen alternativas lingüísticas adecuadas que se parecen bastante a Python/Lisp:
return when some_condition
then do_something ()
other do_something_else ();Son ternarios debajo:
when se expande a una cadena vacía y solo se proporciona para facilitar la lectura.unless se expanda para not ser una versión negativa de when .then se expande a ? .other / otherwise se expande a : . También existe only para cuando la cláusula otherwise es innecesaria:
return when done ()
then 42 only ; y otherwhen para la siguiente condición
return when c is 'A'
then 'a'
otherwhen c is 'B'
then 'b' only ;for macros Estas macros son alias para ciertos patrones de bucle for , y cada una abstrae algunos de los usos frecuentes for bucle for.
foreach (var, type, length, ...) Este recorre una matriz o región de memoria inicializada con la expresión vararg. Cada vez que se itera, var se establece en un puntero al elemento de matriz respectivo. Sí, puntero, para que pueda modificar el elemento en su lugar si es necesario.
foreach ( i , int , 10 , vector ( 10 , int , 1 , 2 , 3 , 3 , 4 , 5 ))
println ( * i ); También muestra el uso de vector .
forthese (var, type, ...) Itera sobre los varargs proporcionados, vinculando cada uno de ellos al type -d var . El bucle anterior se puede traducir como:
forthese ( i , int , 1 , 2 , 3 , 3 , 4 , 5 )
println ( i );fortimes (var, times)Un caso frecuente de pasar de 0 a algún número positivo. Le ahorra bastante tiempo para su
for ( int i = 0 ; i < 28 ; i ++ )
println ( i + 1 );convirtiéndolo en un simple
fortimes ( i , 28 )
println ( i + 1 );
println ( "28 stab wounds, you didn't want to leave him a chance, huh?" );forrange (var, init, target) Itere sobre un rango de números desde init hasta target . Pitonesco. Aquí está el bucle de conversión de Celsius a Fahrenheit con forrange :
forrange ( c , -10 , 20 )
printf ( "Celsius %i = Fahrenheit %fn" , c , ( 32 + ( c * 1.8 ))); Tenga en cuenta que init y target son números enteros arbitrarios, con y sin signo. Y init podría ser mayor que target , en cuyo caso el paso de iteración disminuye la variable.
forrangeby (var, type, init, target, by) Itere type -d var desde iter hasta target , avanzando paso a by cada vez. Pitonesco.
forrangeby ( x , double , 1.0 , 10.0 , 0.5 )
println ( x );Estos permiten una asignación rápida y precisa para patrones típicos. Principalmente modelado a partir de C++.
new (type, ...) new operador de C++ es bueno, por lo que no vendrá mal tener algo similar en C, ¿verdad? No preguntes más:
struct ListNode {
int val ;
struct ListNode * next ;
};
struct ListNode * node = new ( struct ListNode , 2 , new ( struct ListNode , 1 , nil ));O, si lo deseas, puedes agregar aún más sintaxis encima:
#define cons ( val , ...) new(struct ListNode, val, __VA_ARGS__)
cons ( 2 , cons ( 1 , nil ));vector (length, type, ...) C++ de nuevo. std::vector es una estructura de datos extremadamente útil y versátil sobre la que es fácil razonar. Si bien esta macro no tiene ni remotamente tantas funciones como su contraparte de C++, simplifica un patrón frecuente de "asignar una matriz de esa cantidad de elementos y con estos contenidos":
double * vec = vector ( 10 , double , 1 , 2 , 3 , 4 , 5 );delete (...) En caso de que no le guste free los recursos y prefiera un nombre C++ más elegante.
Por lo demás igual que free .
Estos establecen nuevos enlaces locales, garantizan cálculos diferidos o actúan de otro modo en el bloque posterior a ellos.
lambda (ret, name, ...) (GCC, Clang o C++)Funciones anidadas/lambdas/cierres, ¡ahora en 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, ...) Esto garantiza que nunca tendrá uso después de la liberación, porque proporciona el procedimiento de liberación ( close ) por adelantado. Especialmente útil para objetos asignados dinámicamente y designadores de archivos.
with ( file , fclose , fopen ( "hello.txt" , "w" ))
fprintf ( file , "Hello world!n" ); Una de las desventajas es que la var vinculada es void * , por lo que es posible que deba forzarla a su tipo antes de usarla.
defer (...) Descarga el código que se ejecutará después del siguiente bloque. No al final de la función como en Go, porque eso es imposible difícil de implementar en C. Aún así, Pretty C defer es bastante útil.
try catchManejo de errores sofisticado, ahora en C. Ejemplo refactorizado a partir de la referencia de errno:
try log ( 0.0 );
catch ( NOERR )
println ( "No error." );
catch ( EDOM , ERANGE )
println ( "Math error!" ); Pretty C también proporciona NOERR y NOERROR , para facilitar el error en la carcasa del interruptor.
make indent antes de confirmar, eso debería manejar la mayoría de los detalles de estilo.