Здравствуйте, 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>
Господа, есть ли способ избавиться от явного использования IEnumerator в следующем коде преобразования потока лексем в дерево?
#light
type Dest = | Node of string * list<Dest>
let incremented(it : System.Collections.Generic.IEnumerator<'a>) =
if it.MoveNext() then it else failwith "enumeration finished"
let parse(src : seq<int * string>) : seq<Dest> =
let rec impl (it : System.Collections.Generic.IEnumerator<int * string>) : Dest =
let (count, label) = it.Current
Node(label, seq { for i in 0 .. count-1 -> impl(incremented(it)) } |> Seq.to_list)
seq {
let it = src.GetEnumerator()
while it.MoveNext() do
yield impl it
}
let input = [(2,"root");(0,"A");(2,"B");(0,"B1");(0,"B2")]
let output = input |> parse |> Seq.to_list
output |> any_to_string |>System.Console.WriteLine