On Tue, May 29, 2012 at 12:57 PM, Ronan Lamy <[email protected]> wrote:
>>>> The absence of test failures only shows that a feature that didn't exist
>>>> wasn't used. As for special cases, I already mentioned the Expr vs Basic
>>>> thing (why is this implemented only for Expr, when callability is
>>>> unrelated to the concept of Expr?), but the special handling of Symbol
>>>> is also a problem and the complicated implementation of Expr.__call__
>>>> probably makes assumptions that can be broken. Also, if any Expr
>>>> subclass with a Lambda in its args will cause problems.
>>
>> I agree that could be an issue. Perhaps this could be an argument for
>> not putting it in Basic, that a Basic (but not Expr) object is more
>> likely to have some Lambda somewhere in its args that doesn't expect
>> to be recursively called.
>>
>> Do we have any classes in SymPy with Lambda in their .args?
>
> I know of TransformationSet and RootSum, but we could certainly create
> more and users can too.
It seems that this already causes issues with Stefan's patch:
In [51]: print RootSum(x**2 + x + 1, exp)(x)
RootSum(x**2 + x + 1, Lambda(_x, exp(_x)))
In [52]: print RootSum(x**2 + x + 1, exp)(y)
2*exp(y)
I guess the only way around this is to either provide a way for
classes to prevent recursion into their args, or to only allow
recursion into classes that specifically allow it.
>
>>>>
>>> Yes, I agree. These should be discussed further, however I do not
>>> think that these are show-stoppers. I would prefer to finish with the
>>> examples from Aaron before proceeding on this.
>>
>>
>> Most of my examples are syntactic sugar (but I guess this whole thing
>> is just syntactic sugar). A nice example would be replace. You could
>> do expr.replace(sin**2 + cos**2, 1). Right now you'd either have to
>> do expr.replace(Lambda(x, sin(x)**2 + cos(x)**2), 1) or
>> expr.replace(sin(a)**2 + cos(a)**2, 1), where a = Wild('a').
>
> Well, this can't work without solving issue 1688, but even then, this would
> be a very implicit syntax that could easily do too much or too little, just
> like expr.subs(exp(x), ...) which you've repeatedly complained about.
Yes, I know that it would require changing how Function works. You
stated yourself in the issue that making Function an object would
allow defining operators on functions. Isn't sin**2 + cos**2 an
operator on Functions? Or more generally, Lambda((x, y), x**2 +
y**2)(sin, cos). I don't really see how allowing such a thing would
be useful unless they are recursively callable.
>
>>
>> But actually it would be more useful than even just that. Anywhere
>> where you would use Lambda or .subs(x, y) (or defining a simple Python
>> function that returns an expression), you could just use this instead.
>> So instead of something like
>>
>> def my_expr(x):
>> return some_SymPy_expression_in_terms_of_x
>>
>> you could just have the expression itself, as a function.
>
> f(x) isn't the same thing as f, so I guess that what you mean isn't the
> expression itself, but another one that involves only functions, but not x.
Yes. It's not easy to express. I guess it's the "uncalled" expression.
> This can get confusing quickly if the expression is complicated.
>
>> This is somewhat related to my previous discussion about replacing
>> f(x, y) with an expression evaluated at x and y (see
>> https://groups.google.com/forum/?hl=en_US&fromgroups#!searchin/sympy/evaluate/sympy/TsRxB8HnUuI/moOq251RBpcJ).
>> If this were implemented I could just do expr.subs(psi,
>> z**Id[1]*exp(-I*omega(z)*Id[2]) (this is also why we need a more
>> powerful identity function, as I noted on the issue).
>
> I find expr.subs(psi, Lambda([x, y], z**x*exp(-I*omega(z)*y))) easier to
> understand.
>
>> I know that Lambdas can be used to do a lot of these things, but
>> Lambda is inherently crippled in that if you want to mainpulate the
>> expression in the Lambda at all, you have to peel off the Lambda
>> first. With this, you don't have to do any of that. You can even use
>> Lambdas if you want, though if you do, you can run into the issue
>> where some part of an expression is "stuck" in the Lambda (like
>> Lambda(x, x + 1) - 1).
>>
>> As another example, if I have an iterative function, like
>>
>> f(xn) = x_(n - 1)*(x_(n - 1) - 1)
>>
>> You can compute something like,
>>
>> f = Lambda(x, x*(x - 1)) # or Id*(Id - 1)
>> f2 = f(f)
>> f3 = f2(f)
>>
>> and then f, f2, and f3 are all callables, for which you can just say
>> f(0.3), f2(0.3), f3(0.3) and get numbers back.
>
> I find this quite confusing. Is f2 equal to f o f? As for f3, I don't
> understand
> it at all. I'm not sure that it's even possible for a mathematical function
> (with specified domain and range) to belong to its own domain of definition.
f2 = f o f, f3 = f o f o f. I agree that f can't be a function on
itself (a function it its own domain would require an infinitely
nested set, which I believe ZFC disallows). f(f) is just syntactic
sugar for f o f. f3 becomes f(f(f)) because the first f (in f2) is
already called, so it isn't called again. Then f3(x) becomes
f(f(f(x))) (the first two f's are already called, only the inner f is
not, so it gets the x).
Aaron Meurer
>
>> In short, you eliminate the need for named dummy variables with this,
>> because they aren't there at all.
>
> OK, avoiding dummy variables can sometimes be advantageous.
>
>> I can attest from my personal experience that this sort of thing would
>> be very useful. I use these patterns quite often, especially the
>> .subs(x, y) pattern, and I've often felt that if I could define the
>> whole expression as a function directly that it would make things much
>> easier. I've done the def my_expr(x): ... thing, and (when I remember
>> that it exists) created a Lambda, but those are both limited in that
>> the expression is "stuck" inside the function or Lambda (at least with
>> Lambda you can see what it is and get it out if you want, though). If
>> I want to perform any kind of simplification or modify the expression
>> at all I have to recreate the function or Lambda.
>>
>> Aaron Meurer
>>
>> --
>> 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.
>>
>
> --
> 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.
>
--
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.