Как это можно было бы переписать менее императивно в Rust

#functional-programming #rust

#функциональное программирование #Ржавчина

Вопрос:

 fn get_variable_info (route_path: amp;str) -> HashMap<String, uint> {

    let mut map = HashMap::new();
    let mut i = 0;
    for matched in REGEX_VAR_SEQ.captures_iter(route_path) {
        map.insert(matched.at(1).to_string(), i);
        i = i   1;
    }

    map
}
  

У меня есть эта функция, которая принимает a amp;str и перебирает Iterator захваты для создания a HashMap<String, uint> . Мне не нравится императивный стиль этого, и мне интересно, можно ли это переписать более функциональным способом в Rust?

В псевдокоде что-то подобное было бы больше того, что мне нужно.

 let mut i = 0;
REGEX_VAR_SEQ
    .captures_iter(route_path)
    .map(| matched | {
        KeyValuePair{
           key: matched.at(1).to_string(),
           value: i
        }
        i = i   1;
        KeyValuePair
    })
    .toHashMap()
  

Ну, это все еще не идеально, потому что мне не нравится i переменная, но моей первой целью было бы избавиться от императивного цикла 🙂

Ответ №1:

Вы довольно близки! Ваш KeyValuePair и toHashMap на самом деле Iterator.collect , который работает над FromIterator признаком, который HashMap реализует для (K, V) пар.

Таким образом, это что-то вроде [(k, v), (k, v), (k, v)].move_iter().collect::<HashMap<K, V>>() .

Для i части есть Iterator.enumerate , которая превращается [a, b, c] в [(0, a), (1, b), (2, c)] .

Итак, это конечный результат:

 REGEX_VAR_SEQ.captures_iter(route_path)
             .enumerate()
             .map(|(i, matched)| (matched.at(1).to_string(), i))
             .collect()
  

(Вы можете либо оставить HashMap<String, int> вывод, если это возможно (например, тип возвращаемого метода), либо указать его при collect вызове, .collect::<HashMap<_, _>>() .)

Комментарии:

1. потрясающе! Большое спасибо. Вероятно, я должен назвать вас участником моего проекта Floor 😉 github.com/cburgdorf/Floor

2. Спасибо за дополнительную информацию! Что это за функция, которая позволяет мне просто писать .collect::<HashMap<_, _>>() вместо .collect::<HashMap<String, uint>>() ? Оба будут работать просто отлично. Это просто еще одна форма вывода типа?

3. @Christoph, да, это вывод локального типа. Насколько я знаю, это довольно недавняя функция Rust.

4. @VladimirMatveev: Я не знаю, что это недавно введенная функция, хотя я узнал об этом только за последние пару месяцев.

5. @ChrisMorgan, вот его запрос на извлечение: github.com/mozilla/rust/pull/12764 . Он был представлен в середине марта. И на самом деле это называется «подсказка частичного типа».