Lance,

Sorry if I am being a pain in the #%%, I just want to make sure that
we get the desig of this right as someone else said "you only get to
implement __call__ once". I do appreciate you willingness to do the
implementation of this and hear me out.  A few things about this most
recent patch:

The patch allows __call__ to be used in the following ways:

+        >>> f = 1+x*y
+        >>> f(x=pi,y=2)
+        1 + 2*pi

This is great and I think we all agree that this absolutely should be
supported.  +1 on this.

+        >>> f({x:pi, y:2})
+        1 + 2*pi

I am +0 on this.  The main thing that I am guided by is that __call__
should be used to implement something that looks like a function call
(in the mathematical sense).  The mathematician in me sees this and
asks, how do I can a function with a dictionary?

+        >>> f([(x,pi),(y,2)])
+        1 + 2*pi

I am -1 on this.  Try to forget about subs for a second.  Most new
users will want to use a function call syntax before they do a subs (I
am thinking of my students in the physics department).  This syntax is
_very_ confusing for someone expecting function calls to behave like
they do in math.

Also, it violates this (pun intended):

>>> import this
...
There should be one-- and preferably only one --obvious way to do it.
...

For function calling that involves key/value pairs f(x=1,y=3) already
works just fine.  As an aside, this is also a complaint that I have
about subs - we have a single function that can be called in (it seems
10 different ways.  It that really needed.  Simplify, simplify,
sympify.

Other thoughts?

Brian

On Tue, Nov 18, 2008 at 8:20 PM, Lance Larsen <[EMAIL PROTECTED]> wrote:
>
> # HG changeset patch
> # User "Lance Larsen <[EMAIL PROTECTED]>"
> # Date 1226946818 25200
> # Node ID 060b92b72467a29a2d098e7ce0ee96cbf4c2395b
> # Parent  d1019a5c66d12d524fe64359c1bd8054cab0cfa9
> Substitution syntax extension - implements f.subs(x=1,y=2) and
> shorthand syntax f(x=1,y=2).
>
> diff -r d1019a5c66d1 -r 060b92b72467 sympy/core/basic.py
> --- a/sympy/core/basic.py       Tue Nov 18 17:36:24 2008 +0100
> +++ b/sympy/core/basic.py       Mon Nov 17 11:33:38 2008 -0700
> @@ -896,26 +896,43 @@
>         """
>         return self
>
> -    def subs(self, *args):
> +    def subs(self, *args, **kwargs):
>         """
>         Substitutes an expression.
>
>         Calls either _subs_old_new, _subs_dict or _subs_list
> depending
> -        if you give it two arguments (old, new), a dictionary or a
> list.
> +        if you give it two arguments (old, new), a dictionary, a list
> or
> +        pass in named parameters. When named parameters are passed
> in,
> +        these are converted to a dictionary and _subs_dict is called.
>
>         Examples:
>
>         >>> from sympy import *
>         >>> x,y = symbols('xy')
> -        >>> (1+x*y).subs(x, pi)
> -        1 + pi*y
> +        >>> (1+x*y).subs(x=pi, y=2)
> +        1 + 2*pi
>         >>> (1+x*y).subs({x:pi, y:2})
>         1 + 2*pi
>         >>> (1+x*y).subs([(x,pi), (y,2)])
>         1 + 2*pi
> +        >>> (1+x*y).subs(x, pi)
> +        1 + pi*y
> +
> +        Subs can be called implicitly as well as shown in the
> following
> +        examples:
> +
> +        >>> f = 1+x*y
> +        >>> f(x=pi, y=2)
> +        1 + 2*pi
> +        >>> f({x:pi, y:2})
> +        1 + 2*pi
> +        >>> f([(x,pi), (y,2)])
> +        1 + 2*pi
> +        >>> f(x, pi)
> +        1 + pi*y
>
>         """
> -        if len(args) == 1:
> +        if len(args) == 1 and len(kwargs) == 0:
>             sequence = args[0]
>             if isinstance(sequence, dict):
>                 return self._subs_dict(sequence)
> @@ -923,9 +940,11 @@
>                 return self._subs_list(sequence)
>             else:
>                 raise TypeError("Not an iterable container")
> -        elif len(args) == 2:
> +        elif len(args) == 2 and len(kwargs) == 0:
>             old, new = args
>             return self._subs_old_new(old, new)
> +        elif len(args) == 0 and len(kwargs) > 0:
> +            return self._subs_dict(kwargs)
>         else:
>             raise Exception("subs accept either 1 or 2 arguments")
>
> @@ -1932,9 +1951,25 @@
>         from sympy.integrals import integrate
>         return integrate(self, *args, **kwargs)
>
> -    #XXX fix the removeme
> -    def __call__(self, *args, **removeme):
> -        return Function(self[0])(*args)
> +    def __call__(self, *args, **kwargs):
> +        """Alias for calling the subs function. All subs syntax is
> supported
> +        the two parameter syntax f(x,2) for f(x=2).
> +
> +        Examples:
> +
> +        >>> from sympy import *
> +        >>> x,y = symbols('xy')
> +        >>> f = 1+x*y
> +        >>> f(x=pi,y=2)
> +        1 + 2*pi
> +        >>> f({x:pi, y:2})
> +        1 + 2*pi
> +        >>> f([(x,pi),(y,2)])
> +        1 + 2*pi
> +        """
> +        if len(args) > 1:
> +            raise Exception("Unsupported syntax. Pass a dictionary, a
> list of substitution pairs, or name=value pairs.")
> +        return self.subs(*args, **kwargs)
>
>     def __float__(self):
>         result = self.evalf()
> diff -r d1019a5c66d1 -r 060b92b72467 sympy/core/tests/test_subs.py
> --- a/sympy/core/tests/test_subs.py     Tue Nov 18 17:36:24 2008 +0100
> +++ b/sympy/core/tests/test_subs.py     Mon Nov 17 11:33:38 2008 -0700
> @@ -169,3 +169,16 @@
>     assert (f(x,y)).subs(f,sin) == f(x,y)
>     assert (sin(x)+atan2(x,y)).subs([[atan2,f],[sin,g]]) == f(x,y) + g
> (x)
>     assert (g(f(x+y, x))).subs([[f, l], [g, exp]]) == exp(x + sin(x +
> y))
> +
> +def test_subs_call_syntax():
> +    a, b, x, y, p, q = map(Symbol, "abxypq")
> +    f = 2*a*x+3*b*y
> +    assert f(x=1, y=2) == 2*a + 6*b
> +    assert f({a*x:p,b*y:q}) == 2*p + 3*q
> +
> +def test_implicit_subs_call_syntax():
> +    a, b, x, y, p, q = map(Symbol, 'abxypq')
> +    f = 2*a*x + 3*b*y
> +    assert f(x=1, y=2) == 2*a + 6*b
> +    assert f({a*x:p,b*y:q}) == 2*p + 3*q
> +    assert f([(a*x,p),(b*y,q)]) == 2*p + 3*q
>
> >
>

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

Reply via email to