سؤال

In the following example:

fn main() {
  let str_vec: ~[&str] = "lorem lpsum".split(' ').collect();

  if (str_vec.contains("lorem")) {
    println!("found it!");
  }
}

It will not compile, and says:

error: mismatched types: expected &&'static str 
but found 'static str (expected &-ptr but found &'static str)

What's the proper way to find the word in sentence?

هل كانت مفيدة؟

المحلول 2

let sentence = "Lorem ipsum dolor sit amet";
if sentence.words().any(|x| x == "ipsum") {
    println!("Found it!");
}

You could also do something with .position() or .count() instead of .any(). See Iterator trait.

نصائح أخرى

The contains() method on vectors (specifically, on all vectors satisfying the std::vec::ImmutableEqVector trait, which is for all vectors containing types that can be compared for equality), has the following signature,

fn contains(&self, x: &T) -> bool

where T is the type of the element in the array. In your code, str_vec holds elements of type &str, so you need to pass in a &&str -- that is, a borrowed pointer to a &str.

Since the type of "lorem" is &'static str, you might attempt first to just write

str_vec.contains(&"lorem")`

In the current version of Rust, that doesn't work. Rust is in the middle of a language change referred to as dynamically-sized types (DST). One of the side effects is that the meaning of the expressions &"string" and &[element1, element2], where & appears before a string or array literal, will be changing (T is the type of the array elements element1 and element2):

  1. Old behavior (still current as of Rust 0.9): The expressions &"string" and &[element1, element2] are coerced to slices &str and &[T], respectively. Slices refer to unknown-length ranges of the underlying string or array.

  2. New behavior: The expressions &"string" and &[element1, element2] are interpreted as & &'static str and &[T, ..2], making their interpretation consistent with the rest of Rust.

Under either of these regimes, the most idiomatic way to obtain a slice of a statically-sized string or array is to use the .as_slice() method. Once you have a slice, just borrow a pointer to that to get the &&str type that .contains() requires. The final code is below (the if condition doesn't need to be surrounded by parentheses in Rust, and rustc will warn if you do have unnecessary parentheses):

fn main() {
  let str_vec: ~[&str] = "lorem lpsum".split(' ').collect();

  if str_vec.contains(&"lorem".as_slice()) {
    println!("found it!");
  }
}

Compile and run to get:

found it!

Edit: Recently, a change has landed to start warning on ~[T], which is being deprecated in favor of the Vec<T> type, which is also an owned vector but doesn't have special syntax. (For now, you need to import the type from the std::vec_ng library, but I believe the module std::vec_ng will go away eventually by replacing the current std::vec.) Once this change is made, it seems that you can't borrow a reference to "lorem".as_slice() because rustc considers the lifetime too short -- I think this is a bug too. On the current master, my code above should be:

use std::vec_ng::Vec;  // Import will not be needed in the future

fn main() {
  let str_vec: Vec<&str> = "lorem lpsum".split(' ').collect();

  let slice = &"lorem".as_slice();
  if str_vec.contains(slice) {
    println!("found it!");
  }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top