For expensive functions, perhaps one could save significant computational expense if scipy.differentiate.derivative also returned the value of the function at the point of the derivative? (I presume this value is always computed as part of the algorithm.) Also, this could allow cleaner code for algorithms that require both the function value and its derivative given points.
As the function is currently implemented, f(x) is always computed. However, with default settings (central difference approximation), the value is only used for determining array shapes, dtypes, etc… not for computing the derivative itself. So IIRC we didn’t return f(x) because in the future, we might want to avoid that function evaluation. See https://github.com/scipy/scipy/blob/54ef5423f2e4376230ec3bfda6912a07a50958e3/scipy/differentiate/\_differentiate.py#L391-L398 .
@mdhaber Thanks for sharing the reasoning here. I would personally be ok if the f(x) value were provided now, but became None in future implementations where it is (optionally?) not calculated.
Unfortunately, making the change from returning the value to returning None would be backward incompatible.
One option in situations like this is to make a class to represent the callable used by differentiate and to cache function values.
I was thinking of adding it as typing.Optional field in a minor version bump, with None being a possible return value from the start, even though it might not actually be None until some future implementation.
Other maintainers are invited to chime in as to whether this is a viable strategy. My understanding is that we would not want to suddenly change from returning a valid value to returning None.
Perhaps to clarify, I’m saying users should always fully expect that the new value could be None and check for that eventually, even if it may not happen in the initial implementation.