Re: [F#] seq и IEnumerator
От: mryau Россия http://woodland.ru/~wjdogs
Дата: 20.07.09 20:05
Оценка: 4 (1)
Здравствуйте, Anton V. Kolotaev, Вы писали:

AVK>Господа, есть ли способ избавиться от явного использования IEnumerator в следующем коде преобразования потока лексем в дерево?

Если трактовать входной поток как Seq, то нет такого способа т.к. не определён оператор доступа к хвосту.

На List (и совместимо с OCaml):
let parse src = 
   let rec iter = function
     | (0, label)::tl ->
        tl, Node(label, [])
     | (count, label)::tl ->
        let tl, sons = at_lvl [] tl count
        tl, Node(label, List.rev sons)
     |[] -> failwith "enumeration finished"
   and at_lvl res lst = function
       | 0 -> lst, res
       | n ->
          let tl, node = iter lst
          at_lvl (node::res) tl (n-1)
   and aux acc lst =
     match iter lst with
       | [],r -> List.rev (r::acc)
       | tl,r -> aux (r::acc) tl
   aux [] src

printfn "%A" (parse [(2,"root");(0,"A");(2,"B");(0,"B1");(0,"B2")])


P.S. Если везде на выходе нужны списки, а не последовательности, то вместо seq {for ... yield ...} |> Seq.to_list можно просто использовать [for ... yield ...]

AVK>
AVK>#light

AVK>type Dest = | Node of string * list<Dest>

AVK>let incremented(it : System.Collections.Generic.IEnumerator<'a>) = 
   
AVK>   if it.MoveNext() then it else failwith "enumeration finished"

AVK>let parse(src : seq<int * string>) : seq<Dest> = 
   
AVK>   let rec impl (it : System.Collections.Generic.IEnumerator<int * string>) : Dest = 
      
AVK>      let (count, label) = it.Current
AVK>      Node(label, seq { for i in 0 .. count-1 -> impl(incremented(it)) } |> Seq.to_list)
   
AVK>   seq {   
AVK>      let it = src.GetEnumerator()
      
AVK>      while it.MoveNext() do
AVK>         yield impl it
AVK>   }
    
AVK>let input = [(2,"root");(0,"A");(2,"B");(0,"B1");(0,"B2")]

AVK>let output = input |> parse |> Seq.to_list

AVK>output |> any_to_string |>System.Console.WriteLine
AVK>
f#
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.