Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursively unpack list into elements

I have a list and would like to return each element from it individually. Basically like popping from a stack. For example:

let rnd = new System.Random()
let rnds = List.init 10 (fun _ -> rnd.Next(100))
List.iter (fun x -> printfn "%A"x ) rnds

However instead of iterating, I would actually like to return each integer one after the other until the list is empty. So basically something along the lines of:

List.head(rnds)
List.head(List.tail(rnds))
List.head(List.tail(List.tail(rnds)))
List.head(List.tail(List.tail(List.tail(List.tail(rnds)))))

Unfortunately my attempts at a recursive solution or even better something using fold or scan were unsuccessful. For example this just returns the list (same as map).

let pop3 (rnds:int list) =
    let rec pop3' rnds acc =
        match rnds with
        | head :: tail -> List.tail(tail)
        | [] -> acc
    pop3' [] rnds
like image 424
s952163 Avatar asked Mar 13 '23 04:03

s952163


1 Answers

Would uncons do what you need?

let uncons = function h::t -> Some (h, t) | [] -> None

You can use it to 'pop' the head of a list:

> rnds |> uncons;;
val it : (int * int list) option =
  Some (66, [17; 93; 33; 17; 21; 1; 49; 5; 96])

You can repeat this:

> rnds |> uncons |> Option.bind (snd >> uncons);;
val it : (int * int list) option = Some (17, [93; 33; 17; 21; 1; 49; 5; 96])
> rnds |> uncons |> Option.bind (snd >> uncons) |> Option.bind (snd >> uncons);;
val it : (int * int list) option = Some (93, [33; 17; 21; 1; 49; 5; 96])
like image 132
Mark Seemann Avatar answered Mar 24 '23 03:03

Mark Seemann