[Python-ideas] Symbolic expressions (or: partials and closures from the inside out)
Nathan Rice
nathan.alexander.rice at gmail.com
Sun Jan 15 08:04:11 CET 2012
> The pattern you employ with SymbolicObject, is a nice way to mix code that is
> executed immediately, with code that is executed later. Symbolic algebra
> languages, like Maple and Mathematica, function this way too.
I find it to be useful quite frequently. I think making generative
SQL expressions with SQL Alchemy got me hooked.
> I propose however a slightly different interface:
>
> There should be a special object "quoted" to create instances of
> "SymbolicObject". The objects should be created in the "__getattribute__"
> method. This way the objects know their name, which is quite useful. A
> symbolic object would be created like this:
>
> X = quoted.X
>
> You could also write:
>
> const = Constraints(quoted.X * 2 + 1 >= 5, quoted.X % 2 != 0)
The factory there seems to add complexity. The Class(args)
constructor style is less magic, and I can imagine wanting to pass
things to the symbolic object, like a name, default value, a
docstring, etc.
> The standard library should contain at least these symbolic algorithms:
>
> evalsym(tree, environment, return_type="any")
> Evaluates an expression and returns the result. Works similar to:
>
> eval(compile(tree, "", "eval"), environment)
>
> This call would return 7:
>
> evalsym(quoted.X * 2 + 1, {"X":3})
>
> However it should do partial evaluation if some symbols are
> unknown, and return an ast.AST in this case (similar to Maple and
> Mathematica). This expression should be True:
>
> evalsym(quoted.X + quoted.Y, {"Y":3}) == quoted.X + 3
>
> The optional argument "return_type" specifies the type of the
> result. This simplifies algorithms using "eval". Argument
> "return_type" can be: "any", "ast", or "object".
I think a method call leads to more readable code than a function,
because they grow left to right and are structured like English.
Something along the lines of:
expr = X ** (M*(N+1))
expr.realize({N:2, M:3, X:4})
expr.realize((N,2)).realize((M, 3)).realize((X, 4))
Tasty curry.
As a side note, perhaps PyPy is a good place to prototype something
like this? :)
Nathan
More information about the Python-ideas
mailing list