Confusion with arrays and functions

I was using a function inside a loop to modify a 2-Dimensional array variable (say DATA) in my code when I realised that the variable changes even when I have not given DATA as an argument or tried to return it to the main body of the program. Instead of the code throwing an error (that DATA is not defined in the function), I got the output I wanted from the code. Consequently, I tried out more possibilities and got even more confused. Each of the possibilities I tried where I expected some error to pop up, I did not get any error and instead got the expected answer.

Why did the compiler not give an error when I did not mention all the arguments?
How does the compiler know what to return at the end of the function?
How do the returned values get stored in the intended location?
What is a good programming practice when modifying an array using a function?

[CODE]

Data1 = 1000 * ones(10);
Data2 = 2000 * ones(10);
Data3 = 3000 * ones(10);
Data4 = 4000 * ones(10);
Data5 = 5000 * ones(10);
Data6 = 6000 * ones(10);
Data7 = 7000 * ones(10);
Data8 = 8000 * ones(10);

function ChangeData1(i)          Data1[i] = Data1[i] + i;                 end;
function ChangeData2(i)          Data2[i] = i;                            end;
function ChangeData3(Data3,i)    Data3[i] = Data3[i] + i;                 end;
function ChangeData4(Data4,i)    Data4[i] = i;                            end;
function ChangeData5(Data5,i)    Data5[i] = Data5[i] + i;    return Data5 end;
function ChangeData6(Data6,i)    Data6[i] = i;               return Data6 end;
function ChangeData7(i)          Data7[i] = Data7[i] + i;    return Data7 end;
function ChangeData8(i)          Data8[i] = i;               return Data8 end;

for i in 1:10
    ChangeData1(      i);
    ChangeData2(      i);
    ChangeData3(Data3,i);
    ChangeData4(Data4,i);
    ChangeData5(Data5,i);
    ChangeData6(Data6,i);    
    ChangeData7(      i);
    ChangeData8(      i);    
end

println(Data1')
println(Data2')
println(Data3')
println(Data4')
println(Data5')
println(Data6')
println(Data7')
println(Data8')

[OUTPUT]

[1001.0 1002.0 1003.0 1004.0 1005.0 1006.0 1007.0 1008.0 1009.0 1010.0]
[1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0]
[3001.0 3002.0 3003.0 3004.0 3005.0 3006.0 3007.0 3008.0 3009.0 3010.0]
[1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0]
[5001.0 5002.0 5003.0 5004.0 5005.0 5006.0 5007.0 5008.0 5009.0 5010.0]
[1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0]
[7001.0 7002.0 7003.0 7004.0 7005.0 7006.0 7007.0 7008.0 7009.0 7010.0]
[1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0]

[EDIT]
I realised that if I use variable names in function different from those used in main code, some functions throw errors. So the following are more observations:

[CODE]

Data1 = 1000 * ones(10);
Data2 = 2000 * ones(10);
Data3 = 3000 * ones(10);
Data4 = 4000 * ones(10);
Data5 = 5000 * ones(10);
Data6 = 6000 * ones(10);

function ChangeData1(Data,j)    Data[j] = Data[j] + j;    return Data end;
function ChangeData2(Data,j)    Data[j] =           j;    return Data end;
function ChangeData3(Data,j)    Data[j] = Data[j] + j;    return Data end;
function ChangeData4(Data,j)    Data[j] =           j;    return Data end;
function ChangeData5(Data,j)    Data[j] = Data[j] + j;                end;
function ChangeData6(Data,j)    Data[j] =           j;                end;

for i in 1:10
    Data1 = ChangeData3(Data1,i);
    Data2 = ChangeData4(Data2,i);
    ChangeData3(Data3,i);
    ChangeData4(Data4,i);
    ChangeData5(Data5,i);
    ChangeData6(Data6,i);    
end

println(Data1')
println(Data2')
println(Data3')
println(Data4')
println(Data5')
println(Data6')

[OUTPUT]

[1001.0 1002.0 1003.0 1004.0 1005.0 1006.0 1007.0 1008.0 1009.0 1010.0]
[1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0]
[3001.0 3002.0 3003.0 3004.0 3005.0 3006.0 3007.0 3008.0 3009.0 3010.0]
[1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0]
[5001.0 5002.0 5003.0 5004.0 5005.0 5006.0 5007.0 5008.0 5009.0 5010.0]
[1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0]

Hello,

You may find this page helpful: https://docs.julialang.org/en/v1/manual/variables-and-scoping/.

The compiler does not error because the variables (data1-8) are in the global scope (Main.Data1,…) even when you don’t pass them as argument.

The return value of a function is the return value of the last expression by default. Unless you have an explicit return ....

While ChangeData1(i) and ChangeData3(Data1 #not 3,i) will mutate Data1 in the same way. When Data1 is an argument, the julia compiler produces more efficient code. So a “better practice” is passing in an argument. However, it is not needed, and may not matter for non performance critical code.

Hope this helps.

2 Likes

Thanks a lot for clarifying it! The links were helpful.