4

I did something like this, which works:

let s = " \"".as_bytes();
let (space, quote) = (s[0], s[1]);

I wanted to do something like this

&[space, quote] = " \"".as_bytes();

But it gives me the error

slice pattern syntax is experimental (see issue #23121)

Is it possible to do something similar?

TerraPass
  • 1,562
  • 11
  • 21
x4rkz
  • 513
  • 4
  • 19
  • as described in the error the syntax is experimental, so you'd better not use it for now. Why you want to use the slice pattern? – kennytm Jul 23 '16 at 19:23
  • Does it mean it is not implemented yet? I turns out that I don't need to do it anymore because I found a better solution for my problem. However, I was still curious about why it is not working. And I might need to use it some day. – x4rkz Jul 23 '16 at 19:31
  • 1
    @x4rkz: Experimental means that it is not yet decided whether it would be implemented as is, implemented in another way, or not implemented at all. It's in flux. – Matthieu M. Jul 23 '16 at 19:35
  • 1
    It is implemented but the semantics could change anytime. To prevent accidentally breaking your code, you need to explicitly tell the compiler to opt-in for these unstable features to use it. – kennytm Jul 23 '16 at 19:36
  • Did you go look at [issue 23121](https://github.com/rust-lang/rust/issues/23121), as the error message says? – Shepmaster Jul 23 '16 at 23:11

1 Answers1

6

As the error tells you, slice pattern syntax is experimental. This means either the semantics are not clear or the syntax might change in the future. As a result, you need a nightly version of the compiler and to explicitly request that feature:

#![feature(slice_patterns)]

fn main() {
    match " \"".as_bytes() {
        &[space, quote] => println!("space: {:?}, quote: {:?}", space, quote),
        _ => println!("the slice lenght is not 2!"),
    }
}

Also note that you can't just write &[space, quote] = whatever anyway because there is a possibility that whatever is not the right length. To make the pattern matching exhaustive, you need a _ case or a case with ... What you tried would give another error:

error[E0005]: refutable pattern in local binding: `&[]`, `&[_]` and `&[_, _, _, ..]` not covered
 --> src/main.rs:4:9
  |
4 |     let &[space, quote] = " \"".as_bytes();
  |         ^^^^^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _, _, ..]` not covered
  |
  = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
  = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
help: you might want to use `if let` to ignore the variant that isn't matched
  |
4 |     if let &[space, quote] = " \"".as_bytes() { /* */ }

As of Rust 1.26 you can pattern match on an array instead of a slice. If you convert the slice to an array, you can then match on it:

use std::convert::TryInto;

fn main() {
    let bytes = " \"".as_bytes();

    let bytes: &[_; 2] = bytes.try_into().expect("Must have exactly two bytes");
    let &[space, quote] = bytes;

    println!("space: {:?}, quote: {:?}", space, quote);
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
mcarton
  • 27,633
  • 5
  • 85
  • 95