且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何填充现有列表/数组

更新时间:2023-02-05 14:32:40

欢迎使用推理!

在Reason/OCaml中,列表是不可变的.在后台,它们是简单的单链接列表.每次修改"它们时,您都要创建新的.这是一个示例:

let a = [1, 2, 3];
let b = [0, ...a];

这类似于JavaScript的数组"spread",不同的是这里要使用现有的a,在前面链接一个新节点0,并将其命名为b. a仍指向[1, 2, 3](因此为不变"). b现在是[0, 1, 2, 3].这是有效的,因为[1, 2, 3]部分是共享的.

这样做的好处是,您不必担心传递列表的麻烦,而无需意外地使用晦涩的功能对其进行修改. List的不变性使您可以纯粹通过查看您现在盯着的值来推理代码(因为它永远不会改变!).

list的缺点是在末尾添加内容效率很低:

let c = a @ [4] 

该操作基本上是获取一项[4]的列表,并依次将[1, 2, 3]的每一项附加到该列表.因此,在性能方面呈线性关系.但是从列表实现的简单性来看,从历史上看,这是值得权衡的.

所以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.Array 下找到熟悉的JS数组操作>

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

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

I am new at reason / ocaml / functional programming.

I know about List.append and [] @ [] but these functions will create new list but how to populate existing list / array?

  1. What is the best way to populate list?
  2. What is the best way to populate array? Means if coords type is let coords: array point = [];
  3. Or this is wrong flow (algorithm) for such case?

Reason code:

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;

JS analogue:

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

Welcome to Reason!

In Reason/OCaml, lists are immutable. Under the hood they're simple singly-linked list. You create new ones each time you "modify" them. Here's an example:

let a = [1, 2, 3];
let b = [0, ...a];

This is akin to JavaScript's array "spread", except here you're taking the existing a, linking a new node 0 at the front, and calling it b. a still points to [1, 2, 3] (thus "immutable"). b is now [0, 1, 2, 3]. This is efficient since the [1, 2, 3] part is shared.

The advantage of this is that you don't have to worry about passing your list around and accidentally have an obscure function modify it. List's immutability allows you to reason about your code purely by looking at the value you're staring right now (since it'll never change!).

The drawback of list is that it's inefficient to add something at the end:

let c = a @ [4] 

That operation's basically taking a list of one item, [4], and successively attaching each item of [1, 2, 3] to it. So linear in terms of perf. But judging by the simplicity of the list implementation, it was historically deemed worth the tradeoff.

So 3. it's the wrong flow if you're trying to set a list item.

  1. The best way to populate a list in your case is by mapping over it non-mutatively, from the old list: let newList = List.map (fun blabla => ...) raw
  2. Same for array. Map over it. There's Array.of_list and Array.to_list if you're ever stuck.

More on array: OCaml array is mutable, and its size is unchangeable. Think of it as a block of memory. You'd allocate a new array through Array.make newSize, then populate it through Array.set. This wouldn't make sense if you're resizing the array a lot, so choose the right data structure.

For JS compilation, BuckleScript compiles an ocaml array to a JS array. It's thus mutable and resizable. You'll find your familiar JS array operations under Js.Array

As a general heuristic, if you'd like to change the length: try filter. If you'd like to change the length and the contained items, try fold_left. Otherwise, map.

More recently, we've started implementing some immutable, resizable, optionally mutable array. Stay tuned!