Its possible to create infinite, circular lists using let rec, without needing to resort to mutable references:
let rec xs = 1 :: 0 :: xs ;;
But can I use this same technique to write a function that receives a finite list and returns an infinite, circular version of it? I tried writing
let rec cycle xs =
let rec result = go xs and
go = function
| [] -> result
| (y::ys) -> y :: go ys in
result
;;
But got the following error
Error: This kind of expression is not allowed as right-hand side of `let rec'
Your code has two problems:
result = go xs
is in illegal form for let rec
The above code is rejected by the compiler because you cannot write an expression which may cause recursive computation in the right-hand side of let rec
(see Limitations of let rec in OCaml).
Even if you fix the issue you still have a problem: cycle
does not finish the job:
let rec cycle xs =
let rec go = function
| [] -> go xs
| y::ys -> y :: g ys
in
go xs;;
cycle [1;2];;
cycle [1;2]
fails due to stack overflow.
In OCaml, let rec
can define a looped structure only when its definition is "static" and does not perform any computation. let rec xs = 1 :: 0 :: xs
is such an example: (::)
is not a function but a constructor, which purely constructs the data structure. On the other hand, cycle
performs some code execution to dynamically create a structure and it is infinite. I am afraid that you cannot write a function like cycle
in OCaml.
If you want to introduce some loops in data like cycle
in OCaml, what you can do is using lazy structure to prevent immediate infinite loops like Haskell's lazy list, or use mutation to make a loop by a substitution. OCaml's list is not lazy nor mutable, therefore you cannot write a function dynamically constructs looped lists.