将数组送入printfn

时间:2017-02-22 17:56:52

标签: f# printf

我正在打印Tic-Tac-Toe板。我有一个字符串,用于电路板的每个单元格和电路板的格式字符串。我现在正在做:

let cells = [| 'X'; 'O'; 'X'; 'O'; 'X'; 'O'; ' '; ' '; ' ' |]
printfn ".===.===.===.\n\
         | %c | %c | %c |\n\
         .===.===.===.\n\
         | %c | %c | %c |\n\
         .===.===.===.\n\
         | %c | %c | %c |\n\
         .===.===.===.\n" cells.[0] cells.[1] cells.[2] cells.[3] cells.[4] cells.[5] cells.[6] cells.[7] cells.[8]

有没有办法将cells数组提供给printfn而不显式枚举数组中的所有9个项目?我可以以某种方式使用Array.fold或kprintf吗?

3 个答案:

答案 0 :(得分:5)

Funk的答案非常好,但我认为你可以通过引入一个join函数来连接元素(单个单元格或行)与它们之间的分隔符并围绕它们来简化它。

let join s arr = sprintf "%s%s%s" s (String.concat s arr) s

然后你可以这样做:

cells
|> Seq.chunkBySize 3
|> Seq.map (Seq.map (sprintf " %c ") >> join "|")
|> Seq.map (fun s -> s + "\n")
|> join ".===.===.===.\n"
|> printfn "%s"

答案 1 :(得分:4)

这远非性感,但有一种模式可以找到。

cells
|> Array.toList
|> List.chunkBySize 3
|> List.fold 
    (fun acc list -> acc + 
                     (list |> List.fold (fun acc char -> acc + sprintf "| %c " char) "") + 
                     "|\n.===.===.===.\n") 
    ".===.===.===.\n"
|> printf "%s"

答案 2 :(得分:3)

每次连续应用函数的参数都会产生不同的类型。例如:

let f1 = printfn "%d %d %d"  // f1 : int -> int -> int -> unit
let f2 = f1 0  // f2 : int -> int -> unit
let f3 = f2 1  // f3 : int -> unit
let r = f3 2   // r  : unit

请注意f1f2f3r都有不同的类型。不同的类型意味着您无法将它们推送到通用数据结构中,例如列表或序列。

(老实说,有一种方法可以使用方法重载,但这往往会破坏编译器,通常对于实际应用程序来说并不是必需的)

我宁愿走另一条路:

for i in 0..2 do
  printf ".===.===.===.\n|"
  for j in 0..2 do
    printf "%c |" cells.[i*3+j]
  printfn ""
printfn ".===.===.===."