代码之家  ›  专栏  ›  技术社区  ›  duanemat

在OCaml中添加到字符串映射

  •  8
  • duanemat  · 技术社区  · 15 年前

    我一直在试图弄清楚我所想的是一个非常简单的任务,即从函数中向OCaml中的字符串映射添加条目。相关内容如下:

    module StringMap = Map.Make (String);;
    let m = StringMap.empty;;
    
    let rec count ke = match ke with
     |[] -> []
     |hd::tl -> begin let m = StringMap.add hd 1 m; [hd] @ count tl end;;
    

    我一直收到神秘的“语法错误”消息,但我还没有找到一个解决方案,即使在剥离代码基本上什么都没有。我可以用一个命令添加到字符串映射,但是如果我尝试运行 let m = StringMap.add hd 1 m 在函数内部,它无法运行。我相信这是个简单的问题,但有人能帮忙吗?谢谢。

    2 回复  |  直到 15 年前
        1
  •  15
  •   Sami    15 年前

    您的代码似乎有一些问题。但首先,这里有一个关于如何做你想做的事情的例子:

    module StringMap = Map.Make (String)
    
    let rec count m ke =
        match ke with
        | [] -> m
        | hd :: tl -> count (StringMap.add hd 1 m) tl
    
    let m = count StringMap.empty ["foo"; "bar"; "baz"]
    

    对原始代码的一些评论:

    • 双分号用于告诉REPL循环您希望它使用您的代码。如果不使用它,你应该避免它们。
    • 单个分号用于分隔命令式表达式,例如在赋值之后。这里有一个let表达式,其语法为“let<..>in<..>”,因此在它后面使用分号是错误的。(“let a=…”不带“in”是顶级构造,不能在本地使用)。
    • StringMap(以及ocaml中的大多数其他结构)是功能性的,而不是命令性的。你不能改变你在第一行声明的“m”。您必须构建结构,最后在循环结束时返回完全构建的结构。
        2
  •  10
  •   Community Mohan Dere    9 年前

    你的困惑源于你误解了 let 建造。它不修改对象:它不是赋值语句(。这个 构造给出 名称 给一个 价值 构造是
    名称 = in 表达
    名称 参考 价值 在里面 表达 . 在将名称绑定到该值之前,将计算该值一次。范围 表达 价值 外部 表达 (另一方面,这个值一直存在,直到垃圾被收集)。

    最高层 构造与表达式中的构造相似,但不具有 在里面 表达 部分。名称的作用域是程序的其余部分(好像 包含下面所有内容的部分,至少在进入模块之前)。

    m ,但那不是 := 参考 . 引用是可以修改的对象。这在Ocaml中不是自动的:与C、Java和Lisp等语言不同,Ocaml不使用单一语言特性为值命名并创建可修改的存储。这个 ref 使用 ! 运算符以获取其值:

    let r_m = ref StringMap.empty;; (*the type of r_m is 'a StringMap.t ref*)
    let rec count ke = match ke with
      | [] -> []
      | hd::tl -> r_m := StringMap.add hd 1 !r_m; [hd] @ count tl;;
    

    但这不是很好的Ocaml风格。Ocaml支持这种命令式风格,但是您应该避免它,因为命令式编程比函数式编程更容易出错。函数样式是在需要修改对象时创建新值。请注意,由 Map add 返回与旧对象共存的新对象(即 ). 切换到功能样式需要更改 count 通过将映射作为参数传递,对不同映射执行函数。我建议你 Sami's answer

    推荐文章