在Julia函数中重新定义函数会产生奇怪的行为
考虑以下函数,其定义包含函数的重新定义在Julia函数中重新定义函数会产生奇怪的行为,julia,Julia,考虑以下函数,其定义包含函数的重新定义 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()运行时没
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不支持重新定义函数有关,但我不确定。为什么会发生这种情况?我想说,这属于一个更普遍的已知问题
在你的例子中考虑一个更简单的函数:
function f()
p() = "before"
println(p())
p() = "after"
nothing
end
调用f()
将在“
之后打印”
在您的情况下,您可以通过以下方式检查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
所有这些都将按预期工作。这种方法的局限性在于,在namep
(它绑定到一个具体的匿名函数,但我猜在您的示例中不需要多个分派)上没有得到多个分派