Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List iteration loop enhancements #152

Closed
cardillan opened this issue Sep 25, 2024 · 1 comment
Closed

List iteration loop enhancements #152

cardillan opened this issue Sep 25, 2024 · 1 comment
Labels
experimental Experimental feature (implemented, waiting for evaluation)

Comments

@cardillan
Copy link
Owner

Changes to the syntax

Two non-breaking changes to the existing syntax:

  • Parentheses around the list will become optional.
  • There will be an optional do keyword separating the list from the loop body (this will actually be added to all variants of the loops).

List iteration with multiple control variables

The list iteration loop will support multiple control variables. The length of the list will have to be a multiple of the number of control variables in that case, and it will be traversed in these multiples. Example:

for unit, amount in @mono, 5, @poly, 3, @mega, 1 do
    process_units(unit, amount);
end; 

def process_units(unit, amount)
    // Do something here
end;

The process_units function will be called three times, with the @mono, 5, @poly, 3 and @mega, 1 values passed in as arguments.

List iteration with modifications

By applying the out modifier on a list iteration control variable, any modifications to the variable will be transferred back to the variable in the list then the current iteration ends (either normally or through the continue statement). Not all list control variables need to be marked as out:

for out unit, item in
    unit1, @coal,
    unit2, @lead,
    unit3, @sand,
    unit4, @copper
do
    if unit.dead !== 0 then
        unit = find_unit(@poly); // Bind new unit, as this one is dead
    end; 
    // Make the unit mine the required material here
end;

Control variables marked as out must not be assigned a constant value from the list:

for out i in a, b, 3, d do ... // error: 3 is a constant and cannot accept new value 

When the loop is exited via break, the values made to the out control variable in the last iteration won't be written back to the list:

count = 0;
for out i in a, b, c, d do
    i = count++;
    if count > 2 then break; end;    
end;

a will be set to 0, b to 1 and c and d will remain unmodified.

If the initial value of an out out variable isn't used by the loop, the loop can be used to initialize the variables in the list:

for out i, out j in a, b, c, d do
    print(i); 
    i = rand(100);
    j = 2 * i;
    print(j);
end;

Variables a and c will be reported as uninitalized. Variables b and d won't.

Also, while the compiler generates the assignments to j at the beginning of the loop, the Data Flow optimization will remove them. It is therefore not necessary to distinguish in the source code between variables that read the initial value from the list elements and variables that don't, and there won't be a syntax for that.

Current limitations

Features described above will be part of the next release. In the initial implementation, the out variables will not support assigning a new value to an external variable.

Also, code produced by unrolling a loop with modifications might not be optimal; #151 was created to address this.

Syntax considerations

The parentheses around the list were made optional. This makes it look similar to the for-style loop, where the initialization, condition and loop increment expressions aren't enclosed in parentheses either, and consistent with the overall Mindcode syntax, which avoids parentheses where possible. Instead, the do keyword was added as a delimiter between the list/loop condition and the loop body.

When using multiple loop control variables, the syntax doesn't support separating the list entries into tuples - we do not do this:

for (unit, amount) in (@mono, 5), (@poly, 3), (@mega, 1) do
    process_units(unit, amount);
end; 

The reasons are twofold:

  • There are currently no plans to support tuples in the syntax anywhere else, so this would be a one-off construct
  • In the future, the loop might be enhanced to support arrays. It might be possible to allow iterations over an array and a fixed list like this:
var units[3];      

for unit, type in units, (@mono, @poly, @mega) do
    unit = ubind(type); 
end; 

The grouping would, therefore, be done on "inlined arrays", not tuples.

@cardillan cardillan added the enhancement New feature or request label Sep 25, 2024
@cardillan cardillan added experimental Experimental feature (implemented, waiting for evaluation) and removed enhancement New feature or request labels Oct 8, 2024
@cardillan
Copy link
Owner Author

The feature will be promoted to standard in version 3.0, closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
experimental Experimental feature (implemented, waiting for evaluation)
Projects
None yet
Development

No branches or pull requests

1 participant