Suppose I have a function f that allocates, for instance the following
function sum_of_fractions(a)
v = map(x -> 1/(x+a), 1:10)
return sum(v)
end
Assume for the sake of this discussion that I cannot get rid of the temporary vector v by converting the operation to a loop. To get rid of the allocations, one could pass a vector v to use as a buffer:
NB: even though a buffer was passed to it, this still allocates a vector to store the result of map. You’d need something like this to avoid allocating:
function y = sum_of_fractions!(buffer, a)
map!(x -> 1/(x+a), buffer, 1:10)
return sum(buffer)
end
function sum_of_fractions!(buffer::AbstractVector, a::Real)
# https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-captured
fun = let a = a
x -> 1/(x + a)
end
map!(fun, buffer, 1:length(buffer))
sum(buffer)
end
function sum_of_fractions(::Type{T}, len::Integer, a::Real) where {T}
sum_of_fractions!(zeros(T, len), a)
end
Regarding the order of the parameters of the mutating function, see the manual’s style guide: section.
Instead of putting the closure into a local variable, it might sometimes be nicer to create it with a global function:
function my_callable_object(b)
let a = b
x -> 1/(x + a)
end
end
Then create your function by calling my_callable_object, like my_callable_object(a).
Actually in this case I would not use it, and have the name of the variable (buffer) be very clear in that it won’t use the content of buffer in the computation. The other alternative, mentioned above, is to have two methods:
function foo(x)
buffer = similar(x)
return foo!(buffer, x)
end
function foo!(buffer, x)
...
end
Also of note to know about in case it helps: Bumper.jl. I believe it’s very stable and useful now on Linux at least. It will also Work on Windows, less tested, and if it seems to work there or on any platform then it’s as good as on Linux. It’s just that Windows doesn’t overcommit, so it could possibly run out of space in extreme situations.
Is this idiomatic? I believe you would (want to) define foo! if you want to change arguments. And would have a corresponding foo, that doesn’t and reuse that code. Though your way works too, to simplify into one function. Using ! is actually just a convention, though useful to maintain.
I’m thinking, since it’s a common pattern, to have these two similarily named functions, can and should it be handled with a macro, that defines the other for you?
function y = sum_of_fractions(a)
Note, this is not idiomatic. You could skip y = I think this may be from or similar syntax to MATLAB?! [Or you can skip function and use the short form. Though I believe that 3rd form (and more!) works too and you’re making a function named y, as synonym?]