# How to define a function to be used in a loop?

I have written following piece of codes which is a part of very larger program.

x = ConstantArray[0, 7];
i0 = Range[-2, 2]/2;
i1 = RandomReal[{-2, 2}, {400, 7}];
For[u = 1, u <= 7, u++, x[[u]] = Position[Abs[i1[[300, u]] - i0], Min[Abs[i1[[300, u]] - i0]]]];


The question is when I am going to change it in a way to look simpler by defining a function as:

index[u_] := Abs[i1[[300, u]] - i0];


and the For loop like:

For[u = 1, u <= 7, u++, x[[u]] = Position[index[u], Min[index[u]]]];


I face this error:

SetDelayed::write: Tag Abs in Abs[{1.,0.5,0.,-0.5,-1.}+{0.498994,2.91363,1.70631,-0.708323,-1.91564,-0.708323,1.70631}][u_] is Protected.

Note that the number "300" has been chosen arbitrarily and it can be any number between "1" and "400" or the For command itself can be in an outer loop iterating "1-400". Thanks in advance.

• try with clean Kernel before trying the second case loop. Do you still get the error? Or write ClearAll[x,i0,i1] before trying again. – Nasser Jun 10 at 6:49
• Besides, you might get a slightly faster execution time when changing the For loop to Position[index[#], Min[index[#]]] & /@ Range[7] – mgamer Jun 10 at 7:26

There's no need to use Position, it's faster to just look for the position of the smallest element directly with Ordering:

i0 = Range[-2, 2]/2;
i1 = RandomReal[{-2, 2}, {400, 7}];
x = Table[First[Ordering[Abs[i1[[300, u]] - i0], 1]], {u, 7}]


Also, Table is generally preferred over pre-allocating a list and populating it with For.

If you insist on the format of x with the nested curly braces, then replace the last line with

x = Table[{Ordering[Abs[i1[[300, u]] - i0], 1]}, {u, 7}]


Rewriting it like this fixes the error:

index[start_Integer, u_Integer] := Abs[i1[[start, u]] - i0];


Then, your for loop becomes this

For[u = 1, u <= 7, u++, x[[u]] = Position[index[300, u], Min[index[300, u]]]];


This yields the same result as your initial code and uses a function.

One suggestion, try to avoid "For" loops. Since you are just iterating over a row, this would do the trick:

With[{row = i1[[300]]}, Position[Abs[# - i0], Min[Abs[# - i0]]] & /@ row]


It also yields the same result, which is this: {{{3}}, {{1}}, {{3}}, {{5}}, {{3}}, {{1}}, {{5}}}