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 
>

Reply via email to