Stdout appears as type instable

I made the following progress bar, but according to @code_warntype it is somewhat type instable. How can I make it type stable?

function progressbar(ntimes::S, current::S) where S<:Int
  val = current/ntimes
  val_rounded = round(S, val*10)
  bars = "β–ˆ" ^ val_rounded
  remainder = " " ^ (10 - val_rounded)
  joined = bars*remainder
  percentage = round(val*100, digits=2)
  printstyled(stdout, "[$joined] $percentage% \r")
end

P.S.: I do not want to use third-party packages for having a progress bar.

Does it have to be type stable? It’s just printing progress after all. You could typeassert it to stdout::Base.TTY I guess, but I don’t think you’d see all that much difference in performance, and it might then fail on systems where stdout is not a TTY.

1 Like

Does it have to be type stable?

Yes, I want to embed this into my package. The package is type stable and I do not want to break the rule. As you said, the performance reduction might be negligible, but I don’t want to break the type stability of the package :frowning_face:
By the way, Thank You So Much :heart:

Yes… I do not do that.

1 Like

Will passing stdout as an argument work for you?

function progressbar(io, ntimes::S, current::S) where S<:Int
    val = current/ntimes
    val_rounded = round(S, val*10)
    bars = "β–ˆ" ^ val_rounded
    remainder = " " ^ (10 - val_rounded)
    joined = bars*remainder
    percentage = round(val*100, digits=2)
    printstyled(io, "[$joined] $percentage% \r")
end

With that change @code_warntype no longer complains. It also gives you the ability to print to other IO types.

3 Likes

Yes, how is that going be a problem?

Really cool. However, it prints the IO as well:

julia> for i ∈ 1:1000
         progressbar(IO, 1000, i)
         sleep(0.01)
       end
IO[β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ] 100.0% 

Interesting that it prints the literal IO. To print to stdout, you should call it like this:

julia> progressbar(stdout, 1000, 500)
[β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ     ] 50.0%

Or any even a file for example:

open("log.txt", "w") do io
    progressbar(io, 1000, 500)
end
1 Like

Thank you so much. Great!