Search code examples
recursioniterationsmlconvertersradix

Is there a way to display this only once?


I wrote this sml function that allows me to display the first 5 columns of the Ascii table.

fun radix (n, base) =
    let
        val b = size base
        val digit = fn n => str (String.sub (base, n))
        val radix' =
            fn (true, n) => digit n
            | (false, n) => radix (n div b, base) ^ digit (n mod b)
    in
        radix' (n < b, n)
    end;

val n = 255;
val charList = List.tabulate(n+1, 
  fn x => print(
      "DEC"^"\t"^"OCT"^"\t"^"HEX"^"\t"^"BIN"^"\t"^"Symbol"^"\n"^
      Int.toString(x)^"\t"^
      radix (x, "01234567")^"\t"^
      radix (x, "0123456789abcdef")^"\t"^
      radix (x, "01")^"\t"^
      Char.toCString(chr(x))^"\t"
  )
);

But I want the header : "DEC"^"\t"^"OCT"^"\t"^"HEX"^"\t"^"BIN"^"\t"^"Symbol" to be displayed only once at the beginning, but I can't do it. Does anyone know a way to do it?

On the other hand I would like to do without the resursive call of the "radix" function. Is that possible? And is it a wise way to write this function?


Solution

  • I want the header : "DEC"... to be displayed only once at the beginning

    Currently the header displays multiple times because it is being printed inside of List.tabulate's function, once for each number in the table. So you can move printing the header outside of this function and into a parent function.

    For clarity I might also move the printing of an individual character into a separate function. (I think you have indented the code in your charList very nicely, but if a function does more than one thing, it is doing too many things.)

    E.g.

    fun printChar (i : int) =
        print (Int.toString i ^ ...)
    
    fun printTable () =
        ( print "DEC\tOCT\tHEX\tBIN\tSymbol\n"
        ; List.tabulate (256, printChar)
        ; ()  (* why this? *)
        )
    

    It is very cool that you found Char.toCString which is safe compared to simply printing any character. It seems to give some pretty good names for e.g. \t and \n, but hardly for every function. So if you really want to spice up your table, you could add a helper function,

    fun prettyName character =
        if Char.isPrint character
        then ...
        else case ord character of
             0 => "NUL (null)"
           | 1 => "SOH (start of heading)"
           | 2 => "STX (start of text)"
           | ...
    

    and use that instead of Char.toCString.

    Whether to print a character itself or some description of it might be up to Char.isPrint.

    I would like to do without the resursive call of the "radix" function.

    Is that possible?

    And is it a wise way to write this function?

    You would need something equivalent to your radix function either way.

    Sure, it seems okay. You could shorten it a bit, but the general approach is good.

    You have avoided list recursion by doing String.sub constant lookups. That's great.