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