Ale*_*207 4 julia type-stability
我想从带有do-block的文件中读取数据。使用do块非常重要,因为即使在读取文件期间发生错误,我也必须确保正确关闭文件。文件中的数据应转换为作为参数提供的类型。我真正的用例是使用NetCDF文件,但是我可以重现纯文本文件的类型稳定性问题。
假设有一个file.txt包含content 的文件123,可以使用以下文件创建:
write("file.txt","123")
Run Code Online (Sandbox Code Playgroud)
当我按如下所示加载没有do-block的文件时,结果是类型稳定的:
function loadfile1(T)
f = open("file.txt")
data = parse(T,readline(f))
close(f)
return data
end
Run Code Online (Sandbox Code Playgroud)
@code_warntype正确推断我得到Float32的结果是:
@code_warntype loadfile1(Float32)
Body::Float32
[...]
Run Code Online (Sandbox Code Playgroud)
但是,以下变体:
function loadfile2(T)
f = open("file.txt") do f
return parse(T,readline(f))
end
end
Run Code Online (Sandbox Code Playgroud)
产生类型不稳定的代码:
@code_warntype loadfile2(Float32)
Body::Any
9 1 ? %1 = %new(getfield(Main, Symbol("##842#843")){DataType}, T)::getfield(Main, Symbol("##842#843")){DataType} ?
? %2 = Main.open::Core.Compiler.Const(open, false) ?
? %3 = invoke Base.:(#open#294)($(QuoteNode(Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}()))::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, %2::Function, %1::getfield(Main, Symbol("##842#843")){DataType}, "file.txt"::String)::Any
??? return %3
Run Code Online (Sandbox Code Playgroud)
如何修改函数loadfile2(带有do-block)并仍然获得类型稳定的结果?
它可以移动T到签名中的类型规范:
function loadfile2(::Type{T}) where T
f = open("file.txt") do f
return parse(T,readline(f))
end
end
Run Code Online (Sandbox Code Playgroud)
这种方式T在编译时是已知的。