Abstracting loops

When you find you must perform the same loop logic in various places in your program, you may use a one-off for_expansion to abstract the pattern.

For example, let’s say we have players, a buffer array of Player structs, and as players join over the network this array gets populated while player_count is incremented. You will want to loop over the connected players in various places in your code, and each time you do you must use the same loop logic, which will be one of these:

// option (a)

for player_index: 0 .. player_count - 1 {
    player := players[player_index];
    // ...
}


// option (b)

for player, player_index: players {
    if player_index >= player_count  break;
    // ...
}

Neither of these options are especially nice; there’s more noise than we’d like, and both take two lines to set up (allowing for the possibility of a mistaken omission, particularly with the second option).

We can use a for_expansion to clean this up:

active_players: struct {};
for_expansion :: (_: *type_of(active_players), body: Code, flags: For_Flags) #expand {
    for `it, `it_index: players {
        if it_index >= player_count  break;
        #insert body;
    }
}

Now, any time we want to loop over the active players we simply do this:

for player: active_players {
    // ...
}