¿Cómo haces que los decoradores sean tan poderosos como las macros?

7

Fondo rápido: estoy diseñando un lenguaje Pythonic que quiero que sea tan poderoso como Lisp sin dejar de ser fácil de usar. Y por "poderoso", quiero decir "flexible y expresivo".

Me acaban de presentar a los decoradores de funciones de Python, y me gustan. Encontré esta pregunta que sugiere que los decoradores no Tan potente como las macros de Lisp. La tercera respuesta a esta pregunta dice que la razón por la que no lo son es porque solo pueden operar en funciones.

Pero, ¿y si pudieras usar decoradores en expresiones arbitrarias? (En mi idioma, las expresiones son de primera clase, al igual que las funciones y todo lo demás, por lo que hacerlo sería bastante natural). ¿Eso haría a los decoradores tan poderosos como las macros Lisp? O tendría que usar reglas de sintaxis, como Racket y Honu , o alguna otra técnica?

EDIT

Me pidieron que proporcionara un ejemplo del constructo sintáctico. Para un "decorador de expresiones", simplemente sería un decorador en una expresión (donde "$ (...)" crea un objeto de expresión):

@Decorator("Params")
$(if (true):
    printf("Was true")
else:
    printf("Wasn't true"))

Además, si do necesito usar reglas de sintaxis, como se mencionó anteriormente, usaría una sintaxis de coincidencia de patrones:

# Match a bool expression, a comma, and a string.
macro assert(expr:bool lit string) { e , s }:
    if (!e):
        error s
    else:
        printf("All good")

Lo anterior coincidiría con esto:

assert i == 0, "i should have been 0"

Es un boceto aproximado, pero debería darte una idea.

    
pregunta Gavin Howard 08.08.2014 - 05:52

1 respuesta

8

Respuesta corta: No puedes.

No en Python ni nada parecido a lo que es hoy, al menos. La razón es directa: las funciones son objetos. Las expresiones no lo son. Las expresiones describen actividades: la actividad de operar con objetos y producir un resultado. Mientras que la entrada y salida de expresiones son objetos, las expresiones en sí no lo son. Como no son objetos, no pueden ser decorados.

Esta limitación en la metaprogramación de Python está bastante integrada en el lenguaje. No es imposible cambiar la semántica de Python. Los módulos como forbiddenfruit le permiten a Monkeypatch construir objetos de formas que son oficialmente "imposibles". Módulos como MacroPy , karnickel , y el ahora desaparecido MetaPython proporciona algunas funciones de macros a través de la reescritura de AST y técnicas relacionadas. Sin embargo, ninguno de estos está certificado para uso en producción, y la mayoría aparece, soporta una o dos iteraciones de idioma y luego se evapora. Los movimientos de doble retroceso, giro y giro necesarios para hacer que funcionen, simplemente no son sostenibles en ningún período de tiempo, en ninguna generalidad o en el contexto del "código en el que puede confiar".

Hay módulos que utilizan con éxito la introspección y la reflexión para inspeccionar lo que está sucediendo actualmente en un programa. Por ejemplo, mi módulo say funciona bien en muchas versiones de Python 2 y Python 3, e incluso en implementaciones alternativas de Python como PyPy. Pero pocos metamódulos de Python pueden cambiar la semántica del programa. GvR ha sido bastante resistente a las instalaciones de metaprogramación. La semántica de la declaración with , por ejemplo, se restringió con el propósito particular de limitar la cantidad de metaprogramación que puede soportar.

Pero, eso es Python como existe hoy. Puede imaginar que su lenguaje Python ++ tiene bloques de código arbitrarios (el mítico lambda multilínea, a menudo mencionado pero nunca visto en Python) que puede ser decorado. Las Lambdas son objetos, y los bloques de código son muy capaces de objetos. Probablemente no querría la sobrecarga de convertir cada en un objeto, pero no es difícil imaginar un entorno en el que cualquier expresión que fuera interesante codificar en un bloque pueda hacerse, y luego decorarse.

Dos lenguajes estándar (es decir, que no son Lispy) y bastante Pythonic que han trabajado para integrar metaprogramación y facilidades de macros avanzadas son Julia y Nim (anteriormente conocido como Nimrod). La forma en que abordan la representación y transformación del programa es muy poderosa y sería un buen punto de estudio para su diseño.

    
respondido por el Jonathan Eunice 15.08.2014 - 04:17

Lea otras preguntas en las etiquetas