普遍使用Core的`List.init`吗? [英] Core's `List.init` in Pervasives?

查看:75
本文介绍了普遍使用Core的`List.init`吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我习惯了JaneStreet的Core库.它的List模块具有简洁的init功能:

I'm used to JaneStreet's Core library. Its List module has a neat init function:

List.init;;
- : int -> f:(int -> 'a) -> 'a list = <fun>

它允许您使用自定义函数初始化元素来创建列表:

It allows you to create a list with using a custom function to initialize elements:

List.init 5 ~f:(Fn.id);;
- : int list = [0; 1; 2; 3; 4]

List.init 5 ~f:(Int.to_string);;
- : string list = ["0"; "1"; "2"; "3"; "4"]

但是,Pervasives中似乎不存在此功能,这很可悲.我是否缺少某些东西,还是必须自己实施?如果我确实需要编写它,该如何实现?

However, this function doesn't seem to exist in Pervasives, which is sad. Am I missing something, or do I have to implement it myself? And if I do need to write it, how do I achieve this?

编辑:

我写了init的命令式版本,但是在这种情况下不得不诉诸OCaml的命令式功能是不合适的. :(

I have written an imperative version of init, but it doesn't feel right to have to resort to OCaml's imperative features in such a case. :(

let init n ~f =
  let i = ref 0 in
  let l = ref [] in
  while !i < n do
    l := (f !i) :: !l;
    incr i;
  done;
  List.rev !l
;;

我已经在OCaml的GitHub上打开了拉请求,以包含此功能

I've opened a pull request on OCaml's GitHub to have this feature included.

此功能已在OCaml 4.06中发布.

The feature was released in OCaml 4.06.

推荐答案

递归实现非常简单.但是,它不是尾递归的,这意味着您将面临大列表的堆栈溢出的风险:

A recursive implementation is fairly straightforward. However, it is not tail-recursive, which means that you'll risk a stack overflow for large lists:

let init_list n ~f =
  let rec init_list' i n f =
    if i >= n then []
    else (f i) :: (init_list' (i+1) n f)
  in init_list' 0 n f

我们可以使用常用技术将其转换为尾递归版本:

We can transform it into a tail-recursive version using the usual techniques:

let init_list n ~f =
  let rec init_list' acc i n f =
    if i >= n then acc
    else init_list' ((f i) :: acc) (i+1) n f
  in List.rev (init_list' [] 0 n f)

这使用累加器,并且还需要颠倒中间结果,因为列表是反向构造的.请注意,我们也可以使用f (n-i-1)而不是f i来避免反转列表,但是如果f具有副作用,这可能会导致意外的行为.

This uses an accumulator and also needs to reverse the intermediate result, as the list is constructed in reverse. Note that we could also use f (n-i-1) instead of f i to avoid reversing the list, but this may lead to unexpected behavior if f has side-effects.

另一种较短的解决方案是简单地将Array.init用作起点:

An alternative and shorter solution is to simply use Array.init as a starting point:

let init_list n ~f = Array.(init n f |> to_list)

这篇关于普遍使用Core的`List.init`吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆