Рекурсивно распаковать список на элементы


У меня есть список, и я хотел бы вернуть каждый элемент из него по отдельности. В основном, как выскакивание из стопки. Например:

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

Однако вместо итерации я хотел бы возвращать каждое целое число одно за другим, пока список не опустеет. Так что в основном что-то вроде:

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)))))

К сожалению, мои попытки рекурсивного решения или даже лучше чего-то с помощью fold или scan оказались безуспешными. Например, это просто возвращает список (такой же, как карта).

let pop3 (rnds:int list) =
    let rec pop3' rnds acc =
        match rnds with
        | head :: tail -> List.tail(tail)
        | [] -> acc
    pop3' [] rnds
2   4   2016-02-23 10:58:05

2 ответа:

Это кажется хорошей возможностью для класса

type unpacker(l) = 
    let mutable li = l
    member x.get() = 
        match li with
        |h::t -> li<-t;h
        |_ -> failwith "nothing left to return"

Будет ли uncons делать то, что вам нужно?

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

Вы можете использовать его, чтобы " поп " глава списка:

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

Вы можете повторить это:

> 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])