I was playing with JET and noticed that it does not like notation like while (i=f())!==nothing ...
while it is perfectly happy with i=f(); while i!==nothing ...
. f
is a function that returns Union{Int,Nothing}
. It seems the “inline assignment” inside of the while
predicate is the reason for this and I was hoping I can get more feedback concerning the root cause. Is this a bad way to write julia code? Here is a full example with two naive versions of Base.invperm
:
using JET
using Random
function inline_assign_while_loop(permutation::Vector{Int})
indices = Int[]
v = 1
while (i=findfirst(==(v),permutation)) !== nothing
push!(indices, i)
v += 1
end
indices
end
function normal_assign_while_loop(permutation::Vector{Int})
indices = Int[]
v = 1
i = findfirst(==(v),permutation)
while i !== nothing
push!(indices, i)
v += 1
i = findfirst(==(v),permutation)
end
indices
end
test_perm = randperm(10)
@assert inline_assign_while_loop(test_perm) == normal_assign_while_loop(test_perm) == invperm(test_perm)
# A possible error reported by JET because i!==nothing is not inferred
@report_call inline_assign_while_loop(test_perm)
# No possible error reported by JET
@report_call normal_assign_while_loop(test_perm)
@code_warntype is also happier with normal_assign_while_loop
, so I assume the issue is not with JET, rather with the type inference.
My question is: Is this something that Julia’s type inference should be doing better or is there something that I did explicitly wrong (or both)?
I prefer using the problematic inline assignment inside the while
predicate because that way I need to write it only once (instead of writing it once before the loop and once inside the loop body). I know this is an inefficient quadratic algorithm for invperm
, I am using it just as an example.