为什么在本地禁用有关部分应用程序的警告似乎不起作用

Why locally disabling warning about partial application does not seem to work

在 OCaml 4.08 中,默认发出有关部分应用程序的新警告,如:

let _ = (Format.printf "side-effect!@."; List.iter (fun () -> ()))
2 |   (Format.printf "side-effect!@."; List.iter (fun () -> ()))
                                       ^^^^^^^^^^^^^^^^^^^^^^^^
Warning 5: this function application is partial,
maybe some arguments are missing.

尝试通过在各处添加注释来在本地禁用它似乎没有用:

let[@warning "-5"] _ [@warning "-5"] =
  (Format.printf "side-effect!@."; List.iter (fun () -> ()))[@@warning "-5"]

唯一可行的方法是将 [@@@warning "-5"] 技术用作 。但是,那个问题提到

Local disabling of warnings with [@warning "…"] and [@@warning "…"]is not well supported for OCaml versions anterior to 4.06.0

在这种情况下,对于 OCaml 4.08,要在本地禁用此类警告的语法应该是什么?

Edit:按照 glennsl 的建议,将 let _ = ... 替换为 ignore (...) 确实提供了替代方案(在 [=15 之后添加 [@@warning "-5"] =] 似乎有效),但它不太统一,因为顶级声明不能用这种方式替换,尽管它们可以安全地用 [@@@warning "-5"]/[@@@warning "+5"]1 包围。尽管如此,它并没有解释为什么我的第一次尝试没有奏效:它是写错了,是设计使然,还是可能是疏忽?

1 这个'hack'也有可能改变之前状态的缺点;例如,如果先前已在全局级别禁用警告 5,这将无意中重新启用它。

我会说以下引自精美手册(第 8.13.1 节)的内容表明答案是 "by (absence of) design":

Note that it is not well-defined which scope is used for a specific warning. This is implementation dependant and can change between versions.

现在,如果我们试图解释为什么您试图使警告静音的尝试没有奏效,我们可以检查警告 5 是关于什么的:

expression whose result has function type and is ignored.

因此,当我们在特定上下文中有函数表达式 e 时,会发出警告。在 ignore 的情况下,上下文只是一个应用程序,即一个包含表达式,我们可以要求忘记警告 5 的范围大致应该是 ignore 表达式本身(及其包含表达式和项目)。

现在,对于 let _ = ...,事情就不那么明确了:e 在绑定到包罗万象的模式 _ 时会被忽略。有人可能会争辩说,将 [@@ warning "-5"] 放在 let-binding 的末尾应该涵盖整个定义,但如上所述,编译器完全可以自由地不同意这种解释。

然而,这提供了一个完全不需要禁用警告 5 的替代解决方案:只需将表达式绑定到一个变量(当然,以 _ 开头以避免警告 26):

let _i_swear_to_hb_curry_i_know_what_i_m_doing =
  Format.printf "side-effect!@."; List.iter (fun () -> ());;

不触发任何警告:通过绑定到这样的变量,表达式可能仍然感觉有点被忽略,但它不能抱怨它被主动忽略。