How to check if function is in-place

Say I am given a function f and would like to know whether f will return a new array or simply write into its first argument. How do I do that?

I know DifferentialEquations.jl does this, for example. You just supply a function and it figures out if it’s in place or not.

I think DiffEq checks whether the function has 3 or 4 input arguments. The former is non-mutating, the latter is mutating, by convention of DiffEq. I don’t think a general check on whether a function is mutating is possible in Julia (you should look into Rust ;-).

1 Like

They explicitly specify whether it is an in-place modified function or not in the function name and type.

For example, on ODEs, we have that f!(du,u,p,t) is the in-place form which, as its output, mutates du . Whatever is returned is simply ignored.
Similarly, for OOP we have the form du=f(u,p,t) which uses the return.

However, every constructor allows for manually specifying the in-placeness of the function. For example, this can be done at the problem level like:

ODEProblem{true}(f,u0,tspan,p)

https://diffeq.sciml.ai/stable/basics/problem/#In-place-vs-Out-of-Place-Function-Definition-Forms

As far as I’m aware there is no way to programmatically check whether a function mutates its arguments or if it allocates. However, there’s the general function naming convention that a mutating function should have an ! appended at the end of its name. So mutating would be f! and allocating would be f. This is not enforced in any way but it’s generally followed by the community.

1 Like

Alright, then I’ll give the user an argument to specify in-place-ness and default to checking the number of input args, too.

And yeah, Rust is cool.

I was thinking you could potentially check if the function has a method f(out::AbstractArray, x::InputType1, y::InputType2) or a method f(x::InputType1, y::InputType2). Not sure how to do that though and if that’s the best way to do it.

It’s a julia convention to add a ! at the of the name to signify that the function mutates one or more of it’s arguments. In your example the mutating version would be called f! and the other just f.

“mutating” may not only refer to arrays - there are other kinds of containers that can be modified as well, like Dict, Set and similar, so checking for a given method signature also doesn’t work. The convention used by DiffEq.jl or explicitly specifying is best, since at that point it’s clear what the user intended.

1 Like

A problem occurs if your code doesn’t know the name of the function. It could simply be held in some variable.

Maybe functions could have a Mutating trait at some point?

I should add that I don’t need a general solution here. This is just for my little library, where I’d like to have efficient implementations for if the user specifies an in place or out of place function. Of course, I can give the user an argument to specify this themselves, but I thought it might be possible to have a more convenient interface by using the same concept as DifferentialEquations.jl.