如何填充现有的列表/数组

tuc*_*hk4 0 ocaml reason

我是理性/ ocaml /函数式编程的新手.

我知道List.append[] @ [],但这些功能将创造新的名单,但如何填充现有列表/阵列?

  1. 填充列表的最佳方法是什么?
  2. 填充数组的最佳方法是什么?意味着coords类型是let coords: array point = [];
  3. 或者这是这种情况的错误流程(算法)?

原因代码:

type point = {x: int, y: int};

let coords: list point = [];

let append raw =>
  Array.iter
    (
      fun data => {
        let p = {x: data.x, y: data.y};
        /* how to append p to coords */
        ()
      }
    )
    raw;
Run Code Online (Sandbox Code Playgroud)

JS模拟:

const coords = [];
const append = raw => raw.forEach({x, y} => {
  coords.push({
    x: process(x),
    y: process(y)
  });
});
Run Code Online (Sandbox Code Playgroud)

che*_*lou 8

欢迎来到理智!

在Reason/OCaml中,列表是不可变的.在引擎盖下,它们是简单的单链表.每次"修改"它们时都会创建新的.这是一个例子:

let a = [1, 2, 3];
let b = [0, ...a];
Run Code Online (Sandbox Code Playgroud)

这类似于JavaScript的数组"spread",除了在这里,您将获取现有的a,0在前面链接一个新节点,并将其称为b.a仍然指向[1, 2, 3](因此"不可变").b现在[0, 1, 2, 3].这是有效的,因为该[1, 2, 3]部分是共享的.

这样做的好处是你不必担心传递你的列表而不小心有一个模糊的功能修改它.List的不变性允许您纯粹通过查看您正在盯着的值来推理您的代码(因为它永远不会改变!).

列表的缺点是在最后添加一些东西是低效的:

let c = a @ [4] 
Run Code Online (Sandbox Code Playgroud)

该操作基本上是一个项目的列表[4],并连续附加每个项目[1, 2, 3].因此在perf方面是线性的.但从列表实现的简单性来看,它在历史上被认为值得权衡.

所以3.如果您正在尝试设置列表项,那么这是错误的流程.

  1. 在您的案例中填充列表的最佳方法是从旧列表中非变异地映射它: let newList = List.map (fun blabla => ...) raw
  2. 数组相同.映射它.有Array.of_listArray.to_list,如果你曾经被卡住.

更多关于数组:OCaml数组是可变的,其大小是不可更改的.把它想象成一块记忆.你通过分配一个新的数组Array.make newSize,然后填充它Array.set.如果你要大量调整数组大小,那就没有意义,所以选择正确的数据结构.

对于JS编译,BuckleScript将ocaml数组编译为JS数组.它因此是可变的可调整大小的.你会发现你熟悉的JS阵列操作Js.Array

作为一般启发式,如果你想改变长度:试试filter.如果您想更改长度和包含的项目,请尝试fold_left.否则,map.

最近,我们开始实现一些不可变的,可调整大小的,可选的可变数组.敬请关注!