none
Pass this code from C# to F#. Menus and SubMenus. RRS feed

  • Question

  • I have a Menu and Sub-Menu code of the "C # 2019 console".

    I want to do the same but in F #. I don't understand the F # language. That's why I need help.
    When the program is done in F #, I will study it to familiarize myself with it.

    View zoom.

    Code C#:

    using System;
    
    namespace Menu_consola_18_cs
    {
        class Program
        {
            // Variable general para guardar el > de la última opción que haz entrado
            // en la hora de volver atrás. Por ejemplo: 
            private static int guardarOpcion = 0;
            static void Main(string[] args)
            {
                Console.Title = "Menú de opciones";
    
                // Tamaño ventana consola.
                // X anchura.
                Console.WindowWidth = 20;
    
                // Y altura.
                Console.WindowHeight = 5;
    
                // Oculto el cursor.
                Console.CursorVisible = false;
    
                // Fondo verde.
                Console.BackgroundColor = ConsoleColor.Green;
    
                // Letras negras.
                Console.ForegroundColor = ConsoleColor.Black;
    
                MenuPrincipal();
            }
    
            #region Menú principal.
            public static void MenuPrincipal()
            {
                // Almacena la tecla pulsada en la variable.
                ConsoleKey teclaInicial;
    
                // Limpiar pantalla.
                Console.Clear();
    
                // Posición del cursor del título del MENÚ PRINCIPAL.
                Console.SetCursorPosition(0, 0);
    
                // Título.
                Console.Write("   MENÚ PRINCIPAL   ");
    
                // Pocisión de la hora.
                Console.SetCursorPosition(4, 2);
    
                // Formato numérico dd/MM/yyyy.
                Console.Write(DateTime.Now.ToString("ddd dd MMM"));
    
                // Almacena en la variable una tecla pulsada.
                teclaInicial = Console.ReadKey(true).Key;
    
                // ¿Haz pulsado la tecla Enter?
                if (teclaInicial == ConsoleKey.Enter)
                {
                    // Sí. Se ejecuta esta función.
                    MenuOpciones();
                }
            }
            #endregion
    
            #region Menú de opciones principales.
            public static void MenuOpciones()
            {
                // Contador de teclas y navegador.
                int opcion = 0;
                opcion = guardarOpcion;
    
                // Capturar tecla para luego validar.
                ConsoleKey tecla;
    
                while (true)
                {
                    //******************************************************************
                    // Dibujo el menú principal.
    
                    // Limpiar pantalla.
                    Console.Clear();
    
                    switch (opcion)
                    {
                        case 0:
                            Console.SetCursorPosition(0, 0);
                            Console.Write("> Opción A.         ");
                            Console.SetCursorPosition(0, 1);
                            Console.Write("  Opción B.         ");
                            Console.SetCursorPosition(0, 2);
                            Console.Write("  Opción C.         ");
                            Console.SetCursorPosition(0, 3);
                            Console.Write("  Salir.            ");
                            break;
                        case 1:
                            Console.SetCursorPosition(0, 0);
                            Console.Write("  Opción A.         ");
                            Console.SetCursorPosition(0, 1);
                            Console.Write("> Opción B.         ");
                            Console.SetCursorPosition(0, 2);
                            Console.Write("  Opción C.         ");
                            Console.SetCursorPosition(0, 3);
                            Console.Write("  Salir.            ");
                            break;
                        case 2:
                            Console.SetCursorPosition(0, 0);
                            Console.Write("  Opción A.         ");
                            Console.SetCursorPosition(0, 1);
                            Console.Write("  Opción B.         ");
                            Console.SetCursorPosition(0, 2);
                            Console.Write("> Opción C.         ");
                            Console.SetCursorPosition(0, 3);
                            Console.Write("  Salir.            ");
                            break;
                        case 3:
                            Console.SetCursorPosition(0, 0);
                            Console.Write("  Opción A.         ");
                            Console.SetCursorPosition(0, 1);
                            Console.Write("  Opción B.         ");
                            Console.SetCursorPosition(0, 2);
                            Console.Write("  Opción C.         ");
                            Console.SetCursorPosition(0, 3);
                            Console.Write("> Salir.            ");
                            break;
                        default:
                            Console.Write("Fuera de rango.     ");
                            break;
                    }
    
                    // Fin de pintar el menú principal.
                    //******************************************************************
    
                    // Leer tecla ingresada por el usuario.
                    tecla = Console.ReadKey(true).Key;
    
                    // Validar el tipo de tecla.
                    if (tecla == ConsoleKey.Enter)
                    {
                        switch (opcion)
                        {
                            case 0:
                                OpcionA();
                                break;
                            case 1:
                                OpcionB();
                                break;
                            case 2:
                                OpcionC();
                                break;
                            case 3:
                                guardarOpcion = 0;
                                MenuPrincipal();
                                break;
                            default:
                                break;
                        }
                    }
    
                    // Flecha abajo del teclado.
                    if (tecla == ConsoleKey.DownArrow)
                    {
                        opcion++;
                    }
    
                    // Flecha arriba del teclado.
                    if (tecla == ConsoleKey.UpArrow)
                    {
                        opcion--;
                    }
    
                    // Si está en la última opción del menú, salta a la primera.
                    if (opcion > 3)
                    {
                        opcion = 0;
                    }
    
                    // Si está en la primera posición del menú, salta a la última.
                    if (opcion < 0)
                    {
                        opcion = 3;
                    }
                }
            }
            #endregion
    
            #region Opción A (0).
            public static void OpcionA()
            {
                ConsoleKey teclaOpcionA;
                Console.Clear();
                do
                {
                    Console.SetCursorPosition(0, 0);
                    Console.WriteLine("Estás en Opción A.");
                    Console.SetCursorPosition(0, 2);
                    Console.WriteLine("Pulse Enter para");
                    Console.SetCursorPosition(0, 3);
                    Console.WriteLine("Salir.");
    
                    // Almacena el teclado pulsado en la variable teclaSubMenuA.
                    teclaOpcionA = Console.ReadKey(true).Key;
    
                } while (teclaOpcionA != ConsoleKey.Enter);
            }
            #endregion
    
            #region Opción B (1).
            public static void OpcionB()
            {
                // Contador de teclas y navegador.
                int opcionB = 0;
    
                // Capturar tecla para luego validar.
                ConsoleKey teclaOpcionB;
    
                while (true)
                {
                    switch (opcionB)
                    {
                        case 0:
                            Console.SetCursorPosition(0, 0);
                            Console.WriteLine("Estás en Opción B.  ");
                            Console.SetCursorPosition(0, 1);
                            Console.WriteLine("> SubOpción B-1.    ");
                            Console.SetCursorPosition(0, 2);
                            Console.WriteLine("  SubOpción B-2     ");
                            Console.SetCursorPosition(0, 3);
                            Console.WriteLine("  Salir.            ");
                            break;
                        case 1:
                            Console.SetCursorPosition(0, 0);
                            Console.WriteLine("Estás en Opción B.  ");
                            Console.SetCursorPosition(0, 1);
                            Console.WriteLine("  SubOpción B-1.    ");
                            Console.SetCursorPosition(0, 2);
                            Console.WriteLine("> SubOpción B-2     ");
                            Console.SetCursorPosition(0, 3);
                            Console.WriteLine("  Salir.            ");
                            break;
                        case 2:
                            Console.SetCursorPosition(0, 0);
                            Console.WriteLine("Estás en Opción B.  ");
                            Console.SetCursorPosition(0, 1);
                            Console.WriteLine("  SubOpción B-1.    ");
                            Console.SetCursorPosition(0, 2);
                            Console.WriteLine("  SubOpción B-2     ");
                            Console.SetCursorPosition(0, 3);
                            Console.WriteLine("> Salir.            ");
                            break;
                        default:
                            Console.Write("Fuera de rango.     ");
                            break;
                    }
    
                    // Leer tecla ingresada por el usuario.
                    teclaOpcionB = Console.ReadKey(true).Key;
    
                    // Validar el tipo de tecla.
                    if (teclaOpcionB == ConsoleKey.Enter)
                    {
                        switch (opcionB)
                        {
                            case 0:
                                OpcionB1();
                                break;
                            case 1:
                                OpcionB2();
                                break;
                            case 2:
                                guardarOpcion = 1;
                                MenuOpciones();
                                break;
                            default:
                                Console.Write("Fuera de rango.     ");
                                break;
                        }
                    }
    
                    if (teclaOpcionB == ConsoleKey.DownArrow)
                    {
                        opcionB++;
                    }
    
                    if (teclaOpcionB == ConsoleKey.UpArrow)
                    {
                        opcionB--;
                    }
    
                    // Si está en la última opción, salta a la primera.
                    if (opcionB > 2)
                    {
                        opcionB = 0;
                    }
    
                    // Si está en la primera posición, salta a la última.
                    if (opcionB < 0)
                    {
                        opcionB = 2;
                    }
                }
            }
    
            #endregion
    
            #region Opcion B-1.
            public static void OpcionB1()
            {
                ConsoleKey teclaOpcionB1;
                Console.Clear();
                do
                {
                    Console.SetCursorPosition(0, 0);
                    Console.WriteLine("Estás en Opción B-1.");
                    Console.SetCursorPosition(0, 2);
                    Console.WriteLine("Pulse Enter para    ");
                    Console.SetCursorPosition(0, 3);
                    Console.WriteLine("volver atrás.       ");
    
                    // Almacena el teclado pulsado en la variable teclaSubMenuA.
                    teclaOpcionB1 = Console.ReadKey(true).Key;
    
                } while (teclaOpcionB1 != ConsoleKey.Enter);
            }
            #endregion
    
            #region Opcion B-2.
            public static void OpcionB2()
            {
                ConsoleKey teclaOpcionB2;
                Console.Clear();
                do
                {
                    Console.SetCursorPosition(0, 0);
                    Console.WriteLine("Estás en Opción B-2.");
                    Console.SetCursorPosition(0, 2);
                    Console.WriteLine("Pulse Enter para    ");
                    Console.SetCursorPosition(0, 3);
                    Console.WriteLine("volver atrás.       ");
    
                    // Almacena el teclado pulsado en la variable teclaSubMenuA.
                    teclaOpcionB2 = Console.ReadKey(true).Key;
    
                } while (teclaOpcionB2 != ConsoleKey.Enter);
            }
            #endregion
    
            #region Opción C (2).
            public static void OpcionC()
            {
                // Contador de teclas y navegador.
                int opcionC = 0;
    
                // Capturar tecla para luego validar.
                ConsoleKey teclaOpcionC;
                Console.Clear();
                
                while(true)
                {
                    switch (opcionC)
                    {
                        case 0:
                            Console.SetCursorPosition(0, 0);
                            Console.WriteLine("Estás en Opción C.  ");
                            Console.SetCursorPosition(0, 1);
                            Console.WriteLine("> Color 1.          ");
                            Console.SetCursorPosition(0, 2);
                            Console.WriteLine("  Color 2.          ");
                            Console.SetCursorPosition(0, 3);
                            Console.WriteLine("  Opción C-1.       ");
                            break;
                        case 1:
                            Console.SetCursorPosition(0, 0);
                            Console.WriteLine("Estás en Opción C.  ");
                            Console.SetCursorPosition(0, 1);
                            Console.WriteLine("  Color 1.          ");
                            Console.SetCursorPosition(0, 2);
                            Console.WriteLine("> Color 2.          ");
                            Console.SetCursorPosition(0, 3);
                            Console.WriteLine("  Opción C-1.       ");
                            break;
                        case 2:
                            Console.SetCursorPosition(0, 0);
                            Console.WriteLine("Estás en Opción C.  ");
                            Console.SetCursorPosition(0, 1);
                            Console.WriteLine("  Color 1.          ");
                            Console.SetCursorPosition(0, 2);
                            Console.WriteLine("  Color 2.          ");
                            Console.SetCursorPosition(0, 3);
                            Console.WriteLine("> Opción C-1.       ");
                            break;
                        case 3:
                            Console.SetCursorPosition(0, 0);
                            Console.WriteLine("> Color 3.          ");
                            Console.SetCursorPosition(0, 1);
                            Console.WriteLine("  Color 4.          ");
                            Console.SetCursorPosition(0, 2);
                            Console.WriteLine("  Color 5.          ");
                            Console.SetCursorPosition(0, 3);
                            Console.WriteLine("  Salir.            ");
                            break;
                        case 4:
                            Console.SetCursorPosition(0, 0);
                            Console.WriteLine("  Color 3.          ");
                            Console.SetCursorPosition(0, 1);
                            Console.WriteLine("> Color 4.          ");
                            Console.SetCursorPosition(0, 2);
                            Console.WriteLine("  Color 5.          ");
                            Console.SetCursorPosition(0, 3);
                            Console.WriteLine("  Salir.            ");
                            break;
                        case 5:
                            Console.SetCursorPosition(0, 0);
                            Console.WriteLine("  Color 3.          ");
                            Console.SetCursorPosition(0, 1);
                            Console.WriteLine("  Color 4.          ");
                            Console.SetCursorPosition(0, 2);
                            Console.WriteLine("> Color 5.          ");
                            Console.SetCursorPosition(0, 3);
                            Console.WriteLine("  Salir.            ");
                            break;
                        case 6:
                            Console.SetCursorPosition(0, 0);
                            Console.WriteLine("  Color 3.          ");
                            Console.SetCursorPosition(0, 1);
                            Console.WriteLine("  Color 4.          ");
                            Console.SetCursorPosition(0, 2);
                            Console.WriteLine("  Color 5.          ");
                            Console.SetCursorPosition(0, 3);
                            Console.WriteLine("> Salir.            ");
                            break;
    
                        default:
                            Console.Write("Fuera de rango.     ");
                            break;
                    }
    
                    // Leer tecla ingresada por el usuario.
                    teclaOpcionC = Console.ReadKey(true).Key;
    
                    // Validar el tipo de tecla.
                    if (teclaOpcionC == ConsoleKey.Enter)
                    {
                        switch (opcionC)
                        {
                            case 0:
                                // Fondo azul.
                                Console.BackgroundColor = ConsoleColor.Blue;
    
                                // Letras blancas.
                                Console.ForegroundColor = ConsoleColor.White;
                                break;
                            case 1:
                                // Fondo verde.
                                Console.BackgroundColor = ConsoleColor.Green;
    
                                // Letras negras.
                                Console.ForegroundColor = ConsoleColor.Black;
                                break;
                            case 2:
                                OpcionC1();
                                break;
                            case 3:
                                // Fondo negro.
                                Console.BackgroundColor = ConsoleColor.Black;
    
                                // Letras rojo.
                                Console.ForegroundColor = ConsoleColor.Red;
                                break;
                            case 4:
                                // Fondo negro.
                                Console.BackgroundColor = ConsoleColor.Black;
    
                                // Letras rojo.
                                Console.ForegroundColor = ConsoleColor.Yellow;
                                break;
                            case 5:
                                // Fondo negro.
                                Console.BackgroundColor = ConsoleColor.Red;
    
                                // Letras rojo.
                                Console.ForegroundColor = ConsoleColor.DarkRed;
                                break;
                            case 6:
                                guardarOpcion = 2;
                                MenuOpciones();
                                break;
                            default:
                                Console.Write("Fuera de rango.     ");
                                break;
                        }
                    }
    
                    if (teclaOpcionC == ConsoleKey.DownArrow)
                    {
                        opcionC++;
                    }
    
                    if (teclaOpcionC == ConsoleKey.UpArrow)
                    {
                        opcionC--;
                    }
    
                    // Si está en la última opción, salta a la primera.
                    if (opcionC > 6)
                    {
                        opcionC = 0;
                    }
    
                    // Si está en la primera posición, salta a la última.
                    if (opcionC < 0)
                    {
                        opcionC = 6;
                    }
                }
            }
            #endregion
    
            #region OpcionC-1.
            public static void OpcionC1()
            {
                // Contador de teclas y navegador.
                int opcionC1 = 0;
    
                // Capturar tecla para luego validar.
                ConsoleKey teclaOpcionC1;
                Console.Clear();
                
                while(true)
                {
                    Console.Clear();
    
                    switch (opcionC1)
                    {
                        case 0:
                            Console.SetCursorPosition(0, 0);
                            Console.WriteLine("Estás en Opción C-1.");
                            Console.SetCursorPosition(0, 2);
                            Console.WriteLine("  SI");
                            Console.SetCursorPosition(16, 2);
                            Console.WriteLine("> NO");
                            break;
                        case 1:
                            Console.SetCursorPosition(0, 0);
                            Console.WriteLine("Estás en Opción C-1.");
                            Console.SetCursorPosition(0, 2);
                            Console.WriteLine("> SI");
                            Console.SetCursorPosition(16, 2);
                            Console.WriteLine("  NO");
                            break;
                        default:
                            Console.Write("Fuera de rango.     ");
                            break;
                    }
    
                    // Leer tecla ingresada por el usuario.
                    teclaOpcionC1 = Console.ReadKey(true).Key;
    
                    // Validar el tipo de tecla.
                    if (teclaOpcionC1 == ConsoleKey.Enter)
                    {
                        switch (opcionC1)
                        {
                            case 0:
                                guardarOpcion = 2;
                                MenuPrincipal();
                                //Console.Clear();
                                break;
                            case 1:
                                OpcionSI();
                                break;
                            default:
                                Console.Write("Fuera de rango.     ");
                                break;
                        }
                    }
    
                    // Flecha derecha.
                    if (teclaOpcionC1 == ConsoleKey.RightArrow)
                    {
                        opcionC1++;
                    }
    
                    // Flecha izquierda.
                    if (teclaOpcionC1 == ConsoleKey.LeftArrow)
                    {
                        opcionC1--;
                    }
    
                    // Si está en la última opción, salta a la primera.
                    if (opcionC1 > 1)
                    {
                        opcionC1 = 0;
                    }
    
                    // Si está en la primera posición, salta a la última.
                    if (opcionC1 < 0)
                    {
                        opcionC1 = 1;
                    }
                }
            }
            #endregion
    
            #region opcionSI del sub menú C-1.
            public static void OpcionSI()
            {
                ConsoleKey teclaOpcionB1;
                Console.Clear();
                do
                {
                    Console.SetCursorPosition(0, 0);
                    Console.WriteLine("Estás en Opción SÍ.");
                    Console.SetCursorPosition(0, 2);
                    Console.WriteLine("Pulse Enter para    ");
                    Console.SetCursorPosition(0, 3);
                    Console.WriteLine("volver atrás.       ");
    
                    // Almacena el teclado pulsado en la variable teclaOpciónB1.
                    teclaOpcionB1 = Console.ReadKey(true).Key;
    
                } while (teclaOpcionB1 != ConsoleKey.Enter);
            }
            #endregion
        }
    }

    It seems very complicated to adapt C# to F#, programmers. ;)


    http://electronica-pic.blogspot.com

    Saturday, February 29, 2020 11:12 PM

Answers

  • To start with, that C# code is horrible and needs a thorough refactoring to reduce the level of copy and paste.

    It is possible to just do a "remove the semicolons" literal transcription, like

    namespace Menu_consola_18_cs
    
    open System
    
    type internal Program() =
      static member val guardarOpcion = 0 with get, set
    
      static member Main _ =
        Console.Title <- "Menú de opciones"
        Console.WindowWidth <- 20
        Console.WindowHeight <- 5
        Console.CursorVisible <- false
        Console.BackgroundColor <- ConsoleColor.Green
        Console.ForegroundColor <- ConsoleColor.Black
        Program.MenuPrincipal()
    
      static member MenuPrincipal() =
        Console.Clear()
        Console.SetCursorPosition(0, 0)
        Console.Write("   MENÚ PRINCIPAL   ")
        Console.SetCursorPosition(4, 2)
        Console.Write(DateTime.Now.ToString("ddd dd MMM"))
        if  Console.ReadKey(true).Key = ConsoleKey.Enter
        then Program.MenuOpciones()
    
      static member MenuOpciones() =
        let rec loop option =
                Console.Clear()
                match option with
                | 0 ->  Console.SetCursorPosition(0, 0)
                        Console.Write("> Opción A.         ")
                        Console.SetCursorPosition(0, 1)
                        Console.Write("  Opción B.         ")
                        Console.SetCursorPosition(0, 2)
                        Console.Write("  Opción C.         ")
                        Console.SetCursorPosition(0, 3);
                        Console.Write("  Salir.            ")
                | 1 ->  Console.SetCursorPosition(0, 0)
                        Console.Write("  Opción A.         ")
                        Console.SetCursorPosition(0, 1)
                        Console.Write("> Opción B.         ")
                        Console.SetCursorPosition(0, 2)
                        Console.Write("  Opción C.         ")
                        Console.SetCursorPosition(0, 3)
                        Console.Write("  Salir.            ")
                | 2 ->  Console.SetCursorPosition(0, 0)
                        Console.Write("  Opción A.         ")
                        Console.SetCursorPosition(0, 1)
                        Console.Write("  Opción B.         ")
                        Console.SetCursorPosition(0, 2)
                        Console.Write("> Opción C.         ")
                        Console.SetCursorPosition(0, 3)
                        Console.Write("  Salir.            ")
                 | 3 -> Console.SetCursorPosition(0, 0)
                        Console.Write("  Opción A.         ")
                        Console.SetCursorPosition(0, 1)
                        Console.Write("  Opción B.         ")
                        Console.SetCursorPosition(0, 2)
                        Console.Write("  Opción C.         ")
                        Console.SetCursorPosition(0, 3)
                        Console.Write("> Salir.            ")
                 | _ -> Console.Write("Fuera de rango.     ")
    
                 match Console.ReadKey(true).Key with
                 | ConsoleKey.Enter ->
                    match opcion with
                    | 0 -> Program.OpcionA()
                    | 1 -> Program.OpcionB()
                    | 2 -> Program.OpcionC()
                    | 3 -> guardarOpcion <- 0
                           Program.MenuPrincipal()
                    | _ -> ()
                | ConsoleKey.DownArrow ->
                  loop ((opcion + 1) % 4)
                | ConsoleKey.UpArrow ->
                  loop ((opcion + 3) % 4)
        loop guardarOpcion
    
    ...
    [<EntryPoint>]
    let main argv =
      Program.Main argv
      0 // return an integer exit code
    

    but far better is to rebuild it as what it should be, which is a state machine, with as much of the duplication as possible factored out to make it rather more data driven, something like

    namespace Menu_consola_18_cs open System module Program = type TopLevel = | A = 0 | B = 1 | C = 2 | Exit = 3 let next t = match t with | TopLevel.A -> TopLevel.B | TopLevel.B -> TopLevel.C | TopLevel.Exit -> TopLevel.A | _ -> TopLevel.Exit let prev t = match t with | TopLevel.B -> TopLevel.A | TopLevel.C -> TopLevel.B | TopLevel.Exit -> TopLevel.C | _ -> TopLevel.Exit type State = | Principal | Option of TopLevel | OptionA // OptionB, OptionB1, ... let drawPrincipal () = Console.Clear() Console.SetCursorPosition(0, 0) Console.Write(" MENÚ PRINCIPAL ") Console.SetCursorPosition(4, 2) Console.Write(DateTime.Now.ToString("ddd dd MMM")) let writeOption index selected (line : string) = Console.SetCursorPosition(0, index) Console.Write( match selected with | Some true -> "> " | Some false -> " " | _ -> String.Empty ) Console.Write(line) let drawMenu lines predicate = Console.Clear(); lines |> List.iteri (fun index line -> writeOption index (predicate index) line ) let drawOptions opcion = drawMenu [ "Opción A. " "Opción B. " "Opción C. " "Salir. " ] (fun index -> Some (index = int opcion)) let drawOptionA () = drawMenu [ "Estás en Opción A." String.Empty "Pulse Enter para" "Salir." ] (fun _ -> None) let rec mainLoop state = let tecla = Console.ReadKey(true).Key let setOption o = drawOptions o mainLoop (Option o) let setOptionA () = drawOptionA () mainLoop OptionA match state with | Principal -> match tecla with | ConsoleKey.Enter -> setOption TopLevel.A | _ -> () | Option opcion -> match tecla with | ConsoleKey.DownArrow -> opcion |> next |> setOption | ConsoleKey.UpArrow -> opcion |> prev |> setOption | ConsoleKey.Enter -> match opcion with | TopLevel.A -> setOptionA () | TopLevel.B // -> todo | TopLevel.C // -> todo | _ -> drawPrincipal () mainLoop Principal | _ -> setOption opcion | OptionA -> match tecla with | ConsoleKey.Enter -> setOption TopLevel.A | _ -> setOptionA () //| OptionB, OptionB1, ... [<EntryPoint>] let main argv = Console.Title <- "Menú de opciones" Console.WindowWidth <- 20 Console.WindowHeight <- 5 Console.CursorVisible <- false Console.BackgroundColor <- ConsoleColor.Green Console.ForegroundColor <- ConsoleColor.Black drawPrincipal () mainLoop Principal 0 // return an integer exit code

    You could and should do something like this in your C# implementation, with the one difference that the F# style tail-recursion for repetition here should be replaced by the usual `while(true)` loop

    • Marked as answer by Metaconta Monday, March 2, 2020 11:28 PM
    Monday, March 2, 2020 1:47 PM

All replies

  • To start with, that C# code is horrible and needs a thorough refactoring to reduce the level of copy and paste.

    It is possible to just do a "remove the semicolons" literal transcription, like

    namespace Menu_consola_18_cs
    
    open System
    
    type internal Program() =
      static member val guardarOpcion = 0 with get, set
    
      static member Main _ =
        Console.Title <- "Menú de opciones"
        Console.WindowWidth <- 20
        Console.WindowHeight <- 5
        Console.CursorVisible <- false
        Console.BackgroundColor <- ConsoleColor.Green
        Console.ForegroundColor <- ConsoleColor.Black
        Program.MenuPrincipal()
    
      static member MenuPrincipal() =
        Console.Clear()
        Console.SetCursorPosition(0, 0)
        Console.Write("   MENÚ PRINCIPAL   ")
        Console.SetCursorPosition(4, 2)
        Console.Write(DateTime.Now.ToString("ddd dd MMM"))
        if  Console.ReadKey(true).Key = ConsoleKey.Enter
        then Program.MenuOpciones()
    
      static member MenuOpciones() =
        let rec loop option =
                Console.Clear()
                match option with
                | 0 ->  Console.SetCursorPosition(0, 0)
                        Console.Write("> Opción A.         ")
                        Console.SetCursorPosition(0, 1)
                        Console.Write("  Opción B.         ")
                        Console.SetCursorPosition(0, 2)
                        Console.Write("  Opción C.         ")
                        Console.SetCursorPosition(0, 3);
                        Console.Write("  Salir.            ")
                | 1 ->  Console.SetCursorPosition(0, 0)
                        Console.Write("  Opción A.         ")
                        Console.SetCursorPosition(0, 1)
                        Console.Write("> Opción B.         ")
                        Console.SetCursorPosition(0, 2)
                        Console.Write("  Opción C.         ")
                        Console.SetCursorPosition(0, 3)
                        Console.Write("  Salir.            ")
                | 2 ->  Console.SetCursorPosition(0, 0)
                        Console.Write("  Opción A.         ")
                        Console.SetCursorPosition(0, 1)
                        Console.Write("  Opción B.         ")
                        Console.SetCursorPosition(0, 2)
                        Console.Write("> Opción C.         ")
                        Console.SetCursorPosition(0, 3)
                        Console.Write("  Salir.            ")
                 | 3 -> Console.SetCursorPosition(0, 0)
                        Console.Write("  Opción A.         ")
                        Console.SetCursorPosition(0, 1)
                        Console.Write("  Opción B.         ")
                        Console.SetCursorPosition(0, 2)
                        Console.Write("  Opción C.         ")
                        Console.SetCursorPosition(0, 3)
                        Console.Write("> Salir.            ")
                 | _ -> Console.Write("Fuera de rango.     ")
    
                 match Console.ReadKey(true).Key with
                 | ConsoleKey.Enter ->
                    match opcion with
                    | 0 -> Program.OpcionA()
                    | 1 -> Program.OpcionB()
                    | 2 -> Program.OpcionC()
                    | 3 -> guardarOpcion <- 0
                           Program.MenuPrincipal()
                    | _ -> ()
                | ConsoleKey.DownArrow ->
                  loop ((opcion + 1) % 4)
                | ConsoleKey.UpArrow ->
                  loop ((opcion + 3) % 4)
        loop guardarOpcion
    
    ...
    [<EntryPoint>]
    let main argv =
      Program.Main argv
      0 // return an integer exit code
    

    but far better is to rebuild it as what it should be, which is a state machine, with as much of the duplication as possible factored out to make it rather more data driven, something like

    namespace Menu_consola_18_cs open System module Program = type TopLevel = | A = 0 | B = 1 | C = 2 | Exit = 3 let next t = match t with | TopLevel.A -> TopLevel.B | TopLevel.B -> TopLevel.C | TopLevel.Exit -> TopLevel.A | _ -> TopLevel.Exit let prev t = match t with | TopLevel.B -> TopLevel.A | TopLevel.C -> TopLevel.B | TopLevel.Exit -> TopLevel.C | _ -> TopLevel.Exit type State = | Principal | Option of TopLevel | OptionA // OptionB, OptionB1, ... let drawPrincipal () = Console.Clear() Console.SetCursorPosition(0, 0) Console.Write(" MENÚ PRINCIPAL ") Console.SetCursorPosition(4, 2) Console.Write(DateTime.Now.ToString("ddd dd MMM")) let writeOption index selected (line : string) = Console.SetCursorPosition(0, index) Console.Write( match selected with | Some true -> "> " | Some false -> " " | _ -> String.Empty ) Console.Write(line) let drawMenu lines predicate = Console.Clear(); lines |> List.iteri (fun index line -> writeOption index (predicate index) line ) let drawOptions opcion = drawMenu [ "Opción A. " "Opción B. " "Opción C. " "Salir. " ] (fun index -> Some (index = int opcion)) let drawOptionA () = drawMenu [ "Estás en Opción A." String.Empty "Pulse Enter para" "Salir." ] (fun _ -> None) let rec mainLoop state = let tecla = Console.ReadKey(true).Key let setOption o = drawOptions o mainLoop (Option o) let setOptionA () = drawOptionA () mainLoop OptionA match state with | Principal -> match tecla with | ConsoleKey.Enter -> setOption TopLevel.A | _ -> () | Option opcion -> match tecla with | ConsoleKey.DownArrow -> opcion |> next |> setOption | ConsoleKey.UpArrow -> opcion |> prev |> setOption | ConsoleKey.Enter -> match opcion with | TopLevel.A -> setOptionA () | TopLevel.B // -> todo | TopLevel.C // -> todo | _ -> drawPrincipal () mainLoop Principal | _ -> setOption opcion | OptionA -> match tecla with | ConsoleKey.Enter -> setOption TopLevel.A | _ -> setOptionA () //| OptionB, OptionB1, ... [<EntryPoint>] let main argv = Console.Title <- "Menú de opciones" Console.WindowWidth <- 20 Console.WindowHeight <- 5 Console.CursorVisible <- false Console.BackgroundColor <- ConsoleColor.Green Console.ForegroundColor <- ConsoleColor.Black drawPrincipal () mainLoop Principal 0 // return an integer exit code

    You could and should do something like this in your C# implementation, with the one difference that the F# style tail-recursion for repetition here should be replaced by the usual `while(true)` loop

    • Marked as answer by Metaconta Monday, March 2, 2020 11:28 PM
    Monday, March 2, 2020 1:47 PM
  • Hi:

    This horrible code in C # was made by a friend, because he says that 20 years ago, he was taught like this at the time of MS-DOS.

    Your first code does not work for me. Your second F # code does work.

    I will try to improve the C # code, without repetitions and much short range. The idea is that you can create menus and submenus very easily. Both to add more options and to remove them.

    I will return in the future.

    Thanks for your time.


    http://electronica-pic.blogspot.com

    Monday, March 2, 2020 11:28 PM