Loops, Menus, Do Something, Save

What do I have to do to get the Console.WriteLine portents in this module to work as simple regex functions for a string of data? This is what I have so far:

open System
open System.Text.RegularExpressions

let M() = Console.WriteLine("M:")
let R1() = Console.WriteLine("R:")
let R2() = Console.WriteLine("W:")

let rec Menu() =
    Console.Write("M (1), R (2)")
    match Int32.TryParse (Console.ReadLine()) with
    | true, 1 ->
        M()
        Console.Write("M:")
        let value1 = System.Console.ReadLine()
        let M = sprintf "%s" value1
        Menu()
    | true, 2 ->
        R1()
        Console.Write("R:")
        let value2 = System.Console.ReadLine()
        let Replace = sprintf "%s" value2
        R2()
        Console.Write("W:")
        let value3 = System.Console.ReadLine()
        let W = sprintf "%s" value3
        Menu()
           
Menu()

let String ="Lorem ipsum dolor sit amet, consectetur adipiscing elit."

You’ve mentioned that you want your Console.WriteLine calls to include regex in some way, but you haven’t described what you’re trying to do. What are you hoping to do with regex? Right now, your M, R1 and R2 functions don’t even take any input. In order to use Regex, you’ll need an input string as well as a pattern you’re trying to match the input string against.

So I got other functions like regexs to work with inputs. Turns out let String needed to be configured above the Menu() function with the added functions inserted into the actual Menu() function.

In another example related to looped functions I have a so-called “continuous async” function, but I would like it to work without a designated EntryPoint eg.


let Elipse = async {
    do! Async.Sleep 1000
   
    let test = do something

    return test
}


let Loop () = async {

    let! res = Elipse

    printf "%A" res
   
    }

[<EntryPoint>]
let main _ =
  Async.Start (Loop (), CancellationToken.None)
  Console.ReadKey () |> ignore
  0

You can call Async.Start from anywhere, it doesn’t have to be called from the entry point. If you wanted it to run immediately when the module loads, you could even say.

let Loop () = async {
    let! res = Elipse
    printf "%A" res
}

Async.Start (Loop (), CancellationToken.None)

Got it, but what do I need to do to make this Loop() and Async.Start exhibit a partial diagnostic eg. confirm results the same as the one that uses Entry Point?

I’m not sure what you mean by “exhibiting a partial diagnostic,” and the Entry Point you give doesn’t have any results, it just calls Loop, reads a key, and then exits, so I don’t know what results you’re trying to compare between.

For F# Async Loop methods in general do not indicate very well that a continuous loop or “elipse” is undergoing. In the example that I provided if I replace “do something” with a value the value will assume a static representation of a value eg. let value = 10. When I implement examples such as the one you showed me I’m assuming it works, but I end up with something like:

C:\pathtofolder\ (process 14320) exited with code 0.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
Press any key to close this window . . .

Why are these 2 scripts resolving different?

[<EntryPoint>]
let main _ =
  Async.Start (Loop (), CancellationToken.None)
  Console.ReadKey () |> ignore
  0

verses

Async.Start (Loop (), CancellationToken.None)

What can I do so that on my user side I’m prompted with more than just a process and exit code?

You might want to give this a read. Particularly the part about Async.Start. The main thread of your application won’t bother waiting for Loop to finish before it just exits. The difference is not actually dependent on if it’s in your EntryPoint or not, it’s that if you have that Console.ReadKey () in there, the main thread doesn’t exit right away and gives your Loop a chance to finish. You might want to look through the other ways to launch an async from that documentation.

That’s it. I think because my code was very long the specific arrangement of the code became questionable.

I have an example of a slightly more advanced loop async method that works and uses Async.StartChild to run tasks.

let Loop() = async {

    let! fnA = Async.StartChild A 
    let! fnB = Async.StartChild B

    let! ResA = fnA
    let! ResB = fnB

    let Results = sprintf "%s, %s" (ResA) (RB)
    printf "%A" Results
    
    }

  Async.Start (Loop (), CancellationToken.None)
  Console.ReadKey ()

Can I use the same Async.StartChild A or B method to run a module or other let functions that are not defined as Async fnA or Async fnB?

No you can’t directly call Async.StartChild on a non-async function, but if all you want to do is have the two functions run side-by-side in parallel on different threads, you can just wrap them in async on the spot:

open System.Threading

let a () = 
  Thread.Sleep 5_000
  5

let b () = 
  Thread.Sleep 5_000
  10

let loop = async { 
  let! fnA = Async.StartChild (async { return a() })
  let! fnB = Async.StartChild (async { return b() })

  let! resA = fnA
  let! resB = fnB

  printfn "%i, %i" resA resB
}


[<EntryPoint>]
let main args = 
  Async.RunSynchronously loop
  0

I can verify that this runs in just 5 seconds, even though a and b both wait for 5 seconds.

Does this relate to this kind of formula, too?

let str = File.ReadAllText "IO.txt"
let str = Regex.Replace(str,"\s+"," ")
let Res = Regex.Match(str, ".+").ToString().Split(' ')   

for i in 1..Res.Length - 2  do

let N = [Res.[i]] 

let Log = async {

The code preceding the designated async method doesn’t apparent syntaxically in an async either before it or after it. The code I’ve procured uses 2 asyncs and has other functions working between them. I would like the entirety of the script that I’ve completed to perform a continuous loop. Do I need asyncs to NP-complete?

I’m sorry, but I don’t understand your question at all.
Looking at your code, I can foresee you’ll run into trouble if you have asyncs inside of a for loop. There’s no real way to get from the async world back to the synchronous world except Async.RunSynchronously (which kinda defeats the purpose of async - you only do this at the entry point), or Async.Start, which is only useful for fire & forget stuff. If you want to do async stuff inside of a loop, then your loop is most likely going to have to be inside an async itself, e.g.,

let doStuff = async {
  let Res = Regex.Match(str, ".+").ToString().Split(' ')   
  for i in 1..Res.Length - 2  do
    let N = [Res.[i]] 
    let! Log = ...
}

Got it. In that case, what would be the correct syntax for looping actual modules continuously?

I think you’re saying you want two different loops to both be running concurrently and continuously? You could do that either with

let loop1 = async { 
  while true do
    do! Async.Sleep 2_000
    printfn "Hello from loop 1"
}

let loop2 = async {
  while true do
    do! Async.Sleep 3_000
    printfn "Hello from loop 2"
}


[<EntryPoint>]
let main args = 
  [loop1; loop2]
  |> Async.Parallel
  |> Async.RunSynchronously
  |> ignore

  0

or your main could instead look like

[<EntryPoint>]
let main args = 
  Async.RunSynchronously <| async {
    let! doLoop1 = Async.StartChild loop1
    let! doLoop2 = Async.StartChild loop2
    do! doLoop1
    do! doLoop2 // you'd never hit this line, but probably best to include
  }

  0

I’m shooting for keeping all my modules, loops, and subscripts on the same .fs or .fsx. So, I’ve broken script up into several module A = let etc… / module B = let etc… / module C = let etc… There are async sections in these, presumably there is other synchronous code between these routines, and all in all my works fine, but I would like to loop the entire thing continuously. Would resorting to a recursive loop function make more sense, and are you familiar with any working continuous recursive loop functions that will bind modules and run them similar to how the example above is expressed?

Sure, you can do something like

module A = 
  let rec loop1 () = async { 
    do! Async.Sleep 3_000
    printfn "Hello from loop 1"
    return! loop1 ()
  }


module B = 
  let rec loop2 () = async {
    do! Async.Sleep 5_000
    printfn "Hello from loop 2"
    return! loop2 ()
  }


[<EntryPoint>]
let main args = 
  [A.loop1 (); B.loop2 ()] 
  |> Async.Parallel
  |> Async.RunSynchronously
  |> ignore
  0

Can you corroborate that just a module can be called, run everything in the module more like this:

[<EntryPoint>]
let main args = 
  [A; B] 
  |> Async.Parallel
  |> Async.RunSynchronously
  |> ignore
  0

No, modules cannot be executed, only functions can. Or rather, any code inside a module that is executable (like a printf statement) is executed once immediately upon loading the module. You can’t run it again. However, you might be able to just turn your modules into functions directly. You can define subfunctions within a function. So for example, if you had

module A = 
  let f x = 
    sprintf "produced %i" (x+1) 
  
  for i in 1 .. 100 do 
    printfn "%s" (f i)

you could change that to

let A () = 
  let f x = 
    sprintf "produced %i" (x+1)
  
  for i in 1 .. 100 do 
    printfn "%s" (f i)

Then it won’t execute until called, but you can call it multiple times, and you can make it async, or recurse in an infinite loop, or whatever.
Note that one key difference is that in a module you can define new types, but you can’t define any types inside of a function. The types would have to be moved outside of the function.

Does F# have the means to do an operation like this without having to put module B after module A?

open System

module A =

 let hello() =
     printfn "Hello world"

     
module B =

let m1 = A.hello()