Exercise 5: A More Complex Example

In this task, we'll be implementing code to make the following syntax possible:

fn main() {
for_2d!(row <i32> in 1..5, col <i32> in 2..7, {
    // code
});
}

Ignoring extra curly braces, this code should translate to

fn main() {
for row in 1..5 {
    let row: i32 = row;
    for col in 2..7 {
        let col: i32 = col;
        // code
    }
}
}

Note that the names of the variables may change (i.e. they could be row and col, or x and y, or something else).

To complete this task, there more fragment specifiers you will need to know about:

  • ident: an "identifier", like a variable name. ident metavariables Can be followed by anything.
  • block: a "block expression" (curly braces, and their contents). Can be followed by anything.
  • ty: a type. Can only be followed by =>, ,, =, |, ;, :, >, >>, [, {, as, where, or a block metavariable.

As a reminder, you may not edit the main function, but it should eventually look like the following:

fn main() {
    for row in 1..5 {
        let row: i32 = row;
        for col in 2..7 {
            let col: i32 = col;
            { (Coordinate { x: col, y: row }).show() }
        }
    }
    let values = [1, 3, 5];
    for x in values {
        let x: u16 = x;
        for y in values {
            let y: u16 = y;
            {
                (Coordinate {
                    x: x.into(),
                    y: y.into(),
                })
                    .show()
            }
        }
    }
}