Нижеследующий код выполняет, в двух словах, следующую работу: последовательность элементов преобразует в другую последовательность, которая состоит из элементов отвечающих некоторому условию и заданного кол-ва соседствующих с ними элементов.
Данный код компилируется без вопросов, с одним единственным предупреждением, касающимся матчинга (переписывание матчинга так, чтобы предупреждение исчезло ничего не меняет, так что к делу не относится.), но получившийся автомат не работает, выбрасывая исключение в рантайм.
using System;
using System.Console;
using Nemerle.Utility;
using System.Collections.Generic;
module Program
{
private variant ST
{
| Scan
| Lead
| Gold
| BuffOut {count : int;}
| GoldOut
| LeadOut {count : int;}
}
public SelectWithTrain[T](this seq : IEnumerable[T],
predicate : T -> bool,
train : int = 5
) : IEnumerable[T]
{
def queue = Nemerle.Collections.Queue(train);
mutable state = ST.Scan();
foreach(elem in seq)
{
def loop(s : ST)
{
| Scan => loop(if(predicate(elem)) ST.Gold() else ST.Lead())
| Lead => {
when (queue.Count >= train)
_ = queue.Dequeue();
queue.Enqueue(elem);
ST.Scan()
}
| Gold => loop(ST.BuffOut(queue.Count))
| BuffOut(n) when n > 0 => {
yield queue.Dequeue();
loop(ST.BuffOut(n-1))
}
| BuffOut(0) => loop(ST.GoldOut())
| GoldOut => {
yield elem;
ST.LeadOut(train)
}
| LeadOut(n) when n > 0 => {
if (predicate(elem))
loop(ST.Gold())
else
{
yield elem;
ST.LeadOut(n-1)
}
}
| LeadOut(0) => ST.Scan()
}
state = loop(state)
}
}
Main() : void
{
def lst = [-1, 2, 3, -4, -5, -6, -7, -8, -9, -10, 11, -12, 13, 14, 15, -16];
def iter = lst.SelectWithTrain(_ > 0, 2);
// ожидаемый вывод [-1, 2, 3, -4, -5, -9, -10, 11, -12, 13, 14, 15, -16], но...
WriteLine($[x | x in iter]); // здесь возникает исключение, о котором ниже.
}
}
А вот и исключение:
System.InvalidProgramException was unhandled
Message: Common Language Runtime detected an invalid program.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll