>> >>
>> >>>
>> >>> * 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.

Reply via email to