Su tarea es agregar una característica a un lenguaje de programación, ya sea implementando una biblioteca muy inteligente o procesando el texto de entrada y / o ajustando el proceso de compilación.
Ideas:
- Agregue intercalación de presentaciones de estilo PHP a C (por ejemplo
<?c printf("Hello,"); ?> world!
). - Agregue un operador de fusión nulo a uno de esos lenguajes que no sea C #.
- Agregar macros a PHP.
- Añadir
goto
a JavaScript. - Agregue la coincidencia de patrones al lenguaje X
- Agregue compatibilidad con espacios de nombres a un idioma que no lo tenga.
- Haz que C parezca PHP.
- Haz que Haskell se parezca a Pascal.
- ... (siéntase libre de publicar ideas en la sección de comentarios)
Reglas:
- Trae algo a la mesa. No solo diga "Template Haskell" para agregar servicios de metaprogramación a Haskell. Esto no es StackOverflow.
- La implementación completa debe caber en una pantalla completa (sin contar el ejemplo).
- No aloje código en un sitio externo específicamente para esta tarea.
- La característica más impresionante o sorprendente gana.
No se preocupe por implementar la función 100% correctamente. ¡Lejos de ahi! El principal desafío es descubrir lo que quiere hacer y cortar brutalmente los detalles hasta que su empresa planificada sea factible.
Ejemplo:
Agregue un operador lambda al lenguaje de programación C.
Acercamiento inicial:
Bien, sé que me gustaría usar libgc para que mis lambdas resuelvan los problemas de funarg hacia arriba y hacia abajo. Supongo que lo primero que tendría que hacer es escribir / encontrar un analizador para el lenguaje de programación C, luego necesitaría aprender todo sobre el sistema de tipos de C. Tendría que descubrir cómo darle sentido en lo que respecta a los tipos. ¿Tendría que implementar la inferencia de tipos, o simplemente debería requerir que el parámetro formal se escriba como se indica? ¿Qué pasa con todas esas características locas en CI que aún no conocemos?
Está bastante claro que implementar lambda en C correctamente sería una tarea enorme. ¡Olvídate de la corrección! Simplifica, simplifica.
Mejor:
Atornille funargs hacia arriba, ¿quién los necesita? Podría hacer algo complicado con las funciones anidadas de GNU C y las expresiones de declaración . Quería mostrar una sorprendente transformación sintáctica en C con un código escueto y hacky, pero ni siquiera necesitaré un analizador para esto. Eso puede esperar para otro día.
Resultado (requiere GCC):
#include <stdio.h>
#include <stdlib.h>
#define lambda(d,e)({d;typeof(e)f(d){return(e);};f;})
#define map(F,A)({typeof(F)f=(F);typeof(*(A))*a=(A);({int i,l=((int*)(a))[-1]; \
typeof(f(*a))*r=(void*)((char*)malloc(sizeof(int)+l*sizeof(*r))+sizeof(int)); \
((int*)r)[-1]=l;for(i=0;i<l;i++)r[i]=f(a[i]);r;});})
#define convert_to(T) lambda(T x, x)
#define print(T, fmt) lambda(T x, printf(fmt "\n", x))
int main(void)
{
int *array = 1 + (int[]){10, 1,2,3,4,5,6,7,8,9,10};
map(print(int, "%d"), array);
double *array2 = map(lambda(int x, (double)x * 0.5), array);
map(print(double, "%.1f"), array2);
long *array3 = map(convert_to(long), array2);
map(print(long, "%ld"), array3);
long product = 1;
map(lambda(int x, product *= x), array);
printf("product: %ld\n", product);
return 0;
}
Eso fue fácil, ¿no? Incluso agregué una map
macro para que sea útil y bonita.
fuente
Respuestas:
Sintaxis de OOP en Haskell
Los objetos pueden tener propiedades:
... y métodos:
fuente
&
y definido así(&) = flip ($)
.&
porque es el operador unario 'dirección de' (la implementación de punteros en Haskell se deja como un ejercicio para el lector).flip id
goto
en JavaScript?Mi primer pensamiento fue un enfoque funcional : agregar un parámetro a la función para indicar dónde debería comenzar la ejecución, usando eso con una
switch
declaración y un bucle externo que llama repetidamente a la función en su propio valor de retorno . Desafortunadamente, eso impediría el uso de variables locales, ya que perderían sus valores con cada goto.Podría usar una
with
declaración y mover todas las declaraciones de variables al comienzo de la función, pero tenía que haber una mejor manera. Eventualmente se me ocurrió usar el manejo de excepciones de JavaScript . De hecho, Joel Spolsky dijo: "Considero que las excepciones no son mejores que" ir a ... " , obviamente un ajuste perfecto.La idea era poner un bucle infinito dentro de una función, terminado solo por una
return
declaración o una excepción no detectada. Todos los gotos, tratados como excepciones, quedarían atrapados dentro del ciclo para evitar su terminación. Aquí está el resultado de ese enfoque:Puede usarlo así, incluso en modo estricto ES5 , excepto en Internet Explorer ( demo ):
[Internet Explorer, por alguna razón, no evalúa el código de una función anónima, por lo que habría que darle un nombre a la función (antes de reescribirla) y llamarla con ese nombre. Por supuesto, eso probablemente rompería las reglas del modo estricto.]
Esto no permite saltar a una declaración ubicada dentro de un bloque (hasta que tales construcciones como el dispositivo de Duff se vuelvan legales), pero podemos ocuparnos de eso (otra función reescrita autoejecutable), ¿verdad?
fuente
goto
se implementara completamente en JavaScript (a donde podría usargoto
para saltar fuera de cualquier alcance, incluso una función ), implicaría soporte para las continuaciones.#define en Java
Pensé que sería divertido implementar macros en Java.
Uso de muestra (se convierte en código publicado anteriormente; hagámoslo raro):
fuente
Foreach en C
Iterar matrices (funciona para matrices estáticas, no unas, recibidas a través del puntero)
Para probarlo:
resultado:
fuente
Propiedades en C
Tomasz Wegrzanowski implementó propiedades en el plano C, segfaulando intencionalmente el programa cuando se accede a la propiedad.
Un objeto con una "propiedad" se configura creando un
struct
que cruza varias páginas, asegurando que la dirección de memoria de la propiedad se encuentre en una página diferente de los miembros de datos reales. La página de la propiedad está marcada como sin acceso, lo que garantiza que intentar acceder a la propiedad causará un defecto. Luego, un manejador de fallas determina qué acceso a la propiedad causó la falla predeterminada y llama a la función apropiada para calcular el valor de la propiedad, que se almacena en la dirección de memoria de la propiedad.El controlador de fallas también marca la página de datos como de solo lectura para garantizar que el valor calculado permanezca consistente; la próxima vez que intente escribir en un miembro de datos, eso desencadena un defecto de seguridad, cuyo controlador establece la página de datos como lectura-escritura y la página de propiedades como no acceso (lo que indica que necesita ser recalculado).
fuente
Procedente calculado en Common Lisp
Inicialmente implementé venir de. Pero eso no fue lo suficientemente bueno.
Inspirado por el goto computarizado, decidí implementar el origen computarizado.
Ejemplos de uso
Para cada declaración de origen en el cuerpo de etiqueta, comprobará en cada etiqueta si la variable de origen es igual a la etiqueta actual y, de ser así, saltará a la declaración de origen correspondiente.
Greeter
FizzBuzz
fuente
"Autocadenas" en Ruby
El código es bastante simple:
Ahora puedes hacer
fuente
Agregar macros a PHP
Podemos usar el preprocesador C para esta tarea.
Un script php:
Tubería aunque cpp:
Resultado:
fuente
<<<HEREDOC
Sin embargo, An no es más que 3 desplazamiento inferior o izquierdo y un identificador :-) Sin embargo, esto hará una macro sustitución en cadenas heredoc.grep -v ^#
arreglaría. Supongo que esto es suficiente para esta pregunta :-)Guardias decoincidencia de patronesen PythonEl cuerpo de la función viene en 288 caracteres.
Guardias decoincidencia de patrones lepermiten utilizar funciones completamente diferentes según los valores de los argumentos. Aunque se puede emular fácilmente con una serie deif
declaraciones,losprotectores decoincidencia de patronespueden ayudar a separar secciones de código, y es una gran excusa para hacer una metaprogramación loca.pattern_match
es un decorador que crea una nueva función que implementa guardias decoincidencia de patrones. Las condiciones para cada "subfunción" dada en cada cadena de documentos en líneas que comienzan con una tubería (|
). Si todas las condiciones se evalúan de verdad, se ejecuta esa versión de la función. Las funciones se prueban en orden hasta que se encuentra una coincidencia. De lo contrario,None
se devuelve.Un ejemplo ayudará a aclarar:
fuente
f [a,b,c] = ...
, que no solo prueba el argumento contra un predicado, sino que une las variables respectivas en una coincidencia exitosa. Sin embargo, esto sigue siendo bastante bueno.f (x:xs) = ...
yf [] = ...
). De alguna manera enrevié a los guardias allí, pero de ahí tomé el|
.Corutina
No puedo tomar crédito por esto, así que lo he marcado CW.
Coroutines in C por Simon Tatham
fuente
Operadores personalizados en Lua
Pogs abusó hábilmente de la sobrecarga de operadores en Lua para permitir la definición de operadores infix personalizados. He expandido esto para admitir la sección del operador (aplicando parcialmente un operador con cualquier operando) y llamando al objeto resultante como si fuera una función.
fuente
Cadenas multilínea en javascript
En esta sintaxis elaborada para cadenas multilínea, cada cadena multilínea irá precedida de
(function(){/*
una nueva línea, seguida de una nueva línea y*/}+'').split('\n').slice(1,-1).join('\n')
.Con esta increíble e intuitiva sintaxis, finalmente podemos usar cadenas multilínea:
Para las personas a las que no les gusta nuestra sintaxis simple, tenemos un compilador de nuestro nuevo lenguaje fabuloso:
el mismo ejemplo, en la versión en lenguaje compilado:
fuente
*/
mis cadenas multilínea. ¡Esto es súper molesto cuando se incluyen expresiones regulares en las cadenas!Lista divisible en C # (como Python)
Siempre disfruté de la notación de corte de Python y desearía que estuviera disponible en C #
Uso:
Código, lejos de prueba de error:
fuente
Hacer C más simple
Este código le permite escribir programas en C que se parecen un poco más a un lenguaje de script. Cuenta con palabras clave como 'var', 'is', 'string', 'plus', 'equal' y varias otras. Funciona a través de muchas declaraciones de definición.
Esto le permite escribir código como:
Lo anterior se expande a:
Probablemente no sea demasiado útil, pero me pareció bastante interesante que esencialmente pudieras crear un lenguaje de programación completo a través de un montón de
#define
s.fuente
#define
s lo suficientemente complejos , incluso puede darle a su idioma cosas como manejo de excepciones y recolección de basura mientras mantiene la capa C fundamental debajo.Tcl
Tcl no tiene más
do ... while
odo ... until
menos ...Ejemplo:
uplevel
ejecuta un script en el alcance de los llamantes.fuente
Ir a PostScript
Mi primer pensamiento fue que tendría que perder el tiempo con la pila de ejecutivos, por lo que este inicio falso desentierra el operador de continuación para detener desde ghostscript (o xpost).
Pero, es más simple que eso. Debido a que la posición del archivo es la misma para todos los duplicados del identificador de archivo (
setfileposition
consume su argumento, por lo que esta es la única semántica útil para esa función).Se imprime
5
.Hay algunas limitaciones con lo anterior. El salto no es inmediato, sino que ocurre cuando el cuerpo del if vuelve al nivel superior y el intérprete vuelve a leer del archivo (en lugar de leer del conjunto que contiene el cuerpo del if). En ese punto, el archivo ha sido reposicionado y el 'goto' tiene efecto.
fuente
currentfile <pos> setfileposition
, contando bytes desde el inicio del archivo.Symbol#to_proc
con argumentos en RubySymbol#to_proc
es probablemente uno de mis trucos favoritos para escribir código Ruby realmente sucinto. Supongamos que tienesy desea convertir el contenido de
nums
ytext
a flotantes y palabras mayúsculas, respectivamente.Symbol#to_proc
le permite acortar código como este:a esto:
¡Increíble! Pero lo que si queremos aumentar todos los elementos de
nums
lai
potencia XX, o reemplazar todas las apariciones des
la*
detext
? ¿Hay alguna forma de acortar código como este?Por desgracia, no hay una manera fácil de pasar argumentos cuando se usa
Symbol#to_proc
. Lo he visto de varias maneras, pero probablemente dos de las más inteligentes y utilizables implican parches de mono en laSymbol
clase [ 1 , 2 ]. Ilustraré la primera forma a continuación.Ahora puedes hacer cosas como:
fuente
JavaScript foreach
Salida
Sintaxis alternativa, más como Tcl.
fuente
Gotos en Haskell
La idea básica es que los gotos se pueden simular parcialmente usando la última instrucción en
do
anotaciones. por ejemplo:es equivalente a
Debido a que la ejecución saltará a la última declaración, es óptimo expresar gotos.
porque de la forma en que se hace, los gotos solo saltan cuando están
do
directamente en el bloque de una definición de nivel superior. en realidad es "llamar a x e ignorar el resto de las declaraciones vistas léxicamente " en lugar de "todas las x e ignorar el resto de las declaraciones", como un verdadero goto.El mayor problema es que cuando no hay forma de dejar la ejecución en medio de una acción de E / S, incluso
return
no lo hace;return
no hace nada cuando no es la última declaración.esto supera esto al capturar el resto de las declaraciones en otro
do
bloque.se convierte
la
print 3
declaración es capturada por eldo
bloque, por lo que seloop
convierte en la última declaración.Esta transformación también admite variables presentes en el alcance de las acciones. Esto se hace recordando las variables que están dentro del alcance y pasándolas a las acciones. por ejemplo:
esto simplemente se traduce en:
algunas notas:
Además,
return undefined
se agrega una declaración para garantizar que eldo
bloque de captura no esté vacío.porque a veces hay ambigüedad de tipo en el
do
bloque de captura , en lugar deconst
usarasTypeOf
, que es lo mismoconst
pero requiere que sus dos parámetros tengan el mismo tipo.la implementación real (en javascript):
un examen:
se convierte en:
salida:
fuente
return
en Haskell es una función regular, y no está relacionada con la palabra clave en C / etc.Python Goto
goto.py
Uso
Caso de prueba de muestra
Ejemplo de salida de caso de prueba
Solo un poco divertido con exec (). Puede generar un error de profundidad de recursión máxima si no se usa correctamente.
fuente
// importa javascript sin usar específicamente la etiqueta de script en una página HTML
Es patético, sí, lo sé. Longitud: 99
fuente
script
etiqueta a su alrededor. Entonces, ¿dónde está exactamente la nueva característica?