Я играл с Rust портировал мой движок Score4 AI, основываясь на работе над моей функциональной реализацией в OCaml. Я специально хотел посмотреть, как Rust тарифицируется с кодом функционального стиля.
Конечный результат: он работает, и он очень быстрый - намного быстрее, чем OCaml. Он почти затрагивает скорость C/С++ с императивным стилем - это действительно здорово.
Есть что-то, что меня беспокоит - почему мне нужно два амперсанда в последней строке этого кода?
let moves_and_scores: Vec<_> = moves_and_boards
.iter()
.map(|&(column,board)| (column, score_board(&board)))
.collect();
let target_score = if maximize_or_minimize {
ORANGE_WINS
} else {
YELLOW_WINS
};
if let Some(killer_move) = moves_and_scores.iter()
.find(|& &(_,score)| score==target_score) {
...
Я добавил их, потому что ошибки компилятора "наводили" меня на него; но я пытаюсь понять, почему... Я использовал трюк, упомянутый в другом месте в Stack Overflow, чтобы "спросить" компилятор, чтобы сообщить мне, что это за тип:
let moves_and_scores: Vec<_> = moves_and_boards
.iter()
.map(|&(column,board)| (column, score_board(&board)))
.collect();
let () = moves_and_scores;
... который вызвал эту ошибку:
src/main.rs:108:9: 108:11 error: mismatched types:
expected `collections::vec::Vec<(u32, i32)>`,
found `()`
(expected struct `collections::vec::Vec`,
found ()) [E0308]
src/main.rs:108 let () = moves_and_scores;
... как я и ожидал, moves_and_scores
- это вектор кортежей: Vec<(u32, i32)>
. Но затем, в ближайшей следующей строке, iter()
и find()
заставляют меня использовать отвратительные двойные амперсанды в параметре закрытия:
if let Some(killer_move) = moves_and_scores.iter()
.find(|& &(_,score)| score==target_score) {
Почему закрытие find
требует двух амперсандов? Я мог понять, почему это может понадобиться (передайте кортеж по ссылке, чтобы сэкономить время/пространство), но почему два? Это из-за iter
? То есть, создается iter
создание ссылок, а затем find
ожидает ссылку на каждый вход, поэтому ссылка на ссылку?
Если это так, разве это, возможно, довольно уродливый недостаток дизайна в Rust?
На самом деле я ожидал бы find
и map
, а все остальные функциональные примитивы будут частью самих коллекций. Принуждение к iter()
для выполнения каких-либо функций в функциональном стиле кажется обременительным, и даже более того, если он заставляет этот тип "двойных амперсандов" в каждой возможной функциональной цепочке.
Я надеюсь, что мне не хватает чего-то очевидного - любая помощь/разъяснение наиболее приветствуются.