Почему использование return в качестве последнего оператора функции считается неудачным?
Я читал документацию Rust и натолкнулся на следующий пример и выражение
Использование возврата в качестве последней строки функции работает, но считается плохим стилем:
fn foo(x: i32) -> i32 {
if x < 5 { return x; }
return x + 1;
}
Я знаю, что мог бы написать выше
fn foo(x: i32) -> i32 {
if x < 5 { return x; }
x + 1
}
но я более соблазнился написать первое, поскольку это более интуитивно понятно. Я понимаю, что возвращаемое значение функции должно использоваться в качестве выражения, чтобы позднее работало, но тогда почему бы не поощрять первое?
Ответы
Ответ 1
Это просто.
У конвенций не должно быть особых оснований, они просто должны быть общепринятыми конвенциями. Как это бывает, у этого человека есть относительно веская причина - его короче, поскольку у вас нет return
;
, Вы можете подумать, что return x + 1;
более интуитивно понятен, но я не согласен сильно - это действительно решёт, и я чувствую настоятельную необходимость исправить это. Я говорю об этом как о том, кто до начала использования Rust никогда раньше не использовал язык, ориентированный на выражение. При написании Python, return x + 1
в этом месте, посмотрите правильно, при написании Rust это выглядит неправильно.
Теперь, как это бывает, этот код, вероятно, должен быть написан таким образом:
fn foo(x: i32) -> i32 {
if x < 5 {
x
} else {
x + 1
}
}
Это подчеркивает ориентацию выражения языка.
Ответ 2
Скопировано из reddit: почему синтаксис операторов return явный?
Ответ от @pcwalton
Явный возврат действительно раздражает в замыканиях. Например, до появления функций стрелок ES6 в JavaScript была большая проблема
myArray.map(function(x) { return x * 2; })
является многословным, даже без ключевого слова function
. Если у вас есть неявные возвраты где-то на вашем языке, вы также можете иметь их везде для согласованности. Тот факт, что он делает код менее многословным, является лишь дополнительным бонусом.
и из @mozilla_kmc
Rust - это язык, ориентированный на выражения. Блок имеет форму
{
stmt;
stmt;
...
stmt;
expr
}
Операторы являются (в основном) выражениями или привязками let
, а конечное выражение неявно ()
если не указано. Значение всего блока является значением этого последнего выражения.
Это не только для функций. Ты можешь написать
let foo = if x { y } else { z };
так что if
также занимает место оператора C ?:
Каждый вид блока работает одинаково:
let result = unsafe {
let y = mem::transmute(x);
y.frob()
};
Таким образом, неявный возврат в конце функции является естественным следствием синтаксиса, ориентированного на выражения Rust. Улучшенная эргономика просто приятный бонус :)
Головоломка: return x
само по себе является выражением - какова его ценность?
Ответ:
Это тип блока ()
.
Ответ 3
Clippy ворс дает следующее рациональны для needless_return
ворса:
Удаление возврата и точки с запятой сделает код более ржавым.
Это, вероятно, так же хорошо, как и объективное обоснование, которое мы когда-либо получим.
Что касается интуиции; Я чувствую, что он сформирован нашими индивидуальными переживаниями и поэтому субъективен. Хотя Rust не является языком самого функционального программирования, многие люди, использующие и развивающие его, похоже, имеют сильный опыт в таких функциональных языках программирования, как Haskell, которые полностью основаны на выражениях. Влияние может сильно ощущаться во многих областях Rust (например, обработка ошибок). Таким образом, для них (и, честно говоря, я включил себя) использование выражения вместо выражения кажется более элегантным.