Should a function be named with `!` if it only modifies a container type's inner values?

If A is a container type like:

struct A
    values::Vector
end
# Or
struct A
    values::Tuple
end

where A should hold a number of custom types B:

mutable struct B
    x
end

If a function called modify! can change B.x to a different value, and I want to apply modify! to A{B}. Should it be called modify or modify!?

modify!(a::A) = map(modify!, a.values)

In Julia, ! should be added to names of functions that modify their arguments.

I’d say anything that does an in-place mutation should have an ! appended, no matter where that mutation is happening. To me, if I see a function without an !, I assume that the author of the function is promising me that it will only create new values.

2 Likes

What about functions may or may not change the values (depends on what the values are), should they be appended a bang !?

Could you give a more concrete example? If there are two different behaviors, it feels like it should probably be two different functions, but I might be missing something!

It’s like this in my code. A simpler version is this:

function execute!(job::AbstractJob)
    if issucceeded(job)
        return job  # Just return the job if it has succeeded
    else
        return dispatch!(job)
    end
end

For AbstractJobs that are already succeeded, I just return it back (it is a cached value) since I do not want to run it again, but if it is not run, I will use a function that will modify its values.

I suppose if there’s a chance where the job could be modified, then I should append a !.

Ah, I see what you’re saying! Manager methods that can kick off a bunch of different actions depending on state. Some mutating, some not.

I’m inclined to say yes to !, but this is also the point where clear docs are way more important than a naming convention. As long as you’re clear that mutation is a possibility, then it doesn’t really matter how you get it across to a user. Or at least, that is my two cents.

2 Likes

I would say absolutely yes to using !. Having a trailing ! is no guarantee that the input will change, only a warning that it might. For example, empty! applied to an already empty collection will not change it. And any updating function that overwrites a value with the same value, is still mutating.

Yes, imo, without a doubt, use !

2 Likes