Why does the first loop work but the second does not?
The MWE:
Summary
using Printf
for n in 1:10
if n == 1
flag = true
idx_last = 1
else
flag = false
idx_last = ifelse(flag, n, idx_last)
end
# Print Progress
Base.show(io::IO, f::Float64) = @printf(io, "%.2f", f)
end
for n in 1:10
if n == 1
flag = true
idx_last = 1
else
flag = false
idx_last = ifelse(flag, n, idx_last)
end
# Print Progress
# Base.show(io::IO, f::Float64) = @printf(io, "%.2f", f)
end
I get:
julia> using Printf
julia> for n in 1:10
if n == 1
flag = true
idx_last = 1
else
flag = false
idx_last = ifelse(flag, n, idx_last)
end
# Print Progress
Base.show(io::IO, f::Float64) = @printf(io, "%.2f", f)
end
julia> for n in 1:10
if n == 1
flag = true
idx_last = 1
else
flag = false
idx_last = ifelse(flag, n, idx_last)
end
# Print Progress
# Base.show(io::IO, f::Float64) = @printf(io, "%.2f", f)
end
ERROR: UndefVarError: `idx_last` not defined
Stacktrace:
[1] top-level scope
@ ./REPL[3]:7
Anyone have an idea why the first loop does work? My understanding from the docs is that idx_last should not persist into the second iteration. But it does.
Attempting to reproduce in two REPL’s each with clean temp environment (Julia v1.9.4).
The first version
(@v1.9) pkg> activate --temp
Activating new project at `C:\Users\x\AppData\Local\Temp\jl_06Fn89`
julia> using Printf
julia> for n in 1:10
if n == 1
flag = true
idx_last = 1
else
flag = false
idx_last = ifelse(flag, n, idx_last)
end
# Print Progress
Base.show(io::IO, f::Float64) = @printf(io, "%.2f", f)
end
ERROR: UndefVarError: `idx_last` not defined
Stacktrace:
[1] top-level scope
@ REPL[3]:7
and the second version
(@v1.9) pkg> activate --temp
Activating new project at `C:\Users\x\AppData\Local\Temp\jl_DNYW0n`
julia> using Printf
julia> for n in 1:10
if n == 1
flag = true
idx_last = 1
else
flag = false
idx_last = ifelse(flag, n, idx_last)
end
# Print Progress
# Base.show(io::IO, f::Float64) = @printf(io, "%.2f", f)
end
ERROR: UndefVarError: `idx_last` not defined
Stacktrace:
[1] top-level scope
@ .\REPL[3]:7
Thanks, I did try using fresh REPL sessions for each loop but not in a temp project.
I’m using version 1.10.0-rc2 and get the same results:
(@v1.10) pkg> activate --temp
Activating new project at `/tmp/jl_sQfyMH`
julia> using Printf
julia> for n in 1:10
if n == 1
flag = true
idx_last = 1
else
flag = true
idx_last = ifelse(flag, n, idx_last)
end
# Print Progress
Base.show(io::IO, f::Float64) = @printf(io, "%.2f", f)
print(idx_last)
end
12345678910
My versioninfo:
julia> versioninfo()
Julia Version 1.10.0-rc2
Commit dbb9c46795b (2023-12-03 15:25 UTC)
Build Info:
Official https://julialang.org/ release
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU: 64 × AMD Ryzen Threadripper 2990WX 32-Core Processor
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-15.0.7 (ORCJIT, znver1)
Threads: 1 on 64 virtual cores
It also runs using julia --startup-file=no. So not something in the startup.jl file it seems.
This seems like a version bug to me, I think it warrants opening an issue. I would leave out the print(idx_last) line if the problem reproduces without it, better to leave out cosmetic factors.
The only guess I have for idx_last persisting is if it somehow mistakenly assigned a global variable that disappears somehow? Pretty far-fetched, but you could throw in a println(n, hasproperty(Main, :idx_last), isdefined(Main, :idx_last)) (first checks if global variable exists, second checks if it is assigned to a value) as the first line in the loop body?
So I updated to 1.10.0. I got the same results, then added your line:
julia> using Printf
julia> for n in 1:10
println(n, hasproperty(Main, :idx_last), isdefined(Main, :idx_last))
if n == 1
flag = true
idx_last = 1
else
flag = false
idx_last = ifelse(flag, n, idx_last)
end
# Print Progress
Base.show(io::IO, f::Float64) = @printf(io, "%.2f", f)
end
1falsefalse
2falsefalse
3falsefalse
4falsefalse
5falsefalse
6falsefalse
7falsefalse
8falsefalse
9falsefalse
10falsefalse
julia> for n in 1:10
println(n, hasproperty(Main, :idx_last), isdefined(Main, :idx_last))
if n == 1
flag = true
idx_last = 1
else
flag = false
idx_last = ifelse(flag, n, idx_last)
end
# Print Progress
# Base.show(io::IO, f::Float64) = @printf(io, "%.2f", f)
end
1falsefalse
2falsefalse
ERROR: UndefVarError: `idx_last` not defined
Stacktrace:
[1] top-level scope
@ ./REPL[11]:8
It appears the second loop does iterate twice. Does anyone else see this in Julia 1.10?
It is supposed to, the first iteration goes to the unproblematic n==1 branch, the second iteration goes to the else branch where it throws an error over the non-existent idx_last in ifelse(flag, n, idx_last).
You demonstrated that it’s not a temporary global variable at least, so you should omit that println line in the MWE. You could mention that adding such a line would show the REPL’s global scope lacks idx_last at any point.
Still happens in the full 1.10.0 release, has an issue been opened on Github for this? BTW you don’t need to define Base.show in particular, even a local foo() = 0 before or after the if statement will cause this.