【问题标题】:How to mark functions as `@deprecate`d?如何将函数标记为`@deprecate`d?
【发布时间】:2020-11-05 18:34:51
【问题描述】:

(问题指 Julia 版本 v1.5)

我试图了解 @deprecate 宏在 Julia 中的工作原理。 documentation 不幸的是我不清楚:

@deprecate old new [ex=true]

弃用旧方法并指定替换调用新方法。防止 @deprecate 通过将 ex 设置为 false 来导出旧的。 @弃用 定义了一个与旧方法具有相同签名的新方法。

警告: 从 Julia 1.5 开始,@deprecate 定义的函数在没有设置 --depwarn=yes 标志的情况下运行 julia 时不会打印警告,因为 --depwarn 选项的默认值为 no。警告是从 Pkg.test() 运行的测试中打印出来的。

例子

julia> @deprecate old(x) new(x)

旧(具有 1 种方法的通用函数)

julia> @deprecate old(x) new(x)

假旧(具有 1 种方法的通用函数)

那我该怎么办?

function old(x::Int)
    print("Old behavior")
end

function new(x::Int)
    print("New behavior")
end

# Adding true/false argument doesn't change my observations.
@deprecate old(x) new(x)  # false 


old(3)
# Prints "Old behaviour". No warning. 
# Also: The deprecation is not mentioned in the help (julia>? old)

这个@deprecate 宏的目的似乎是替换函数?我觉得这违反直觉。如何将功能标记为已弃用(即用户应该收到警告和提示可以使用什么作为替代品,也应该在文档中)?

编辑:我注意到我的错误。签名(在我的情况下为::Int)必须相同才能正常工作。但是,如何获得警告?

【问题讨论】:

    标签: julia deprecated


    【解决方案1】:

    假设您在版本 1 中将此方法作为库的公共 API 的一部分:

    # v1.0.0
    mult3(x::Int) = 3x
    

    在版本 2 中,您希望停止支持 mult3(这是一项重大更改)。但是使用更通用的方法仍然可以使用相同的功能:

    # v2.0.0
    mult(x, y) = x * y
    

    版本 1 的用户习惯使用mult3,这意味着他们的代码在更新到 v2 时会中断。因此,您可能希望在 v1.x 系列中发布一个中间版本,其中 mult3 存在但已被弃用并根据 mult 实现:

    # v1.1 - transition
    
    # This is the new API for v2
    mult(x, y) = x*y
    
    # The old API is still supported, but deprecated and implemented using the old one
    @deprecate mult3(x::Int) mult(3, x)
    
    # The above is more or less equivalent to defining
    # function mult3(x::Int)
    #    # print an error message is `--depwarn` has been set
    #    return mult(3, x)
    # end
    

    v1 API 在 v1.x 后期版本中没有损坏,但调用已弃用方法的用户会看到以下类型的消息,以帮助他们过渡到较新的 v2 API:

    julia> mult3(14)
    ┌ Warning: `mult3(x::Int)` is deprecated, use `mult(3, x)` instead.
    │   caller = top-level scope at REPL[3]:1
    └ @ Core REPL[3]:1
    42
    

    (但从 Julia 1.5 开始,只有在 Julia 的命令行中提供了 --depwarn=yes 或出现在 Pkg.test() 运行的测试套件中时才会显示警告)


    或者,正如 cmets 中所述,您可能希望保留旧的实现,只是在用户调用它时警告用户。为此,您可以直接使用Base.depwarn

    # v1.1 - transition
    
    # This is the new API for v2
    mult(x, y) = x*y
    
    # The old API is still supported, but deprecated
    # It is implemented by itself:
    function mult3(x)
        Base.depwarn("`mult3(x)` is deprecated, use `mult(3,x)` instead.", :mult3)
        return 3x
    end
    

    当在 Julia 的命令行中提供了 --depwarn=yes 时,这会产生与 @deprecate 相同的警告:

    julia> mult3(14)
    ┌ Warning: `mult3(x)` is deprecated, use `mult(3,x)` instead.
    │   caller = top-level scope at REPL[4]:1
    └ @ Core REPL[4]:1
    42
    

    从 Julia 1.6 开始,depwarn 将接受关键字参数以强制发出警告,即使用户没有使用 --depwarn=yes 请求它们:

    julia> Base.depwarn("Foo is deprecated", :foo, force=true)
    ┌ Warning: Foo is deprecated
    │   caller = ip:0x0
    └ @ Core :-1
    

    【讨论】:

    • 感谢您的回答。这解释了@deprecate 背后的想法。当每个人开始抱怨所有功能都被重命名为每个版本时,我认为默认情况下警告是禁用的。另一方面,我如何实现我想要的? (不要替换该方法,甚至可能不允许指定替换,始终显示警告并包含在帮助文本中)。答案是标准库中不存在这样的功能吗?
    • 我不确定我是否理解您想要实现的目标。 “总是显示警告”-> 如果您的意思是忽略--depwarn,那么我猜@deprecate 不是您想要的,我不确定您是否会找到任何不符合此特定含义的替代方案命令行选项。至于帮助文本,我想可能有人认为@deprecate 可以接受文档字符串,以便可以记录不推荐使用的函数。你也许可以提出一个关于这个的问题。或者,如果需要,可以使用 @doc 手动记录已弃用的函数。
    • @AdomasBaliuka,我想你要问的是,你如何离开旧的实现?您也可以保留它并在方法主体内使用Base.depwarn 来引导用户进行替换。有关示例,请参阅 github.com/JuliaImages/Images.jl/blob/…
    • 感谢@tholy,我编辑了我的答案以反映您的评论。
    • 另外值得注意的是,即将进入 Alpha 版的 Julia 1.6 具有一个 force 关键字参数,可确保用户即使没有要求也会看到警告。
    猜你喜欢
    • 1970-01-01
    • 2015-08-25
    • 2017-10-21
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    • 2020-02-09
    相关资源
    最近更新 更多