如何将函数标记为`@deprecate`d?

Ado*_*uka 7 deprecated julia

(问题是指 Julia 版本 v1.5)

我试图了解@deprecate宏在 Julia 中的工作原理。该文档是不幸的是没有明确对我说:

@deprecate old new [ex=true]

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

警告:从 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)
Run Code Online (Sandbox Code Playgroud)

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

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

ffe*_*tte 8

想象一下,您将此方法作为版本 1 中库的公共 API 的一部分:

# v1.0.0
mult3(x::Int) = 3x
Run Code Online (Sandbox Code Playgroud)

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

# v2.0.0
mult(x, y) = x * y
Run Code Online (Sandbox Code Playgroud)

版本 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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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


或者,正如评论中提到的,您可能希望保留旧的实现,只需在用户调用它时警告用户。为此,您可以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
Run Code Online (Sandbox Code Playgroud)

--depwarn=yes已在 Julia 的命令行中提供时,会产生与以下相同类型的警告@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
Run Code Online (Sandbox Code Playgroud)

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

julia> Base.depwarn("Foo is deprecated", :foo, force=true)
? Warning: Foo is deprecated
?   caller = ip:0x0
? @ Core :-1
Run Code Online (Sandbox Code Playgroud)

  • 谢谢您的回答。这解释了“@deprecate”背后的想法。我认为当每个人开始抱怨每个版本的所有功能都被重命名时,警告默认被禁用。另一方面,*我如何实现我想要的?(不要替换该方法,甚至可能允许不指定替换,始终显示警告并包含在帮助文本中)*。答案是标准库中不存在这样的功能吗? (2认同)
  • @AdomasBaliuka,我想你要问的是,你如何保留旧的实现?您还可以将其保留在适当的位置,并在方法主体内使用“Base.depwarn”来引导用户进行替换。有关一些示例,请参阅 https://github.com/JuliaImages/Images.jl/blob/de7d11fab7937efaa461874f2fa957dc0a31e602/src/deprecations.jl。 (2认同)
  • 还值得注意的是,即将进入 alpha 版本的 Julia 1.6 具有“force”关键字参数,可确保用户即使没有要求也能看到警告。 (2认同)