Heisenbug with Julia's parse?

Viewed 70

On today's Advent of Code I needed to parse strings into integers. The function I wrote for that was

function fd(s::String, fromto::UnitRange)::Bool
    try
        parse(UInt, s) in fromto
    catch ArgumentError
        false
    end    
end

That function was called several times within an isvalid which was called for all inputs to count the number of valid things.

The result was always 0 and the respective tests kept failing. Then I extracted one of the failing test things and debugged into isvalid, it passed!

I rearraged a few things and tested more, the same thing kept happening:

  1. Running the code regularly, fd never returned true.
  2. When stepping through, I got true where expected.

After replacing the parse to

function fd(s::String, fromto::UnitRange)::Bool
    parsed = tryparse(UInt, s)
    if isnothing(parsed)
        false
    else
        parsed in fromto
    end
end

it immediately worked always and the exercise was solved.

Shouldn't these two versions of the function always return the same result? What happened here?

Update1

This was the example that I used:

println("Sample is ", isvalid(Dict(
    "hcl" => "#623a2f",   # check with regex
    "ecl" => "grn",       # checked with set
    "pid" => "087499704", # check with regex
    "hgt" => "74in",      # check with regex
    "iyr" => "2012",      # this was parsed
    "eyr" => "2030",      # this was parsed
    "byr" => "1980",      # this was parsed
)))

Update 2

This post only has a subset of the code. If you want to try yourself, you can get the full file at GitHub. I also recorded a video showing the differing behavior with and without debugging.

The thing is demonstrated quite clearly with @assert fd("2010", 2000:2020) == fdt("2010", 2000:2020) failing in one scenario and not in the other.

0 Answers
Related