有没有办法只显示一次?

Is there a way to display this only once?

我编写了这个 sml 函数,它允许我显示 Ascii 的前 5 列 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"
  )
);

但是我想让header : "DEC"^"\t"^"OCT"^"\t"^"HEX"^"\t"^"BIN"^"\t"^"Symbol"在开头只显示一次,但我做不到。有人知道怎么做吗?

另一方面,我希望不对“radix”函数进行递归调用。那可能吗?写这个函数是明智的方法吗?

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

目前 header 显示多次,因为它在 List.tabulate 的函数内部被 print 编辑,table 中的每个数字显示一次。因此,您可以将打印 header 移到此函数之外并移至 parent 函数中。

为了清楚起见,我可能还会将单个字符的打印移到一个单独的函数中。 (我认为您在 charList 中的代码缩进得很好,但是如果一个函数做不止一件事,它就做太多了。)

例如

fun printChar (i : int) =
    print (Int.toString i ^ ...)

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

很高兴您发现 Char.toCString 与简单地打印任何字符相比是安全的。它似乎给了一些很好的名字,例如\t\n,但几乎不适用于每个函数。所以如果你真的想给你的 table 增添趣味,你可以添加一个辅助函数,

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)"
       | ...

并使用它代替 Char.toCString

是否打印字符本身或字符的某些描述可能取决于 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?

无论哪种方式,您都需要与 radix 函数等效的东西。

当然,看起来还可以。你可以缩短一点,但一般的做法是好的。

您通过 String.sub 常量查找避免了列表递归。太好了。