Зачем в rust if expression, возвращающий не unit type, оборачивать в скобки, чтобы оно вело себя как expression и не создавало ошибки компиляции?
В синтаксисе rust все управляющие конструкции типа if, циклы типа for являються выражениями(expressions - expr). То есть они всегда, неявно или явно, что-то возвращают
Так же в rust инструкции (statements) могут быть декларативными и вычислительными (состоящими из expr). В конце каждой инструкции должна быть точка запятой
Из вышеуказанного можно заметить, что конструкцию if нужно завершать ;
, потому что конструкция if это expr. И нет "особой" группы statements, которые могли бы не завершаться ;
, и в которую могли бы включить конструкцию типа if. Я так понимаю в Rust не хотели чтобы if пришлось бы каждый раз глупо заканчивать ;
, поэтому сделали исключение
Но это исключение распространяется не на все if expr, а только на те, которые возвращают unit type (()
). Я думаю это логичное исключение, потому что unit type не может интерпритироваться как часть следующей инструкции, потому что над ним нельзя совершать операции. Так что если if expr возвращает unit type то это гарантированно отдельный statement
Оставшаяся часть if expr, которая возвращает всё остальное, например i32, всё ещё должна заканчиваться ;
. То есть если if expr возвращает i32, то он должен заканчиваться ;
, чтобы считаться отдельной инструкцией. Значит можно сделать вывод, что если не закончить if expr ;
, то компилятор интерпретирует его как часть большей инструкции
Но на практике это совсем не так
Пример:
if true {
1
} else {
1
} + 1;
Здесь могла бы возникнуть неоднозначность в том, что if expr может быть как отдельная инструкция, а может быть как часть другого expr. Но нет, её тут нет, потому что if expr возвращает i32, а значит он может считаться полноценной инструкцией только с ;
в конце. Получаеться никакой неоднозначности нет, if expr тут только как часть другого expr
Тем не менее, это не работает, работает только если обернуть в скобки весь if expression, убрав его с верхнего уровня
(if true {
1
} else {
1
}) + 1;