【问题标题】:Ocaml - Accessing components in an array of recordsOcaml - 访问记录数组中的组件
【发布时间】:2012-12-22 09:11:31
【问题描述】:

我有一个记录类型 tt 的数组 - 最初包含更多组件 ;-) - 并且喜欢在 for 循环中更改其值:

type tt={mutable x: int};;
let f0={x= -1};;
let max=10;;
let ff=Array.create max f0;;
for i=0 to max-1 do ff.(i).x <- i;done;;

尽管如此,ff 的所有字段的值都是 9,而不是从 0 到 9。ff.(i).x 是否正确?我也试过了

for i=0 to max-1 do f0.x <- i;ff.(i) <- f0;done;;

但结果相同...(我使用的是 OCaml 版本 4.00.1) 怎么了?如果有人能给我提示,我会很高兴!

【问题讨论】:

    标签: arrays ocaml record


    【解决方案1】:

    这是初学者在使用Array.create 和可变状态时犯的一个经典错误。我已经详细解释了there。总结是Array.create n foo 没有创建foo 的副本(怎么可能?),它创建了一个case 数组,它们都指向同一个foo

    【讨论】:

      【解决方案2】:

      问题在于ff 数组的所有单元格都包含相同 元素,即f0。您需要为每个单元格创建一个 tt 类型的新元素。 这是一种方法:

      type tt={mutable x: int};;
      let max=10;;
      let ff=Array.init max (fun i -> {x= i});;
      

      现在您可以修改一个单元格而不影响其他单元格。

      【讨论】:

        【解决方案3】:

        问题在于,由于记录是可变的,它是按引用而不是按值存储的,正如您对非可变数据类型所期望的那样(作为整数)所以当你这样做时

        let ff=Array.create 10 f0;;
        

        您实际上存储了对同一记录的 10 个引用。然后每次迭代

        for i=0 to max-1 do ff.(i).x <- i;done;;
        

        只是多次更新同一个引用,所以由于上次迭代是使用i = 9,那么数组中包含的唯一真实记录会获取该值。

        您需要做的是创建 10 条不同的记录,例如:

        # type tt = {mutable x: int};;
        type tt = { mutable x : int; }
        # let f = Array.init 10 (fun i -> { x = -1});;
        val f : tt array =
          [|{x = -1}; {x = -1}; {x = -1}; {x = -1}; {x = -1}; {x = -1}; {x = -1};
            {x = -1}; {x = -1}; {x = -1}|]
        # f.(2).x <- 2;;
        - : unit = ()
        # f;;
        - : tt array =
        [|{x = -1}; {x = -1}; {x = 2}; {x = -1}; {x = -1}; {x = -1}; {x = -1};
          {x = -1}; {x = -1}; {x = -1}|]
        

        【讨论】:

        • 实际上,OCaml 中的大多数类型都是装箱的(是引用类型),除了 int 和可以表示为 int 的东西(如 boolchar 和简单的类似枚举的数据类型)。例如浮动是装箱的;您可以通过== 看到这一点(尽管浮点数组作为特例未装箱)。顺便说一下,像整数和浮点数这样的简单数据类型在定义上是不可变的,因为它们没有内部结构。对于不可变类型,如果它是值类型或引用类型,则没有区别(== 除外),因此通常可以安全地将 OCaml 中的所有类型都视为引用类型。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-25
        • 2017-05-04
        相关资源
        最近更新 更多