Tamas,
running this
typealias AkoString Union{String, SubString{String}}
function parsefield{T <: Real, S <: AkoString}(::Type{T}, str::S)
result = T(0)
try
result = parse(T, str)
catch ArgumentError
errormsg = string("Failed to parse \"",str,"\" as type ", T)
throw(ErrorException(errormsg))
end
return result
end
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))
by evaluating parsefile(...), results in
julia> parsefile(IOBuffer(test_file), fill(Int, 3))
ERROR: Failed to parse "error" as type Int64
in parsefield(::Type{Int64}, ::SubString{String}) at ./REPL[2]:7
in (::##1#2)(::Tuple{Int64,Tuple{DataType,SubString{String}}}) at
./<missing>:0
in collect_to!(::Array{Int64,1},
::Base.Generator{Enumerate{Base.Zip2{Array{DataType,1},Array{SubString{String},1}}},##1#2},
::Int64, ::Tuple{Int64,Tuple{Int64,Int64}}) at ./array.jl:340
in
collect(::Base.Generator{Enumerate{Base.Zip2{Array{DataType,1},Array{SubString{String},1}}},##1#2})
at ./array.jl:308
in parsefile(::Base.AbstractIOBuffer{Array{UInt8,1}}, ::Array{DataType,1})
at ./REPL[4]:5
On Wednesday, November 2, 2016 at 1:01:30 PM UTC-4, Tamas Papp wrote:
>
> 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
>