如何在OCaml中将let绑定标记为弃用?

10

我希望注释一个来自外部库的函数,标记它为废弃以确保在我的项目中不会被使用。假设该库提供了以下模块:

module Lib : sig
  val safe_function : int -> unit
  val unsafe_function : int -> int -> unit
end = struct
  let safe_function _ = ()
  let unsafe_function _ _ = ()
end

我在项目中有一个Util.ml文件,每个文件都会打开它。在这个文件中,我想要做类似于以下的操作:

open Lib

let unsafe_function = Lib.unsafe_function
  [@@deprecated "Use safe_function instead."]

let foo = (fun x -> x)
  [@@deprecated "BBB"]

type t =
  | A [@deprecated]
  | B [@deprecated]
  [@@deprecated]

编译以下的usage.ml文件。
open Util

let _ = unsafe_function 0 0
let _ = foo 0

let _ = A
let f (x : t) = x

会产生以下警告:

$ ocamlc -c -w +3 usage.ml
File "usage.ml", line 6, characters 8-9:
Warning 3: deprecated: A
File "usage.ml", line 7, characters 11-12:
Warning 3: deprecated: Util.t

因此,在let绑定上的deprecated属性不会触发,但是在类型定义和构造函数上会触发,根据属性语法,两者都是支持的。

我找到了这个答案,但它似乎已经过时了,因为:

  1. 它明确说“它“仅适用于值(而不是类型)”,这是不正确的(现在?)如上面的例子所示。
  2. 文档明确说明注释“可以应用于签名或结构体中的大多数项目。”

我删除了我的回答,因为似乎是在传输过程中出现了拼写错误。否则,在我看来它是正确的,但可能是弃用的let绑定必须在不同的编译单元中使用才能触发警告? - glennsl
我将它们移动到不同的文件(util.mlusage.ml)中,但它的行为仍然相同。 - authchir
添加一个包含弃用注释的 util.mli 文件?虽然这并没有完全回答问题,但在这里似乎是正确的做法。 - gsg
2个回答

8

我不确定确切的语法是什么(您的建议听起来正确,与解析器代码相对应,因此可能是编译器中的错误),但您可以滥用模块系统来做到这一点:

include (Lib : sig
    val unsafe_function : int -> int -> unit
    [@@ocaml.deprecated "Use safe_function instead."]
  end)

let _ = unsafe_function 0 0 (* warning here *)

0

刚遇到了同样的问题。OCaml 属性语法有点棘手。 这个方法可行:

let unsafe_function [@deprecated "Use safe_function instead."] = 
  Lib.unsafe_function

(注意单个@


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接