This is a conceptual question. Consider the following (extremely
stylized, but self-contained) code

parsefield{T <: Real}(::Type{T}, string) = parse(T, string)

function parserow(schema, strings)
    # keep i for reporting column, currently not used
    [parsefield(T, string) for (i, (T, string)) in enumerate(zip(schema, 
strings))]
end

function parsefile(io, schema)
    line = 1
    while !eof(io)
        strings = split(chomp(readline(io)), ';')
        parserow(schema, strings)
        line += 1 # currently not used, use for error reporting
    end
end

test_file = """
1;2;3
4;5;6
7;8;error
"""

parsefile(IOBuffer(test_file), fill(Int, 3))

This will fail with an error message

ERROR: ArgumentError: invalid base 10 digit 'e' in "error"
 in tryparse_internal(::Type{Int64}, ::SubString{String}, ::Int64, ::Int64, 
::Int64
, ::Bool) at ./parse.jl:88
 in parse(::Type{Int64}, ::SubString{String}) at ./parse.jl:152
 in parsefield(::Type{Int64}, ::SubString{String}) at ./REPL[152]:1
 in (::##5#6)(::Tuple{Int64,Tuple{DataType,SubString{String}}}) at ./<missing>:0
 in collect_to!(::Array{Int64,1}, 
::Base.Generator{Enumerate{Base.Zip2{Array{DataTy
pe,1},Array{SubString{String},1}}},##5#6}, ::Int64, 
::Tuple{Int64,Tuple{Int64,Int64
}}) at ./array.jl:340
 in 
collect(::Base.Generator{Enumerate{Base.Zip2{Array{DataType,1},Array{SubString{
String},1}}},##5#6}) at ./array.jl:308
 in parsefile(::Base.AbstractIOBuffer{Array{UInt8,1}}, ::Array{DataType,1}) at 
./RE
PL[154]:5

Instead, I would like to report something like this:

ERROR: Failed to parse "error" as Int on line 3, column 3.

What's the idiomatic way of doing this in Julia? My problem is that
parsefield fails without knowing line or column (i in parserow). I could
catch and rethrow, constructing an error object gradually. Or I could
pass line and column numbers to parserow and parsefield for error
reporting, but that seems somehow inelegant (I have seen it in code
though).

Best,

Tamas

Reply via email to