在 OCaml 中总计一个变量

Totalling a variable in OCaml

我有一个循环遍历字符串并打印出每个字符的 dir 的程序。

我想将这些 dir 值合计为一个离散值,我可以打印它。

这是我当前的代码:

let word = "(())";;

let dir = function
  | '(' -> 1
  | ')' -> -1
  | _ -> 0;;

let z =
  (String.iter (fun (c: char) ->
    let d = dir c in
      Printf.printf "%d is the direction of %c\n" d c
  ) word);;

目前,这会打印出以下内容:

1 is the direction of (
1 is the direction of (
-1 is the direction of )
-1 is the direction of )

我不想打印这些,而是​​希望它对 4 个值(1、1、-1、-1)求和并打印出来:

The overall direction is 0

如何在 OCaml 中实现这一点?

简短的回答是您应该使用 fold 而不是 iter。由于标准字符串库中没有 fold,您可能需要自己编写。

稍微长一点的答案是,您可能想要编写一个递归函数来跟踪累积和作为其参数之一。

使用参考:

let z =
  let counter = ref 0 in (String.iter (fun (c: char) ->
    counter := (!counter + dir c)
  ) word); !counter;; 

OCaml 和其他函数式编程语言中的循环通常使用递归函数表示。这是一个可能的实现:

let count_parens str =
  let n = String.length str in
  let rec loop s i =
    if i < n then match str.[i] with
      | '(' -> loop (s + 1) (i + 1)
      | ')' -> loop (s - 1) (i + 1)
      | _ -> loop s (i + 1)
    else s in
  loop 0 0

或者,使用您的 dir 函数:

let count_parens str =
  let n = String.length str in
  let rec loop s i =
    if i < n then loop (s + dir str.[i]) (i + 1)
    else s in
  loop 0 0

循环的具体化是一个fold函数。不幸的是,OCaml 标准库中没有 String.fold 函数。但是您可以使用 Janestreet 制作的 Core 标准库。使用 fold 函数可以更简洁地表达这个循环:

open Core_kernel.Std  

let count_parens str =
  String.fold str ~init:0 ~f:(fun s c -> s + dir c)