如何填充现有列表/数组 [英] how to populate existing list / array
问题描述
我是理性/ocaml/函数式编程的新手.
我了解List.append
和[] @ []
,但是这些函数将创建新列表,但是如何填充现有列表/数组?
- 填充列表的最佳方法是什么?
- 填充数组的最佳方法是什么?表示坐标类型是否为
let coords: array point = [];
- 还是这种情况下的流程(算法)错误?
原因代码:
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类似物:
const coords = [];
const append = raw => raw.forEach({x, y} => {
coords.push({
x: process(x),
y: process(y)
});
});
欢迎使用推理!
在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.如果您要设置列表项,那就错了.
- 根据您的情况填充列表的最佳方法是通过从旧列表中以非可变方式映射它:
let newList = List.map (fun blabla => ...) raw
- 与数组相同.映射它.如果您遇到问题,则有
Array.of_list
和Array.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?
- What is the best way to populate list?
- What is the best way to populate array? Means if coords type is
let coords: array point = [];
- 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.
- 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
- Same for array. Map over it. There's
Array.of_list
andArray.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!
这篇关于如何填充现有列表/数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!