Is Using a Function Inside a For Loop Bad Practice?

programming practicesprogramming-languages

I recently read somewhere that calling a function within a loop is considered bad practice. Is this true? So for example, if I had the following:

function foo(value){
    console.log(value);
}

var bar = ["Foo", "Bar"];

for(var i = 0; i < bar.length; i++){
    foo(bar[i]);
}

Is it bad practice do do this? Should there be another way I should be calling foo?

Note: This question is not specific to Javascript, it's just what I wrote the question in.

Best Answer

It's not a bad practice... it all depends on what the function is doing, and whether the code in the function needs to be within a loop, or whether it can be refactored outside of a loop.

A function is just a set of instructions, so you could, theoretically, take any function's instructions and put them directly inside the loop, and you have essentially the same thing. If that set of instructions is to add two plus two, you don't have much to worry about. If that set of instructions is to open a database table of 10 million rows, find a row, write the values to disk, close the connection and repeat, then you've got something to think about.

Often times, regardless of how long it actually takes, it might just plain be required even if it's not performant. Other times, you could really put some dumb stuff in a loop.

Let's take the "open a database table of 10 million rows and write each row's values to a file" example.

Bad loop:

int count = GetFullCountFromSomewhere();
for (int i = 0 i < count; i++) {
   GetMyRow(i);
   WriteMyRow(i);
}

function GetMyRow(i) {
   Table table = new Table();
   table.Fill(someConnection);
   Row row = table.Rows[i];
   return row;
}

In the above, a table instance (and all of the associated overhead) is done necessarily for each iteration.

Better loop:

Table table = GetMyTable()
for (int i = 0 i < table.Rows.count; i++) {
   WriteMyRow(table.Rows[i]);
}

function GetMyTable(i) {
   Table table = new Table();
   table.Fill(someConnection);
   return table;
}

or, perhaps even better (as it could be internally optimized by the language compiler):

Table table = GetMyTable();
ForEach(var row in Table.Rows) {
    WriteMyRow(row);
}

So, you can see a few ways that we could manage code within a loop versus setting it up outside of the loop.

That's really the only thing worth considering, at least on a day to day basis.