В основном два вопроса:
let x = y
переводится на псевдоанглийский/псевдокод?if let x = y {}
шаг за шагом?Всегда предполагалось, что let объявляет переменную, пока я не встретил if let (код ниже) и не пошел гуглить.
let config_max = Some(3u8);
if let Some(max) = config_max {
println!("The maximum is configured to be {}", max);
} else {
println!("xyz");
}
Потоки StackOverflow объяснили, что let фактически оценивает/проверяет шаблон. Итак, я понял, что пусть только проверяет соответствие шаблона и значения и не объявляет переменную саму по себе:
let y = Some(5);
if let Some(x) = y { doZ(x); }
// 1. let Some(x) = y -- see if pattern Some(x) matches value y, if yes execute next expression
// 2. Some(x) = y -- the next expression, assign value of y to "variable Some(x)"
// if ( 1 and 2 are successful) { execute this }
Но тогда, если let используется только для сопоставления/оценки значения шаблона, то почему он используется в объявлении переменной? Ответ: Потому что он используется НЕ только для сопоставления с образцом, а необходим для объявления переменной.
let y = Some(5);
if let Some(x) = y { doZ(x); }
// if -- if
// let Some(x) = y -- ( if pattern Some(x) matches Some(5), declare variable Some(x) and assign value Some(5) to it )
// doZ(x) -- { execute doZ function and pass x as an argument}
A - Означает ли приведенный выше «перевод», что let Some(x) = Some(5) == let x = 5? Если да, то как это происходит? b - Разве весь смысл типов Option<T> и Enum не в том, чтобы отличаться от необработанных T?
if let x = 5 { doZ(x); } // a
// Warning: x = 5 is irrefutable, consider using just "let" without "if".
5 == Some(5) // b, false
Вышеупомянутая ошибка также опровергает, если if в if let Some(x) = y является обычным if, ищет логическое значение, после чего запускает код внутри "{}". Но let — это оператор, он не возвращает логическое значение или что-то еще, с if или без него. Значит ли это, что if в данном конкретном случае на самом деле не if (которому требуется логическое значение для выполнения кода), а исчерпывающий match? Если да, то почему if, а не какое-то другое/новое ключевое слово?
let
сам по себе тоже выполняет сопоставление с образцом, только только неопровержимые. @кадольфс
Очень хорошее разъяснение, да. Это отлично подходит для таких вещей, как распаковка кортежей.
@cadolphs, так if let нельзя объявить переменную?
@Bookworm: он объявляет переменные как часть процесса распаковки; if let Some(x) = y { ... } в процессе сопоставления с образцом объявляет x, если сопоставление с образцом прошло успешно.
Попробуйте перечитать главу 18 Книги: doc.rust-lang.org/book/ch18-00-patterns.html. Здесь это довольно хорошо объяснено, особенно в 18.1.
let
сам по себе является просто присвоением переменной (возможно, с сопоставлением с образцом, если образец неопровержим).if
сам по себе является ветвлением на основе логического значенияif let
— это не какая-то странная мешанина из let
и if
, а отдельная конструкция:Что делает if let? Он пытается сопоставить значение с шаблоном и при этом привязывает части значения к сравниваемому шаблону. Только если шаблон действительно соответствует успешному совпадению, он затем выполнит код в блоке if let:
let x = 5; // simple variable assignment
let (x, y) = (3, 4); // assignment with pattern matching
if x % 2 == 0 { // only do this code if number is even
println!("x is even");
}
// if let to do pattern-matching and assignment,
// but where the pattern might potentially not match
if let Some(x) = function_that_returns_option() {
println!("The function returned Some(x) with x = {}", x);
}
// if the function had returned None instead, then nothing would have been printed and nothing would have been assigned to that x.
Это просто "принять как есть" или есть какие-то другие варианты использования? Почему это вещь? Почему, например, нет matchLight Some(x) = optionReturn() { println!({x}) }?
@Bookworm: потому что, как правило, полезно свести к минимуму ненужное введение новых ключевых слов, если вы можете избежать их, не создавая чрезмерной сложности. Помимо предложенного вами ключевого слова, if let — это «спичечный свет», который вы предлагаете. let уже выполняет сопоставление с образцом "не может потерпеть неудачу" само по себе (например, распаковка, как показывает cadolphs), if let просто расширяет это до использования "может потерпеть неудачу", когда контролируемый блок выполняется только тогда, когда сопоставление с образцом завершается успешно, так что это на самом деле связано с тем, что if и let уже делают независимо друг от друга.
@ShadowRanger ах хорошо, это ваше объяснение имеет гораздо больше смысла, спасибо!
@cadolphs nit: let сам по себе является просто объявлением переменной, например. let foo; Также, поскольку ваш комментарий охватывает как let, так и if let, может быть полезно охватить let else.
@Bookworm FWIW есть if let RFC, который вы можете прочитать для общего ознакомления, и он ссылается на соответствующие проблемы (в RFC и Rust), где обсуждались предложения.
В Книге говорится, что простое let также является совпадением с образцом: doc.rust-lang.org/book/…
Ваша последняя «ошибка» — это не ошибка, это предупреждение, что if не нужен.