我想实现Haskell cycle
函数的模拟。
如果我显式地传递list元素,这似乎是微不足道的:
let cycle a b c =
let rec l = a::b::c::l in
l
cycle 1 2 3
生成递归列表1, 2, 3, 1...
但是,如何在另一个常规列表的基础上生成递归列表?
let cycle lst = ...
用法
cycle [1;2;3]
发布于 2013-10-18 20:02:56
在像ML这样的热切的语言中,您需要使用流。例如
# let cycle = Stream.from (fun n -> Some (List.nth [1;2;3] (n mod 3)));;
val cycle : int Stream.t = <abstr>
# Stream.npeek 10 cycle;;
- : int list = [1; 2; 3; 1; 2; 3; 1; 2; 3; 1]
发布于 2013-10-18 19:48:41
据我所见,OCaml不适合这种编码,除非您想深入到语言的不安全部分。
坚持语言的安全部分(但使用来自第7章的扩展),这里有一个(不太令人印象深刻的) cycle
版本,它适用于长度为3的列表:
let cycle = function
| [] -> []
| [x] -> let rec res = x :: res in res
| [x; y] -> let rec res = x :: q and q = y :: res in res
| [x; y; z] -> let rec res = x :: t and t = y :: v and v = z :: res in res
| _ -> failwith "list too long"
很容易看出如何将其扩展到任何所需的固定长度,而不是任意长度。
下面是一个函数的会话:
# #use "cyc.ml";;
val cycle : 'a list -> 'a list = <fun>
# cycle [1;2;3];;
- : int list =
[1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1;
2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2;
3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3;
1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1;
2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2;
3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; ...]
无论如何,这是我能做的最好的了。希望能帮上忙。
发布于 2013-10-18 21:02:48
您也可以这样定义它。
# let cycle items =
let buf = ref [] in
let rec next i =
if !buf = [] then buf := items;
match !buf with
| h :: t -> (buf := t; Some h)
| [] -> None in
Stream.from next;;
val cycle : 'a list -> 'a Stream.t = <fun>
utop # let test = cycle [1; 2; 3];;
val test : int Stream.t = <abstr>
utop # Stream.npeek 10 test;;
- : int list = [1; 2; 3; 1; 2; 3; 1; 2; 3; 1]
这是因为:
http://ocaml.org/tutorials/streams.html
https://stackoverflow.com/questions/19457414
复制相似问题