2016-03-10 3 views
3

Как новичок в Rust, я наткнулся на два, по-видимому, действительных способа запуска match на ссылочном типе. Предположим, что я определил enum Color { Red, Yellow, Green, Teal, Blue, Purple }, и я хочу реализовать функцию, которая работает на ссылке &self экземпляра этого перечисления.Должно ли & быть разыменовано до того, как оно будет сопоставлено?

Я вижу два пути, чтобы написать такую ​​функцию:

impl Color { 

    // Approach #1: Match the reference, using references in each pattern 
    fn contains_red(&self) -> bool { 
     match self { 
      &Color::Red => true, 
      &Color::Yellow => true, 
      &Color::Purple => true, 
      _ => false, 
     } 
    } 

    // Approach #2: Dereference &self and match the patterns directly 
    fn contains_blue(&self) -> bool { 
     match *self { 
      Color::Blue => true, 
      Color::Teal => true, 
      Color::Purple => true, 
      _ => false, 
     } 
    } 
} 

Изначально я ожидал, что разыменования &self будет учитываться как движение, и может вызвать ошибки, если я назвал color.contains_blue() на тот же экземпляр дважды в строка, но это, похоже, не так.

Являются ли эти подходы функционально идентичными? Кто-нибудь из них сломается, если я буду сопоставлять более сложные объекты?

+2

Мне сказали разыгрывать аргумент соответствия (ваш подход №2), поскольку он более идиоматичен, потому что он имеет меньше беспорядка. Надеюсь, кто-то сможет ответить на более авторитетный ответ. :-) – Shepmaster

+0

Просто, чтобы убедиться: 'Цвет' не' Копия', правильно? –

+0

@Matthieu Nope, это определено как показано выше, без атрибутов. Но если это существенно повлияет на поведение, я бы хотел услышать об этом. – KChaloux

ответ

6

Вы не можете перейти от неизменяемой ссылки, поэтому вам не нужно беспокоиться об этом.

Это стоит учесть, что можно было бы ожидать матчей работать несколько сродни (Partial) Eq, и это занимает &self. Другими словами, можно было бы ожидать, что он будет ссылаться неявно, если не будет принудительным. Это легко подтверждается небольшими экспериментами.

Следует отметить, что *self is не a move - это ссылка на ячейку памяти. It is thus an lvalue. Следовательно,

Когда выражение головы именующий, матч не выделяет временное местоположение (однако, по значению связывания может скопировать или переместить из-значения).

https://doc.rust-lang.org/reference.html#match-expressions

Если временное место не выделяется, движение не может произойти. Таким образом, поведение гарантировано. В качестве замещающих заметок внутренние данные все равно могут быть удалены из шаблона деструкции, что может вызвать проблему. Это, однако, верно, независимо от того, согласны ли вы на self или *self.

Использование *self представляется неофициальной идиомой и должно быть предпочтительным.

+1

Это помогает понять многое. Зная, что переход не может произойти при использовании чего-то в качестве значения lleue, имеет большой смысл. – KChaloux

1

Я лично предпочитаю второй. На мой взгляд, это лучше всего отражает намерение.

Смежные вопросы