Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to update the same line in F# interactive using printf?

Hello everyone!

I am using F# in Visual Studio Community 2017 for scripting. Im handling large datasets, over which i often loop using recursvive functions. To have a rough idea how long this will take, I am currently using printfn to print the current iteration index. Although i guess this sounds (and is) trivial, here is an example:

let foo f bar maxIter =
    let rec loop currentIter resultList=
        if currentIter<maxIter then
            printfn "current Iteration: %i" currentIter
            loop (currentIter+1) ((f bar)::resultList)
        else
            List.rev resultList
    loop 0 []

enter image description here

This is really cluttering the fsi window, and it is impossible to follow if I additionally print other strings on different steps in a bigger function.

My Question is the following: can i somehow update just one line in fsi with the current iteration number? I have tried using printf and a carriage return:

printf "%i\r"

but this has the same result as using printfn.

Thanks in advance for your help!

Edit: As commenters on this thread pointed out, there currently seems to be no way to do this in VS FSI.

like image 201
kMutagene Avatar asked Aug 31 '25 03:08

kMutagene


1 Answers

A (self-contained) iteration counter could be implemeted by setting the cursor position:

let rec progress i : unit =
    printf "%i" i
    System.Threading.Thread.Sleep 1000
    System.Console.SetCursorPosition(0, System.Console.CursorTop)
    progress (i+1)

progress 0

Note 1: This will overwrite whatever is on the current line, i.e. other log output will be overwritten unless you implement some synchronization means or always use printfn except for the progress. This behaviour can be observed by:

open System
open System.Threading

let rec progress i p : unit =
    printf "%s %i" p i
    Thread.Sleep 1000
    Console.SetCursorPosition(0, Console.CursorTop)
    progress (i+1) p

Tasks.Task.Run(fun () -> progress 0 "t1")
Thread.Sleep 500
Tasks.Task.Run(fun () -> progress 0 "t2")

Note 2: Due to VS limitations this will not work in VisualStudio FSI. It does work in VS Code, the console (compiled to EXE, running CMD or PowerShell) or using non-VS FSI though (tested on Windows 10, VS 15.5.1).

like image 69
CaringDev Avatar answered Sep 02 '25 23:09

CaringDev