Lambda 在OCaml中对变量求和

Lambda 在OCaml中对变量求和,lambda,functional-programming,ocaml,ml,Lambda,Functional Programming,Ocaml,Ml,我有一个程序,它通过一个字符串循环并打印出每个字符的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

我有一个程序,它通过一个字符串循环并打印出每个字符的
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中实现这一点?

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

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

使用引用:

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
循环的具体化是一个
折叠
函数。不幸的是,OCaml标准库中没有
String.fold
函数。但您可以使用Janestreet生成的标准库。使用
fold
函数,可以更简洁地表达此循环:

open Core_kernel.Std  

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

在这里使用引用是反习惯用法。它模糊了循环变量,并引入了命令式编程的其他注意事项。此外,这是一种函数式编程语言,因此最好尽可能使用函数式方法。你不需要使用太多的括号,它们只会把代码弄得乱七八糟。另一方面,即使出于您提到的原因在函数式编程中应该避免引用,在当前情况下,它也会使代码更短。
open Core_kernel.Std  

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