Start learning free

LESSON 117 OF 414 · FOR LOOPS - LOOPING OVER ARRAYS

Buggy Code: Using the Loop Variable in println! in Rust

Practice Read the full explanation

Inside the code editor we've tried to write a for loop that prints a tailored message about every language in the languages array.

So when we ran the code, we expected it to print:

I think Python is cool!
I think Java is cool!
I think JavaScript is cool!

but it seems like we made some mistakes because when we run our code, it produces this output:

I think language is cool!
I think language is cool!
I think language is cool!

Assignment:

Your task is to fix our loop such that it will print the desired output.

STEP 1 OF 1
    Ctrl + Enter to check

    RUST · FOR LOOPS - LOOPING OVER ARRAYS

    Buggy Code For Loops 2 in Rust, explained

    Problem overview

    The loop is supposed to print a message about every language in the languages vector. The expected output is:

    I think Python is cool!
    I think Java is cool!
    I think JavaScript is cool!
    

    The code in the editor compiles and runs, but prints the same line three times:

    I think language is cool!
    I think language is cool!
    I think language is cool!
    

    This is the starting code:

    let languages = vec!["Python", "Java", "JavaScript"];
    for language in &languages {
        println!("I think language is cool!");
    }

    Unlike many bugs, this one produces no error. The loop works: the body runs three times, once per language. What it prints is wrong.

    What goes wrong

    Everything between the double quotes of a string literal is plain text. The word language inside "I think language is cool!" is just the letters l-a-n-g-u-a-g-e, not the loop variable that happens to share the name. Rust doesn't look inside a string literal for variable names. So each pass prints identical text, and the loop variable is never read.

    This is a common point of confusion: a name in code refers to a variable, and the same name in quotes refers to nothing. The loop variable language holds "Python" on the first pass, "Java" on the second and "JavaScript" on the third. The message has to be told to use it.

    The fix

    Put a {} placeholder in the format string where the language should appear, and pass the loop variable as the next argument. println! replaces each {} with the next argument after the format string.

    The message in the quotes now has a gap, and the loop variable fills it on every pass. The reference solution is:

    let languages = vec!["Python", "Java", "JavaScript"];
    for language in &languages {
        println!("I think {} is cool!", language);
    }

    Tracing the three passes: language is "Python", so the line is I think Python is cool!. Then it is "Java", then "JavaScript". The output matches the expected one exactly.

    Language details worth knowing

    • Rust does not build strings by writing the variable inside the quotes, and it does not let you join a literal and a &str with +. Placeholders are the standard way.
    • The arguments fill the placeholders in order. With two placeholders, the first argument goes into the first {} and the second into the second.
    • Rust also accepts a variable name inside the braces, as in println!("I think {language} is cool!");. That form prints the same text. The lesson uses the explicit argument form, and both are correct.
    • A {} with no argument, or an argument with no {}, is a compile error, because println! checks the format string against its arguments when the program is compiled.

    Edge cases and common mistakes

    • Writing {language} only works with a plain variable name. For something like languages[0] or a method call, pass it as an argument instead.
    • Putting the variable inside the quotes without braces, which is the bug in this lesson. Nothing warns you, because the text is valid; only the output tells you.
    • Printing the vector instead of the loop variable. {} can't display a Vec, and the compiler reports it.

    Testing

    Run the fixed code and compare the three lines against the expected output. To be sure the loop variable is really used, change "Java" in the vector to "Rust" and run again: the second line should become I think Rust is cool!, with no change to the loop. If a line stays the same after you edit the vector, the message is not reading the variable.

    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free