Option::map
потребляет внутреннее значение (если оно есть).Таким образом, в коде q.map(|x| x.as_ref())
замыкание принимает значение x
.Вы можете проверить это, заметив, что q.map(|x: &Q| x.as_ref())
выдает ошибку типа, а q.map(|x: Q| x.as_ref())
- нет (все равно выдает ошибку времени жизни).Это означает, что когда вы вызываете x.as_ref()
, создается новая ссылка на x, не связанная с какой-либо внешней ссылкой.Это означает, что ссылка действительна только внутри замыкания, но вы хотите использовать ее в оставшейся части extend1
.
. Вместо этого вы должны заимствовать q
, действительный доконец extend1
.Этот заем q
можно превратить в заимствование его содержимого (если оно есть), используя Option::as_ref()
для преобразования &Option<Q>
в Option<&Q>
(простое использование q.as_ref()
создаст заем q
, который вам нужен).Тогда, когда вы используете карту, закрытие займет &Q
, а не Q
.Срок действия ссылки будет таким же, как и внешний заем q
, поэтому он будет действовать до конца extend1
(при необходимости).
const DEFAULT: &str = "lib";
use std::path::{Path, PathBuf};
fn extend1<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Option<Q>) -> PathBuf {
let q: &Path = q.as_ref().map(|x| x.as_ref()).unwrap_or(DEFAULT.as_ref());
p.as_ref().join(q)
}
(детская площадка)
Поскольку аргументы вашей функции используются только по ссылке, вы можете использовать их только по ссылке.Это так же просто, как добавить амперсанд к каждому аргументу.
const DEFAULT: &str = "lib";
use std::path::{Path, PathBuf};
fn extend1<P: AsRef<Path>, Q: AsRef<Path>>(p: &P, q: &Option<Q>) -> PathBuf {
let q: &Path = q.as_ref().map(|x| x.as_ref()).unwrap_or(DEFAULT.as_ref());
p.as_ref().join(q)
}
(площадка)
или
const DEFAULT: &str = "lib";
use std::path::{Path, PathBuf};
fn extend1<P: AsRef<Path>, Q: AsRef<Path>>(p: &P, q: Option<&Q>) -> PathBuf {
let q: &Path = q.map(|x| x.as_ref()).unwrap_or(DEFAULT.as_ref());
p.as_ref().join(q)
}
(детская площадка)
Обратите внимание, что эта последняя версия не должна вызывать q.as_ref()
, так как q
уже имеет тип Option<&Q>
.Эта версия наиболее точно соответствует вашей исходной функции extend
.