Le vendredi 18 mai 2012 à 22:32 +0200, [email protected] a
écrit :
> >> >>
> >> >>>
> >> >>> * 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.
Do you mean Integral or integrate? It's not quite the same thing. I
don't think that the Integral of a Python function makes much sense,
there's nothing you can compute about it. OTOH, numerically integrating
a numerical function is certainly useful, but my feeling is that it
should be left to the likes of scipy.
An implemented_function is different from a Lambda. First, it's just a
Function subclass with an added attribute, '_imp_', so it's not an
instance of Basic. More fundamentally, it's a black box for sympy, while
a Lambda is completely specified by its args.
> >
> > 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.
OK, but this object is just an opaque wrapper around a Python callable,
not a fully sympy-introspectable expression tree.
>
> >> >>> * 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.
I agree, actually. I'm only describing the current situation.
> >>
> >> 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?).
FunctionClass doesn't really do much besides identifying which classes
represent functions. I guess we could get rid of it if we replaced all
the isinstance(..., FunctionClass) with issubclass(..., Function).
> 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)
> ```
Well, you'd need to define AppliedFunction and decide how to handle
special values (like sin(0) == 0), so it's not as simple as you think.
But what's really difficult is that you'd have to reimplement all the
existing functions. The one advantage of making sin a class is that it's
trivially easy to attach code to it. If you made it a mere instance of
this Function class, it's not clear where you'd implement all its
current methods, and in any case they'd have to be significantly
modified.
> 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?
f is a class because sin "needs" to be a class.
Nowadays, the only non-deprecated use of BasicMeta is to register
classes so that they are accessible via C.TheClass.
>
> Why is there at the same time implemented_function with _imp_, Lambda,
> and Function/Application/FunctionClass?
It's largely an artefact of history, I suppose. However, they all serve
different purposes, so they should probably all stay (except
FunctionClass, I guess), but they could certainly be more consistent.
--
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.