# How to apply an in-place function to a slice of a vector?

I want to have an in-place function that takes a vector as an argument and applies another in-place function to a subarray (in general sense).
How do I do this?

``````function f!(du, u)
println("\nf called")
@show u
du .= reverse(u)
return nothing
end

"""
Applies f!() to the first 2 elements.
"""
function g!(du, u)
f!(du[1:2], u[1:2])
du[3] = 17
return nothing
end

du = zeros(2)
u = [3, 11]

dug = zeros(3)
ug = [u; 0]

@show f!(du, u)
@show du

@show g!(dug, ug)
@show dug
``````

gives

``````f called
u = [3, 11]
f!(du, u) = nothing
du = [11.0, 3.0]

f called
u = [3, 11]
g!(dug, ug) = nothing
dug = [0.0, 0.0, 17.0] # why not [11, 3, 17]?
``````

In julia `du[1:2]` gives a copy of the slice, not a view (unfortunately). You can use the `@view` or `@views` macros, or the `view` function directly to construct views.

So your `g!` function should be

``````function g!(du, u)
@views f(du[1:2], u[1:2])
du[3] = 17
return nothing
end
``````
1 Like

That is, this creates a new object in memory, even without binding it to any name?

Bindings and allocations are totally different concepts, yes.

2 Likes

Does this behaviour affect only function calls? Do I understand correctly that slices passed by value?

In REPL, I can update the array with

``````u = zeros(3)
u[1:2] = ones(2)
``````

and get `[1, 1, 0]` as expected.

No, we just made the (IMO misleading) choice to have `u[1:2] = ones(2)` to be special syntax for `setindex!(u, ones(2), 1:2)`.

The `u[1:2]` there is never creating a slice, itâ€™s just part of the `setindex!` syntax.

1 Like

Iâ€™m afraid I donâ€™t get it completely.
Iâ€™m okay with the fact itâ€™s some â€śspecial syntaxâ€ť. But why does it work in REPL and not in a function (where it requires `@view`}? Where else will it not work?

the distinction isnâ€™t repl vs function itâ€™s before it after an equal sign.

6 Likes

When Julia sees `arr[indices...] = v`, it translates it to `setindex!(arr, v, indices...)` at an early stage. Docs: `setindex!`.

5 Likes

Incidentally, I believe `reverse(u)` will allocate a intermediare temporary vector. A lazy non-allocated version can be had by using `Iterators.reverse` or reverse the indices of a `view`, ie

``````du .= @view u[end:-1:begin]
``````
4 Likes

Thanks. Reverse is there only to provide a MWE.

Sure, but since the question concerns in-place operations and allocations, and since I expect almost everything in an MWE to be relevant, I assumed this was too.

1 Like