Неправильный автомат.
От: Klapaucius  
Дата: 12.05.07 16:03
Оценка:
Нижеследующий код выполняет, в двух словах, следующую работу: последовательность элементов преобразует в другую последовательность, которая состоит из элементов отвечающих некоторому условию и заданного кол-ва соседствующих с ними элементов.
Данный код компилируется без вопросов, с одним единственным предупреждением, касающимся матчинга (переписывание матчинга так, чтобы предупреждение исчезло ничего не меняет, так что к делу не относится.), но получившийся автомат не работает, выбрасывая исключение в рантайм.

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
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.