Getting types right with functional programming


#1

Hi, I want to process some records in an iterable, and wanted to try and do it in as functional style as possible:

using BioSequences
stream = open("tables3PITGs.fasta", "r")
reader = FASTA.Reader(stream)
# Set up reader iterable.

function group_records(reader::FASTA.Reader)
    seqs = Dict{String, Vector{FASTA.Record}}()
    
    function group_record(rec::FASTA.Record)
        pitg = get_pitg(rec)
        v = get!(seqs, pitg, Vector{FASTA.Record}())
        push!(v, rec)
    end
    
    foreach(group_record, reader)
end

code_warntype(group_records, (FASTA.Reader,))
Variables:
  #self#::#group_records
  reader::BioSequences.FASTA.Reader
  seqs::Dict{String,Array{BioSequences.FASTA.Record,1}}
  group_record::#group_record#2{Dict{String,Array{BioSequences.FASTA.Record,1}}}
  n::Int64

Body:
  begin 
      $(Expr(:inbounds, false))
      # meta: location dict.jl Type 104
      SSAValue(5) = $(Expr(:invoke, MethodInstance for fill!(::Array{UInt8,1}, ::UInt8), :(Base.fill!), :($(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{UInt8,1}, svec(Any, Int64), Array{UInt8,1}, 0, 16, 0))), :((Base.checked_trunc_uint)(UInt8, 0)::UInt8)))
      SSAValue(3) = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{String,1}, svec(Any, Int64), Array{String,1}, 0, 16, 0))
      SSAValue(1) = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Array{BioSequences.FASTA.Record,1},1}, svec(Any, Int64), Array{Array{BioSequences.FASTA.Record,1},1}, 0, 16, 0))
      # meta: pop location
      $(Expr(:inbounds, :pop))
      seqs::Dict{String,Array{BioSequences.FASTA.Record,1}} = $(Expr(:new, Dict{String,Array{BioSequences.FASTA.Record,1}}, SSAValue(5), SSAValue(3), SSAValue(1), 0, 0, :((Base.bitcast)(UInt64, (Base.check_top_bit)(0)::Int64)), 1, 0)) # line 4:
      group_record::#group_record#2{Dict{String,Array{BioSequences.FASTA.Record,1}}} = $(Expr(:new, #group_record#2{Dict{String,Array{BioSequences.FASTA.Record,1}}}, :(seqs))) # line 10:
      return $(Expr(:invoke, MethodInstance for foreach(::#group_record#2{Dict{String,Array{BioSequences.FASTA.Record,1}}}, ::BioSequences.FASTA.Reader), :(Main.foreach), :(group_record), :(reader)))
  end::Void

Is there a way I can check the types are predicted properly for the body of the function that gets created inside the outer function? I see I get this “group_record::#group_record#2{Dict{String,Array{BioSequences.FASTA.Record,1}}}” which tells me the type of the captured seqs variable I suppose, but I wondered if there was a way I can check v and the other variable, as I don’t see it in my code_warntype output.

Thanks.