for i in Office.query.all():
print(i.next_vis)
此编译没有警告。当然调用它会产生一个InexactError:Int64(0.5)。问题:您可以强制执行编译时检查吗?
答案 0 :(得分:2)
从这个意义上讲,茱莉亚是一种动态的语言。因此,不,似乎您无法在不先运行函数的情况下检测出赋值的结果是否会导致此类错误,因为这种类型检查是在运行时完成的。
我不确定自己是什么,因此我将该函数包装在模块中,以在不运行该函数的情况下强制(预)编译,结果是未引发任何错误,这证实了这一想法。 (如果您想了解我的意思,请参见here。
已经这么说了,回答您问题的精神:有没有办法避免这种晦涩的运行时错误以意想不到的方式蔓延?
是的。考虑以下两个几乎等效的功能:
function fun1(x ); y::Int = x; return y; end;
function fun2(x::Int); y::Int = x; return y; end;
fun1(0.5) # ERROR: InexactError: Int64(0.5)
fun2(0.5) # ERROR: MethodError: no method matching fun2(::Float64)
您可能认为,很重要,我们将一个错误换成另一个。但这种情况并非如此。在第一种情况下,直到函数中使用输入之前,您都不知道输入会导致问题。而在第二种情况下,您可以在调用函数时有效地执行类型检查。
这是利用Julia优雅的类型检查系统进行“按合同”编程的简单示例。有关详细信息,请参见Design By Contract。
因此,您的问题的答案是,是的,如果您重新考虑设计并遵循良好的编程习惯,以便尽早发现此类错误,则可以避免在错误的场景中稍后再发生此类错误。难以修复或检测。
Julia手册提供了一个style guide,它也可能有帮助(我上面给出的示例就在顶部!)。
答案 1 :(得分:1)
值得仔细考虑一下Julia中真正的“编译时间”,因为这可能与您的想法无关。
定义函数时:
julia> function somefun()
x::Int = 1
x = 0.5
end
somefun (generic function with 1 method)
您不是对其进行编译。实际上,Julia在您调用它之前不会编译它。与典型的JIT或AOT设计相比,Julia的编译器可以被认为是准时的。
现在,当您调用该函数时,它将对其进行编译,然后运行它会引发错误。您可以在首次调用该函数时看到这种编译-它在生成和缓存专用代码时会花费更多的时间和内存:
julia> @time try somefun() catch end
0.005828 seconds (6.76 k allocations: 400.791 KiB)
julia> @time try somefun() catch end
0.000107 seconds (6 allocations: 208 bytes)
因此,也许您可以看到,使用Julia的编译模型,它在编译时是否被捕获并不重要-即使Julia拒绝编译(和缓存)代码,其行为与您的行为完全一样目前看到的。仍然允许您首先定义该函数,并且仍然仅在调用该函数时抛出错误。
您要问的问题是Julia是否(或应该)在函数定义时捕获此错误。然后问题真的是-定义总是导致错误的方法是否可以? a function like error
itself呢?在Julia中,定义一种无条件的错误(如此类错误)是完全可以的,并且这样做有充分的理由。
现在,如果有能力检测到此方法始终无条件错误的话,有几种方法可以查询朱莉娅:
julia> @code_typed somefun()
CodeInfo(
1 ─ invoke Base.convert(Main.Int::Type{Int64}, 0.5::Float64)::Union{}
└── $(Expr(:unreachable))::Union{}
) => Union{}
这是Julia编译过程中的第一步,在这种情况下,它可以看到convert(Int, 0.5)
以外的所有内容都是unreachable
—也就是说,它出错了。此外,它知道由于该函数将永远不会返回,因此它的返回类型为Union{}
(也就是说,永远都不可能返回类型!),因此您可以要求Julia使用例如{ {1}}宏作为测试套件的一部分。