2017-07-04 19 views
5

Chúng ta hãy xem xét một thực hiện enum đơn giản với một phương pháp tĩnh kiểm tra xem một giá trị có giá trị liên quan (hiệu quả của việc thực hiện không phải là để được coi đây):Tại sao số nguyên âm không phải là mẫu hợp lệ trong macro?

enum Letter { 
    Alpha = -1, 
    A = 0, 
    B = 1, 
    C = 2, 
} 

impl Letter { 
    pub fn in_enum(value: isize) -> bool 
    { 
     match value { 
      -1 => true, 
      0 => true, 
      1 => true, 
      2 => true, 
      _ => false, 
     } 
    } 
} 

Bây giờ, chúng ta hãy viết một macro để xây dựng enums với phương thức tương đương in_enum. Macro dưới đây được viết với một số hướng dẫn từ hướng dẫn Serde cho enum deserialization as numbers, trong đó khớp với giá trị biến thể enum cũng xảy ra.

macro_rules! my_enum { 
    ($name:ident { $($variant:ident = $value:expr,)* }) => { 
     #[derive(Clone, Copy, Debug, Eq, PartialEq)] 
     pub enum $name { 
      $($variant = $value,)* 
     } 

     impl $name { 
      pub fn in_enum(value: isize) -> bool 
      { 
       match value { 
        $($value => true,)* 
        _ => false, 
       } 
      } 
     } 
    } 
} 

my_enum!(Letter { 
    Alpha = -1, 
    A = 0, 
    B = 1, 
    C = 2, 
}); 

Playground. Bây giờ, trình biên dịch sẽ không chấp nhận biến thể có số nguyên âm.

error: expected pattern, found `-1` 
    --> src/main.rs:13:24 
    | 
13 |      $($value => true,)* 
    |      ^^^^^^ 

Điều này dường như xảy ra bất kể thế nào tôi viết mô hình này xuống trong vĩ mô, hoặc cho dù tôi sử dụng i32 hoặc isize cho tham số value phương pháp. Thay đổi thông số phân đoạn của $value thành pat cũng nằm ngoài câu hỏi: trình biên dịch sẽ từ chối xây dựng enum, ngay cả khi không có giá trị biến thể âm.

error: expected expression, found `-1` 
--> src/main.rs:5:26 
    | 
5 |    $($variant = $value,)* 
    |       ^^^^^^ 

Điều đáng ngạc nhiên là nó hoạt động mà không sử dụng macro, cũng như khi tôi loại bỏ biến thể Alpha.

Tại sao điều này lại xảy ra?

+0

Vì bạn đã khớp với 'expr', không phải là' pat'. Biểu thức và mẫu là hai phần hoàn toàn khác nhau của ngôn ngữ. –

+1

@DK Thật vậy. Nhưng điều đó một mình không giải thích tại sao '0' được chấp nhận như một mẫu trong khi' -1' thì không. Phần mà '-1' được tạo thành từ mã thông báo' -' theo sau là chữ có thể là thủ phạm ở đây. –

+1

Huh. Tôi ngạc nhiên rằng nó chấp nhận '0'. Tôi nghi ngờ đó là vì '-1' là (nếu tôi nhớ chính xác) nội bộ được biểu diễn dưới dạng' Neg :: neg (1) 'chứ không phải là một số nguyên âm, và điều đó có thể vấp phải bất kỳ phần nào của mã đang cố gắng chuyển đổi 'expr' AST thành một mẫu. –

Trả lời

Các vấn đề liên quan