Rfcs: `match for` syntax to simplify matching across a for loop

Created on 12 May 2016  路  6Comments  路  Source: rust-lang/rfcs

I'm offering a simple suggestion for improving the readability of Rust code. If you think it's a bad idea, feel free to close the issue. I've noticed a pattern throughout my experience of writing code in Rust that could be better written with a simpler syntax, match for. The current syntax for writing a match for loop is as follows:

for token in pattern {
    match token {
        // matching code
    }
}

However, I am suggesting that it might be a good idea to also implement the following which will serve as syntactic sugar for the above and will eliminate the redundancy:

match for token in pattern {
    // matching code
}

As an example in some real world code, I currently have the following:

for pattern in self.template.clone() {
    match pattern {
        TemplateToken::Character(value) => filename.push(value),
        TemplateToken::Series  => if !self.no_name { filename.push_str(self.series_name.clone().as_str()); },
        TemplateToken::Season  => filename.push_str(self.season_number.to_string().as_str()),
        TemplateToken::Episode => filename.push_str(episode.to_padded_string('0', self.pad_length).as_str()),
        TemplateToken::Title   => if self.tvdb { filename.push_str(title); }
    }
}

However, it could be better written as the following simplified form:

match for pattern in self.template.clone() {
    TemplateToken::Character(value) => filename.push(value),
    TemplateToken::Series  => if !self.no_name { filename.push_str(self.series_name.clone().as_str()); },
    TemplateToken::Season  => filename.push_str(self.season_number.to_string().as_str()),
    TemplateToken::Episode => filename.push_str(episode.to_padded_string('0', self.pad_length).as_str()),
    TemplateToken::Title   => if self.tvdb { filename.push_str(title); }
}
T-lang

Most helpful comment

Personally, I'm not sure it's enough convenience to justify adding more syntax to Rust. I would suggest writing a macro.

Additional points:

  • This precise form of the syntax may be ambiguous, since for ... in ... { ... } is itself an expression.
  • Unless I'm mistaken, in your reduced syntax naming the pattern itself is redundant. So it could be match for self.template.clone() (doesn't read quite as well) or something.

All 6 comments

Personally, I'm not sure it's enough convenience to justify adding more syntax to Rust. I would suggest writing a macro.

Additional points:

  • This precise form of the syntax may be ambiguous, since for ... in ... { ... } is itself an expression.
  • Unless I'm mistaken, in your reduced syntax naming the pattern itself is redundant. So it could be match for self.template.clone() (doesn't read quite as well) or something.

At least in my example above, the pattern in match for pattern in self.template.clone() isn't used as I'm just matching across an enum where I will always know all the possible values, but in many other cases where you will not know all possible values, it would be used like so:

let mut tokens = Vec::new();
match for element in expression {
    '+' => tokens.push(Token::Plus),
    '-' => tokens.push(Token::Minus),
    ...
    _ => tokens.push(Token::Number(element))
}

match accepts expressions as input so it should be acceptable. You can, for example, do the following with match:

match for (id, value) in expressions.enumerate() {
    // code here
}

Which would desugar into

for (id, value) in expressions.enumerate() {
    match (id, value) {
        // code here
    }
}

Well for your first example there, it could be

let mut tokens = Vec::new();
match for expression {
    '+' => tokens.push(Token::Plus),
    '-' => tokens.push(Token::Minus),
    ...
    element => tokens.push(Token::Number(element))
}

I suppose that would work pretty well.

Even the shortened syntax has ambiguities:

match for A { a } in Some(A{a: 5}).into_iter() {} {
    () => {}
}

FYI, this was also discussed previously in internals

Was this page helpful?
0 / 5 - 0 ratings