F# 中执行绑定的正确样式



在 F# 中,"do"关键字的一个更微妙的用法是能够注释返回单元(又名语句)的表达式。例如,我经常在函数定义中这样做,以明确返回类型是单位,并指示编译器为我键入 checkthis。例如:

let restart agent = do agent.Post Restart

但是,我不确定 F# 社区中对"do"关键字的主要看法是什么。

在此示例中使用"do"关键字的正确方法是什么:

// Annotate each statement
let move source destination =
do copy source destination
do clear source
// Annotate the statements as one block
let move source destination =
do
copy source destination
clear source
// Just annotate the "return" statement
let move source destination =
copy source destination
do clear source
// Perhaps don't annotate at all?
let move source destination =
copy source destination
clear source

我很少看到 F# 代码中用于此目的do(引入unit表达式)。您描述的大多数类型检查已经在没有它的情况下自动执行,以 FS0020 警告的形式提供关于未使用值。

如果你只是写

let move source destination =
copy source destination
clear source

然后会发生以下三件事之一:

  • copyclear都返回unit

    在这种情况下,一切都很好。

  • copy返回单位以外的类型

    在这种情况下,您将收到有关忽略值的 FS0020 警告:

    表达式copy source destination返回当前被忽略的 int。如果您不需要此值,则应使用 ignore 函数显式忽略它,例如ignore (copy source destination)或将结果绑定到名称,例如let result = copy source destination

  • copy返回单位,clear返回unit以外的类型

    在这种情况下,不会有警告,但move将具有与clear相同的类型,并且这种差异将在呼叫站点上表现出来move,在那里您将获得与上述相同的警告。

因此,do用于类型检查目的的效用相当有限:只有在最后一种情况下,它才会有所作为,方法是使警告出现在原始行上,而不是强迫您从move的呼叫站点导航到它(或者可能 - 如果move是其范围内的最后一行 - 从move的呼叫者的呼叫站点, 等等)。这首先很少是一个错误 - 如果clear返回一个值(例如,指示清除是否成功的布尔值),您肯定希望将该信息传播到调用链上!

也就是说,这是一个非常简单的令牌,(IMO)丝毫不会损害可读性,并且可以说是改进了它。考虑到 F# 社区对少数喜欢禁用轻量级语法 (#light "off") 并手动键入分号和end标记的用户没有问题,我无法想象do任何地方引起任何关注。

最新更新