>> >> >> >>> >> >>> * What about function arity? If f = Lambda(x, x) and >> >>> g = Lambda((x, y), x+y), what is 1 + f + g? >> >> Quite seriously I would answer "Why should we care?". It would be nice >> >> to have partial (lazy) evaluation, but even if we do not have it, this >> >> would be considered just an mis-formed expression that should not be >> >> created (I like more the partial evaluation possibility). Also, we >> >> have already discussed something like this during the argument about >> >> "symbolic lazy nsolve" https://github.com/sympy/sympy/pull/968 . I >> >> would very much like to continue the discussion about this pull >> >> request as I had some unanswered questions. The most important one was >> >> about the "infinitely evaluated" semantics used by Mathematica. I left >> >> a reference to some documentation on the subject but I did not get any >> >> answers. >> > >> > Partial evaluation (a.k.a. currying) is an interesting idea, but it's >> > probably better for this expression to just raise an error (it would >> > do so at call time, to avoid overhead in Add). >> > >> > What was the Mathematica thing? Can you give a link? >> > >> >> Two details about Mathematica (that maybe I misunderstand): >> - less importantly: it permits you to write nonsense: >> Integral[Manifold[Circle[InputFile[blah blah]]]] will not raise an >> error, it will just be left unevaluated because Integral does not know >> what to do with Manifold which does not know ... etc. >> >> - this leads us to "infinite evaluation system" >> reference.wolfram.com/legacy/v1/contents/4.2.7.pdf 2nd paragraph >> To quote: "In Mathematica the evaluation goes on until the result you >> get no longer change." > > I'm not sure whether the reference to Mathematica is really useful. > Mathematica is a programming language, in addition to a CAS, and it > follows a completely different paradigm from Python: rewriting rules vs > OO/imperative. What you mention seems more relevant to the language than > to the CAS.
Yes, you are right. This is a strong argument against my case and I don't have much to say. Emulating this in sympy seems useful nonetheless. >> >> Two examples how this is useful: >> >> - It permits the user to create AST with sympy expression that may not >> make sense for sympy, but that make sense in the formalism that the >> user implements. At the moment this is not always possible as sympy is >> rather draconian about raising errors and demanding that everything is >> Expr (not Basic). > > That's not really true. You can create '1 + Add(FiniteSet(1, 2), And(x, > y))', you just can't print it. >> >> - The symbolic nsolve I was talking about. If there are too many free >> symbols nsolve can not change and thus it returns symbolic unevaluated >> version of itself. Obviously the parallels with Mathematica are flawed >> as this is a feature of the language that Python does not support and >> that we are only emulating. > > The problem with this is that nsolve is, by definition, supposed to > return a numeric result. A Python function is obviously not a numeric > value and getting one where the other was expected will surely crash the > program using it, possibly at an arbitrary distance from the nsolve() > call. What you want can easily be achieved using standard Python > constructs, like functools.partials or a lambda expression, e.g. > lambda a0: nsolve((tan(a*x) - 1).subs(a, a0), x, 1). It is a bit cumbersome and (much more importantly) it does not permit stuff like Intergate(the_lambda_you_defined). Maybe lambdas should be sympified into implemented_functions. Or maybe into Lambdas and we should merge implemented_function into Lambda. > > BTW, calling this a "symbolic nsolve" is confusing, because it's not > symbolic in the sympy sense (where, basically, "a symbolic object" means > "an instance of Basic"). > It returns an instance of Basic (an implemented_function called on the free variable). That is why I called it a symbolic nsolve. >> >>> * 1 + Function('f') can't work anyway, because Function('f') is a >> >>> class, not a sympy object. >> >> This is a second time that you mention this argument. I have some >> >> questions about it. >> >> >> >> Actually Lambda has the same semantics as Function and it works >> >> perfectly with this (just because it subclasses Expr). I have some >> >> open questions about this on our recent discussion on the mailing list >> >> "why is Lambda not subclassing Applications". >> > >> > Does this also apply to 1 + sin? Personally I think we should change >> > how Function('f') works, if just for issue 1198. >> > >> It should apply but it does not because you can not write 1+sin >> because Add accepts only Expr. Ether Add should be less picky or sin >> (ugh... Function?) should subclass Expr. > > Function (and therefore sin) does subclass Expr. When you have f = > Function('f'), then f is a subclass of Function and it is not an > instance of it, while f(x) is an instance of f and therefore of Function > and of Expr. In other words, "f = Function('f')" is nearly equivalent to > "class f(Function): pass". f = Function('f') being a subclass of Functions and not an instance seems like plenty of black magic to me. >> >> Also here we have much black magic and jumping through circles during >> the creation of sin(x) with what I consider an excessive use of >> metaclasses. However I may be very very wrong on this one (more than >> usual ;) > > Huh? Metaclasses aren't involved in the instantiation of sin(x). The > only real indirection is that the parent class, Application, calls > sin.eval(). The metaclass of Application is FunctionClass (which does what?). Overall this part of the core seems excessively complicated without need (again, I am probably missing many details, so correct me). Why can't functions be something simple like (like Lambda actually): ``` class Funtion(Expr): def __init__(self, name): ... def __call__(self, *args): # this is overridden by stuff like sin return AppliedFunction(self.name, *args) ``` Obviously the mpmath magic should be added but this is tangential. Basically, why is `f` a class and not a Basic or Expr? What is the use of BasicMeta? Why is there at the same time implemented_function with _imp_, Lambda, and Function/Application/FunctionClass? -- You received this message because you are subscribed to the Google Groups "sympy" group. To post to this group, send email to sympy@googlegroups.com. To unsubscribe from this group, send email to sympy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sympy?hl=en.