# A particular function that modifies the input

I think I’m going to learn a lot whith this question.

First, my principal goal is to transform any matrix according the following rule:
For each column, find the first element equal to `1.1`. Suposse the position of this elememt is `[n,j]`. So, replaces all elemnts `[n:end,j]` with `[n-1,j]`.
My scripts for this is the following:

``````function tabela_taxas(tab)
for j in 1:size(tab)
aux = tab[:,j]
i = 1
while aux[i] != 1.1
i = i+1
end
element_aux = aux[i-1]
tab[i:end,j] .= element_aux
end
return tab
end
``````

My first question, but not the most important, is that I think there is other way (more elegant) to writte the `tabela_taxas` function.

The second question is related to something strange. First, I will run the `tabela_taxas` function. For this, I’m going to simulate a specific matrix that allows me to test my function

``````tabela = rand(6,5)
tabela[3,1] = 1.1
tabela[2,2] = 1.1
tabela[5,3] = 1.1
tabela[2,4] = 1.1
tabela[2,5] = 1.1
``````

Now, using my function:

``````tabela2 = tabela_taxas(tabela)
``````

You can see that the original matrix, tabela, has been modified. Which shouldn’t happen because the matrix tabela is an input and not an output. It’s as if I had done:

``````tabela = tabela_taxas(tabela)
``````

Can someone explain?

1 Like

The input matrix is the output matrix – notice how your functions modifies and returns the input `tab`, without reassigning to it. If you don’t want to do this, you can add `tab = copy(tab)` to your function before modifying `tab`.
You can confirm that they’re the same matrix via `tabela === tabela2`.

For example:

``````function tabela_taxas!(tab) # mutating definition
for j in axes(tab, 2)
aux = @view(tab[:,j])
i = findfirst(==(1.1), aux)
i === nothing || (aux[i:end] .= aux[i-1])
end
return tab
end

# non-mutating
tabela_taxas(tab) = tabela_taxas!(copy(tab))
``````
4 Likes

In Julia docs for array:

In Julia, all arguments to functions are passed by sharing (i.e. by pointers).

You can read the Wikipedia section to understand passing by sharing. Happy learning!

3 Likes

A pretty common pattern is to write two functions:

``````myfun(x) = myfun!(copy(x))

function myfun!(x)
x = 5 # or some other mutating code
return x
end
``````
5 Likes

I’m not sure this is elegant, and won’t be as fast as @Elrod’s one above, but you can write many such things with `accumulate`:

``````julia> tabela
6×5 Matrix{Float64}:
0.0653491  0.982055  0.419218  0.242059  0.168234
0.149178   1.1       0.398028  1.1       1.1
1.1        0.190122  0.678386  0.854605  0.0642094
0.763535   0.433054  0.278625  0.433437  0.231305
0.0410386  0.528489  1.1       0.229503  0.779562
0.757617   0.383551  0.806496  0.151491  0.782904

julia> accumulate(tabela; dims=1, init=(false, NaN)) do (flag,val),x
(flag || x==1.1) ? (true,val) : (false,x)
end .|> last
6×5 Matrix{Float64}:
0.0653491  0.982055  0.419218  0.242059  0.168234
0.149178   0.982055  0.398028  0.242059  0.168234
0.149178   0.982055  0.678386  0.242059  0.168234
0.149178   0.982055  0.278625  0.242059  0.168234
0.149178   0.982055  0.278625  0.242059  0.168234
0.149178   0.982055  0.278625  0.242059  0.168234
``````
1 Like