我正在阅读Rust文档,并遇到了以下示例和语句
使用return作为函数的最后一行是可行的,但被认为是不好的风格:
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
}
但我更倾向于写前者,因为它更直观,我确实理解函数返回值应该作为表达式使用,所以后者可以工作,但为什么不鼓励前者呢?
6条答案
按热度按时间svmlkihl1#
复制自reddit:Why isn't the syntax of return statements explicit?
来自@pcwalton的回答
闭包中的显式返回确实很烦人,例如,在ES6的箭头函数引入之前,这是JavaScript中的一大难题
即使没有
function
关键字,也是多余的。一旦你的语言中有了隐式返回,为了一致性,你也可以到处都有它们。它使代码更简洁的事实只是一个额外的好处。以及来自@mozilla_kmc
Rust是一种面向表达式的语言。块的形式为
语句基本上是表达式或
let
绑定,如果未指定,则尾随表达式隐式为()
,整个块的值就是最后一个表达式的值。这不仅仅是函数。你可以写
所以
if
也代替了C的?:
操作符,每种块的工作方式都是一样的:因此,函数末尾的隐式返回是Rust面向表达式语法的自然结果。改进的人体工程学只是一个不错的奖励:)
谜题:
return x
本身是一个表达式--它的值是什么?答案(@ dubousjim建议):
它是一个永不类型
!
。rbl8hiat2#
它只是 * 是 *。
约定不需要有特别好的理由,它们只需要是普遍接受的约定。碰巧的是,这个约定确实有一个相对好的理由--它比较短,因为你没有
return
和;
。你可能认为return x + 1;
更直观,但我强烈反对--它真的很烦人,我觉得迫切需要修正它。我说这句话是作为一个谁,在开始使用Rust之前,从来没有使用过面向表达式的语言。在编写Python时,return x + 1
在那个地方看起来是正确的,而在编写Rust时,它看起来是错误的。现在碰巧的是,该代码可能应该这样编写:
这强调了语言的表达取向。
fcipmucu3#
clippy lint为
needless_return
lint提供了以下理由:删除回车和分号会使代码更加生疏。
这可能是我们所能得到的最好的客观理由。
就直觉而言我觉得它是由我们的个人经验塑造的,因此是主观的。虽然Rust本身不是函数式编程语言,但许多使用和开发它的人似乎都有很强的函数式编程语言背景,如Haskell,它完全基于表达式。Rust的许多领域都能强烈地感受到这种影响(eidogg.错误处理)。所以对他们来说(老实说,包括我自己)使用表达式而不是语句似乎更优雅。
htrmnn0y4#
在OCaml中,您的示例:
与您在Rust中修改的示例进行比较:
OCaml中的闭包示例:
与Rust闭合比较:
所以Rust似乎采用了函数式编程风格。
return
会很烦人,而且意义从代码中已经很清楚了。函数式编程语言实际上并不依赖于经典的"赋值给变量,操作变量,返回变量"范式,而是使用"赋值给变量,通过几个不同的函数传输变量,最终结果是输出"范式(甚至赋值给变量也是可选的:向上搜索"无点编程")。
Rust中的"经典"范例:
与OCaml中的函数式编程范例:
如果我们在OCaml例子中需要一个
return
,我们需要把它放在最前面,这在很大程度上是没有意义的,因为我们已经知道它将返回什么。示例:
Rust的
if
语句的求值结果是一个表达式,这与C("Classic")不同,与OCaml(Functional)类似。93ze6v8z5#
与流行的OOP语言不同,Rust是EOP,其中EOP = * 面向表达式 * 编程
当以
;
结尾时,那是一个表达式,因此block是一个表达式。相反,当没有
;
而结束时,这是一个语句。我们写了一个简单的加1函数
我们去掉
;
无法编译,因为函数的类型 tuple 与 i32 不匹配
我们修改函数,
有人说这是隐式return,但我把 -〉 当作 return。
此外,我们可以通过添加 return 强制type进入
i32
。现在我们做一个选择
就不良风格而言,这主要是在这些条件流中,尤其是当它变得越来越大时...
另一种情况是“三进制分配”,
在 bool 中更有意义,
总之,我们最好不要使用 return,而是要明确函数的类型
rhfm7lfc6#
我对下面的解决方案非常满意:配置Clippy不为不必要的返回发出警告,并在缺少最终返回时警告我。
为此,只需在根文件的顶部添加:“”main.rs“”或"“lib.rs”“执行以下剪辑lint:
对我们来说,额外的好处是,在一些闭包中,它可以防止rustfmt删除大括号。在我的团队中,一致认为在闭包中使用大括号会更好,从而在函数参数和代码之间增加额外的分隔。在下面的示例中:
在添加lint之前,rustfm会将get_in方法转换为:
现在,我们得到:
这当然是一个品味问题,但我们在我的团队中一致倾向于后者,特别是因为存在或不存在一个分号(很难看出)不是类型不匹配的原因。因此,我们对该解决方案非常满意(即使有2个return语句增加的冗长)。最终,我们需要另一个lint或rustfm选项来处理我们在大括号方面的特殊口味...