Seq头尾

时间:2011-01-09 21:59:21

标签: f#

是否有单行方式来实施nextLine

let s = ref seqOfLines
let nextLine() =
  let hd = Seq.head !s
  s := Seq.skip 1 !s
  hd

seqOfLines被认为是无限的

3 个答案:

答案 0 :(得分:4)

执行此操作的一种方法是使用基础IEnumerator<String>。它不是一个单行,但它似乎比你的实现更清洁。 (不依赖于mutable,正确使用.NET习语。)

基本上你从序列中得到IEnumerator<'a>接口,然后循环调用MoveNext。这将在无限序列上正常工作。

> let getNextFunc (seqOfLines : seq<'a>) =               
-     let linesIE : IEnumerator<'a> = seqOfLines.GetEnumerator()
-     (fun () -> ignore (linesIE.MoveNext()); linesIE.Current);;

val getNextFunc : seq<'a> -> (unit -> 'a)

要使用,只需传递getNextFunc一个序列,它将返回你的nextLine函数。

> let sequenceOfStrings = seq { for i = 0 to 10000 do yield i.ToString() };;

val sequenceOfStrings : seq<string>

> let nextLine = getNextFunc sequenceOfStrings;;  

val nextLine : (unit -> string)

> nextLine();;
val it : string = "0"
> nextLine();;
val it : string = "1"
> nextLine();;
val it : string = "2"
> nextLine();;
val it : string = "3"

答案 1 :(得分:2)

嗯,我认为你是在试图解决这个问题,因此,你最终会编写一些时髦的代码并失去函数编程的好处。

您可以通过重写函数来获益,因此需要current state并返回value * next state。这将使您的功能保持纯粹功能。您也可能会发现将无限seq转换为LazyList更容易(您需要为此引用F#PowerPack),因此您无需直接触及基础枚举器:

> open LazyList
let seqOfLines = Seq.initInfinite (fun i -> i) |> LazyList.ofSeq
let nextLine = function Cons(x, xs) -> x, xs | Nil -> failwith "Empty list";;

val seqOfLines : LazyList<int>
val nextLine : LazyList<'a> -> 'a * LazyList<'a>

> nextLine seqOfLines;;
val it : int * LazyList<int> = (0, seq [1; 2; 3; 4; ...])
> nextLine (snd it);;
val it : int * LazyList<int> = (1, seq [2; 3; 4; 5; ...])
> nextLine (snd it);;
val it : int * LazyList<int> = (2, seq [3; 4; 5; 6; ...])
> nextLine (snd it);;
val it : int * LazyList<int> = (3, seq [4; 5; 6; 7; ...])

答案 2 :(得分:0)

FSharpx.Collections有一些有用/有效的函数,如Seq.tail,Seq.Head和Seq.UnCons,如果你想将Seq分解为头尾,可能会有用。