Best practice for ! functions

#1

I often try to write mutating functions to avoid unnecessary allocation. But sometimes I have to use the same function and allocate a new array. This usually means that I have to create a new function with almost the same content.

A = randn(3)
function foo!(A)
    A .= A ./ 2
    return nothing
end


function foo()
    A = randn(3)
    A .= A ./ 2
    return A
end

Is there a good practise to avoid copy/paste of mutating functions into normal functions? Would this example is considered a right approach?

function foo2()
    A = randn(3)
    foo!(A)
    return A
end

Thanks!

0 Likes

#2

Yes, that’s a good pattern to use. You can express it more concisely like this:

function foo!(A)
    A .= A ./ 2
    return A
end

foo() = foo!(randn(3))
5 Likes

#3

thanks! what if I have multiple function arguments, for which I also would like to specify types?

C=0.5
function foo(C::Float64)
    A = randn(3)
    A .= A ./ 2 .+ C
    return A
end

A = randn(3)
function foo!(A,C::Float64)
    A .= A ./ 2 .+ C
    return nothing
end

foo2(C::Float64) = foo!(randn(3),C::Float64)

the last expression does not work

0 Likes

#4

It does work — it’s just that your foo! function returns nothing. I think you want it to return A instead.

Note that you don’t need to annotate C with a type when calling foo;

foo2(C::Float64) = foo!(randn(3), C)

will work just as well.

1 Like