请考虑以下函数,这些函数的定义包含对函数的重新定义。
TextDecoded | ID | CreatorID
Helllo, my name is Martin. | 123 | Martin
Yes, I wil do that tomorrow. | 124 | Martin
function foo1()
x = 1
if x != 1
error("Wrong")
end
x = 2
end
function foo()
function p(t) return t + 1 end
if p(1) != 2
error("Wrong")
end
function p(t) return 1 end
end
运行没有错误,但是foo1()
给出了错误foo()
。我认为这可能与Julia不支持一般的重新定义功能有关,但我不确定。为什么会这样?
答案 0 :(得分:3)
我会说这属于一个更普遍的已知问题https://github.com/JuliaLang/julia/issues/15602。
在您的情况下,考虑一个更简单的功能:
function f()
p() = "before"
println(p())
p() = "after"
nothing
end
呼叫f()
将打印"after"
。
对于您而言,您可以通过以下方式检查foo
的情况:
julia> @code_typed foo()
CodeInfo(
4 1 ─ invoke Main.error("Wrong"::String)::Union{} │
│ $(Expr(:unreachable))::Union{} │
└── $(Expr(:unreachable))::Union{} │
) => Union{}
您会看到Julia优化了所有内部逻辑,只调用了error
。
如果您提前一步进行检查,您会看到:
julia> @code_lowered foo()
CodeInfo(
2 1 ─ p = %new(Main.:(#p#7)) │
3 │ %2 = (p)(1) │
│ %3 = %2 != 2 │
└── goto #3 if not %3 │
4 2 ─ (Main.error)("Wrong") │
6 3 ─ return p │
)
您看到的第一行p
仅分配了一次。实际上使用了第二个定义(在这里看不到,但是可以在上面看到)。
要解决您的问题,请使用如下匿名函数:
function foo2()
p = t -> t + 1
if p(1) != 2
error("Wrong")
end
p = t -> 1
end
,一切将按预期工作。这种方法的局限性在于您不会在名称p
上获得多次派发(它绑定到一个具体的匿名函数,但是我想您的示例中不需要多次派发)。