Style question for functions with in place transforms and return types


#1

If I have a function which performs an in place transformation on an argument and also returns a result, what is the appropriate style? The following works as I intend, but I’m wondering if this will get me into trouble at some point. Should I be coding this kind of computation in a different way?

function f!(X)
    @. X = sin(X);
    m = maximum(X);
    return m
end

#2

There are two approaches that are used. The first is as you have done, make the in place alteration and return the altered item even though it is not necessary because anything that can be altered in place tends to be given indirectly and the alteration sticks to the target of that indirection. Still, there are situations where you may want to provide access to the revision directly back to the caller. Then it is necessary to return it, because you cannot presume the caller to have the same access to the data structures that you do.

The other is to return nothing:

function fn!(x)
    # alter x in place
    return nothing
end

I use that form when there is reason to emphasize to the caller that it would be inappropriate to re-handle the updated information, or just to keep the interfaces clean.


#3

It is perfectly reasonable to return a value from an in-place function; most in-place functions in Julia return something useful.

You usually want to think about how your function f!(X) might be composed with other function in order to decide on the return value.

For example, many in-place functions return the altered collection, so that you can compose them with other functions that act on collections, e.g.

first(sort!(push!(A, x))) # returns first element of sorted [A; x]

In other cases, e.g. eigvals!(A), it is more useful to return some quantity computed from the altered collection. It sounds like that may be analogous to your situation.


Best way to shuffle elements in a vector of vectors
#4

In your alternative method with the return nothing, how would you handle that when I wanted to return something in addition to performing the in place transformation?


#5
function fn!(x)
    # alter x in place
    something = result_of_doing_something()
    return something
end

#6

Also, is your Julia example with the return nothing the analog of writing a void function in C that terminates with return;?


#7

What is “C”? :wink:

I cannot recall … no longer am I 2 b a C designer


#8

Strictly speaking no, nothing is a value. Conceptually mapping to C here is not that useful.


#9

Perhaps the chosen example obscures the question a bit.

Is modifying X a primary purpose of f! or is it a side effect of a performance optimization? That is, could you just use maximum(sin, X), and leave X unchanged?

If you actually want to change X, you might consider splitting this into two function calls, modify!(X) and reducefunction(X).

If that is harder to do than your example implies, then I think that I, personally, would return both values, like this: return (X, m).