Что приводит к повторному перечислению последовательности F#?

У меня есть синтаксический анализатор, который фактически представляет собой набор рекурсивных функций, работающих с последовательностью токенов лексера.

Проблема, с которой я сталкиваюсь, заключается в том, что последовательность, кажется, перезапускается с самого начала при вызовах рекурсивных функций. Учитывая следующее определение скелета для функции Parse

    let restricted = Seq.take_while token_search tokens
    let compiled_nodes = Seq.fold (fun list (next: Lexer.Token) -> list @ parse_token this restricted next) [] restricted

Функция parse_token может привести к вызову Parse.

Однако, когда это происходит, параметр tokens оказывается в начале последовательности.

Любые идеи о том, как сохранить последовательность, расположенную там, где она должна быть?

Тиа


person kolosy    schedule 02.03.2009    source источник
comment
Хах, я только что сделал то же самое. Спасибо, что задали этот вопрос, возможно, это сэкономило мне часы дальнейшей борьбы. Я тоже переписываю свой синтаксический анализатор, но вместо этого использую последовательности буферов массива байтов.   -  person Tatiana Racheva    schedule 11.05.2021


Ответы (1)


Я думаю, вам, возможно, придется опубликовать немного больший фрагмент, так как я не совсем понимаю вас.

Тем не менее, последовательность (IEnumerable) - это просто последовательность, и каждый раз, когда вы выполняете for (foreach) или Seq. Независимо от этого, она будет "повторять" последовательность. Мне неясно, что вы хотите сделать и что вы ожидаете, но для синтаксического анализа представление «токенов» в виде последовательности может быть «неправильным», поскольку вы обычно делите токены на потребляемую/зафиксированную область и область просмотра вперед.

Также обратите внимание, что вы обычно не хотите, чтобы «перебор последовательности» имел побочные эффекты.

person Brian    schedule 02.03.2009
comment
вы совершенно правы. Я понял это после того, как разместил вопрос, и понял, в чем проблема. я пытался создать эквивалент общего IEnumerator, что было неправильным подходом. Я закончил тем, что строил его по спискам, передавая неизрасходованные остатки. - person kolosy; 03.03.2009