我正在尝试从JSON.jl模块扩展一个方法,特别是我这样做(扩展'JSON.lower',如文档所示,允许序列化), 一般来说 - 我问的是当前Julia“最佳实践”是什么,用于从另一个模块扩展方法 - 特别是 - 如果这是一个方法来改变模块的某些策略(如本例中{{1 }})。
实际上有一种方法可以保证导入的模块将使用更新的方法,除了修补它吗?
让我们展示期望和险恶的行为:
JSON.jl
module TestProgram
using JSON
import JSON.lower # not sure whether this is needed
JSON.print(Set([1,2,1]))
## output:
## {"dict":{"2":null,"1":null}}
## not the output I want or expect
## in this case might be a good idea to patch JSON.jl and pull request
## and "JSON.print" - is now compiled with this default behaviour
JSON.lower{T}(v::Set{T}) = collect(v) # overloading 'JSON.lower'
println(json(Set([1,2,1])))
## output:
## [2,1]
JSON.print(Set([1,2,1]))
## output still:
## {"dict":{"2":null,"1":null}}
end # module
- 那么这个方法已经编译好了,并且不会使用我的'JSON.lower'扩展json(v::Set{T})
调用的行为符合预期,而json()
表现不同(仅通过某些运行流程中的更改)那么 - 确保这一点的最佳做法是什么?
[目前使用Julia 0.4.6和0.5.0测试此行为]
答案 0 :(得分:3)
是的,您对Julia 0.5及之前的分析是正确的。许多开发人员都清楚地知道这个问题的编号(#265)。为即将推出的0.6版本进行了大量工作。 Julia现在跟踪每个函数的调用者并根据需要重新编译它们。
一般来说,这里最好的建议是直接修补库并推动你的改变。这在0.5和0.6都是如此,即使运行时正确性修复也是如此。建议您不要使用自己未定义的类型扩展导入的函数,因为它会改变所有依赖于它的其他包的行为。这已经被俗称为“类型盗版”,因为你为了自己的目的而扼杀了这种方法 - 这些目的可能不适合其他来电者。
作为一种临时解决方法,您可以尝试将定义添加到~/.juliarc.jl
file,这将在启动时执行,并且在编译任何其他方法之前更有可能被定义。但是,即使这不是防弹,因为软件包可以使用预编译来加速其使用。