Развернуть BTreeSet в ржавчину - PullRequest
0 голосов
/ 22 января 2020

В ржавчине допустима следующая функция:

fn unwrap<T>(s:Option<T>) -> T {
    s.unwrap()
}

Она берет на себя владение s, паникует, если это None, и возвращает владение содержимым s (которое является законным, поскольку Option владеет его содержимым.)

Я пытался написать аналогичную функцию с подписью

fn unwrap_set<T>(s: BTreeSet<T>) -> T { 
  ...
}

Идея состоит в том, что он паникует, если s не имеет размер 1 , в этом случае он возвращает единственный элемент. Похоже, что это должно быть возможно по той же причине, по которой unwrap возможен, однако ни один из методов в BTreeSet не имеет правильной подписи (они должны иметь возвращаемый тип T). Ближайшим был take, и я попытался сделать

    let mut s2 = s;
    let v: &T = s2.iter().next().unwrap();
    s2.take(v).unwrap()

, но это не удалось.

Возможно ли написать функцию типа unwrap_set?

1 Ответ

1 голос
/ 22 января 2020

Самый простой способ сделать это - использовать BTreeSet<T> реализацию IntoIterator, которая позволит вам легко извлекать собственные значения из заданного. за один раз:

fn unwrap_set<T>(s: BTreeSet<T>) -> T {
    let mut it = s.into_iter();
    if let Some(first) = it.next() {
        if let None = it.next() {
            return first;
        }
    }
    panic!("set must have a single value");
}

Если вы хотите косвенно полагаться на IntoIterator, вы также можете использовать обычный l oop, но я не думаю, что он так удобочитаем, так что, вероятно, я бы не стал сделать это:

fn unwrap_set<T>(s: BTreeSet<T>) -> T {
    let mut result = None;
    for item in s {
        // If there is a second value, bail out
        if let Some(_) = result {
            result = None;
            break;
        }
        result = Some(item);
    }
    return result.expect("set must have a single value");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...