Home > Back-end >  How can I write my own function for matching string patterns?
How can I write my own function for matching string patterns?

Time:09-21

I'm trying to replace all non-alphanumeric characters in a String with _. So far, I've figured out how to do the opposite:

fn main() {
    let a = String::from("hello!");
    println!("{}", sanitize(a)); // prints "_____!"
}


fn sanitize(check: String) -> String {
    check.replace(char::is_alphanumeric, "_")
}

When I try to invert the Pattern on the check.replace line, I get an error:

fn main() {
    let a = String::from("hello!");
    println!("{}", sanitize(a)); // should print "hello_"
}


fn sanitize(check: String) -> String {
    check.replace(!char::is_alphanumeric, "_")
}
error[E0600]: cannot apply unary operator `!` to type `fn(char) -> bool {char::methods::<impl char>::is_alphanumeric}`
   --> src/main.rs:146:19
    |
146 |     check.replace(!char::is_alphanumeric, "_")
    |                   ^^^^^^^^^^^^^^^^^^^^^^ cannot apply unary operator `!`

What would be the syntax for inverting this Pattern, so that I can replace non-alphanumeric characters?

I notice in the documentation for matches that char::is_alphanumeric is a valid Pattern because it is "a function or closure that determines if a character matches". I presume I could write my own function if needed, but are there are restrictions on how that function should be written?

CodePudding user response:

The idiomatic way would be to use a closure (unless you really need a separate function that you use in multiple places). As you've seen in the docs, the pattern can be "a function or closure" which matches the signature FnMut(char) -> bool. Using a closure that simply negates char::is_alphanumeric would look like this:

fn sanitize(check: String) -> String {
    check.replace(|c| !char::is_alphanumeric(c), "_")
}

CodePudding user response:

Seems like a custom function can be used anywhere that a Pattern is required so long as it takes a char as its only argument, and returns a bool. Doc:

impl<'a, F> Pattern<'a> for F where
    F: FnMut(char) -> bool, 

In my case, I ended up with the below:

fn main() {
    let a = String::from("hello!");
    println!("{}", sanitize(a)); // should print "hello_"
}


fn sanitize(check: String) -> String {
    check.replace(evil_chars, "_")
}

fn evil_chars(c: char) -> bool {
    !char::is_alphanumeric(c)
}
  • Related