On Friday 28 November 2008 15:06:37 Ondrej Certik wrote:
> Hi,
>
> there is a long discussion in the following two threads:
>
> http://groups.google.com/group/sympy-patches/browse_thread/thread/83c33c0aa
>8560475/
> http://groups.google.com/group/sympy-patches/browse_thread/thread/628ebc799
>ee57ec1
>
> (don't forget to click next at the bottom of the page to get to the next
> pages).
>
> First note, that our current .subs() is verstile enough to support
> almost all kinds of syntax. For example:
>
> In [1]: e = x**y+3*x+sin(y)
>
> In [2]: e
> Out[2]:
>                 y
> 3⋅x + sin(y) + x
>
> In [3]: e.subs(x, z)
> Out[3]:
>                 y
> 3⋅z + sin(y) + z
>
> In [4]: e.subs({x: z})
> Out[4]:
>                 y
> 3⋅z + sin(y) + z
>
> In [5]: e.subs(dict(x=z))
> Out[5]:
>                 y
> 3⋅z + sin(y) + z
>
> In [6]: e.subs({x: 1, y: 2})
> Out[6]: 4 + sin(2)
>
> In [7]: e.subs(dict(x=1, y=2))
> Out[7]: 4 + sin(2)
>
>
> However, it may be useful to allow f(x=1, y=2) directly instead of the
> equivalent e.subs(dict(x=1, y=2)).
> There are pros and cons of each approach, so let me summarize it:
>
> 1) do not allow the e(x=1) syntax, i.e. raise an exception in e.__call__
>
> this doesn't cause any problems
>
> 2) implement e.__call__ along these lines:
>
> def __call__(self, *args, **kwargs):
>     return self.subs(kwargs)
>
> so now e(x=1, y=2) will be possible. A huge disadvantage is that the
> following code will fail:
>
> x = Symbol("a")
> f = x*y
>
> f(x=3)
>
> This is because .subs() will try to substitute for Symbol("x"), but
> there is no Symbol("x") in the expression, only Symbol("a").
>
> Another problem is that what if your Symbol contains characters that
> cannot be in a Python variable, like "\", "-", ..., then it will not
> work.
>
> 3) implement e.__call__ along these lines (nice trick by Riccardo):
>
>     def __call__(self, *args, **kwargs):
>         import inspect
>         frame = inspect.currentframe().f_back.f_globals
>         nkwargs = {}
>         try:
>             for k, v in kwargs.iteritems():
>                 nkwargs[eval(k, frame)] = v
>         finally:
>             del frame
>         return self._subs_dict(nkwargs)
>
> In [1]: t = Symbol("theta")
>
> In [2]: f = x+t**2
>
> In [3]: f(x=10,t=3)
> Out[3]: 19
>
> Now it correctly finds the right variable to substitute for. However,
> I and Brian don't like this, because playing with frames is a messy
> stuff.
>
>
> Read also the threads for more opinions. For comparison, here is what Sage
> does:
>
> sage: t = var("theta")
> sage: t
> theta
> sage: f = x+t**2
> sage: f(x=10,t=3)
> theta^2 + 10
>
>
> So Sage chose the option 2).
>
> So which option should we choose?

I think we should avoid option 2.
I prefer something like:

f({x:2, y:3})

it's 2 character longer but is more pythonic, and it works.

Using this we can call _subs_dict from __call__ without modifying Basic.subs.

Cheers,
Riccardo

> Ondrej



--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sympy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to