朱利亚的类型稳定的do-blocks

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)并仍然获得类型稳定的结果?

Bog*_*ski 5

它可以移动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在编译时是已知的。