Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
745 views
in Technique[技术] by (71.8m points)

rust - Is there a way to use custom patterns such as a regex or functions in a match?

I'm writing a toy programming language in Rust. I prototyped the parser logic in Ruby:

def rd_tree(chars)
  loop do
    case c = chars.next
    when /s/
      # whitespace stuff
    when "("
      # open paren stuff
    when ")"
      # close paren stuff
    else
      # default stuff
    end
  end
end

And now I'm converting it to Rust:

fn rd_tree(chars: std::str::Chars) {
    while let Some(c) = chars.next() {
        if c.is_whitespace() {
            // whitespace stuff
        } else if c == '(' {
            // open paren stuff
        } else if c == ')' {
            // close paren stuff
        } else {
            // default stuff
        }
    }
}

I resorted to using an if, else-if chain because as far as I can tell, Rust's match feature is limited to destructuring, enums, and type patterns. Is there a way to match on regexes or boolean functions? If not, is there a more idiomatic pattern here than if, else-if? I expect the logic to have more branches in the future and I want it to stay neat.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Not yet. The match patterns must be composed of things that can be statically verified by the compiler.

However, you can use a match guard:

fn rd_tree(chars: std::str::Chars) {
    while let Some(c) = chars.next() {
        match c {
            c if c.is_whitespace() => {}
            '(' => {}
            ')' => {}
            _ => {}
        }
    }
}

A match guard allows you to run a function against whatever the pattern matched.


In the future, constant evaluation may be improved to allow calling functions in place of a pattern:

#[derive(PartialEq, Eq)]
struct Foo {
    f: usize,
    g: usize,
}

impl Foo {
    const fn repeated(x: usize) -> Self {
        Foo { f: x, g: x }
    }
}

fn main() {
    let f = Foo { f: 0, g: 1 };
    match f {
        const { Foo::repeated(22) } => println!("hi"),
        _ => println!("1"),
    }
}

This work is tracked in issue #57240. RFC 2920 "const expressions and patterns" (and its tracking issue #76001) are also relevant.

It's not immediately obvious to me how this would work with your exact example or a regex without a substantial amount of effort though.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...