Создание составного итератора в F # - PullRequest
5 голосов
/ 22 февраля 2011

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

У меня есть следующая функция, прямо переведенная с C #:

seq {
    for y1 = 0 to BOARDSIZE-1 do
        for x1 = 0 to BOARDSIZE-1 do
             for dy = -2 to 2 do
                 for dx = -2 to 2 do
                     let x2 = x1 + dx;
                     let y2 = y1 + dy;
                     let currentMove = new MoveStruct(x1, y1, x2, y2);
                     if (currentMove.SomeCondition = true) then
                             yield currentMove;
   }

Это работает, но это неловко, и не совсем "путь F #", не говоря уже о том, что у меня есть скрытое подозрение, что то, что я делаю здесь, не является оптимальным по производительности.

Что бы я хотелнапример, «сгладить это» во что-то, что использует комбинацию «итерации по всем ячейкам», «итерации по всем допустимым шагам из этой ячейки».

А вот функции, которые я надеюсь объединить:

let AllCells =
    seq {
        for y=0 to BOARDSIZE-1 do
            for x=0 to BOARDSIZE-1 do
                yield (x,y);
    };

И

let LegalMovesAround(x1,y1) = 
    seq {
      if board.[x1, y1] = WHITE then
        for dy = -2 to 2 do
          for dx = -2 to 2 do
                let x2 = x1 + dx;
                let y2 = y1 + dy;
                let currentMove = new MoveStruct(x1, y1, x2, y2);
                if (currentMove.DetermineMoveType <> MoveType.ILLEGAL 
                    && board.[x2, y2] = NONE) then
                        yield currentMove;
     }

Я собираюсь рассказать вам о моих различных попытках заставить его работать, потому что ни один из них не был успешным.Но, короче говоря, лучшее, что я мог бы придумать, это итератор, который возвращает seq с каждым выходом, а не уплощенную версию, которую я ищу, которая возвращает простой MoveStruct.

У кого-нибудь есть хорошая идея, как объединить AllCells и LegalMovesAround (x, y)?

С уважением, Алекс

Ответы [ 3 ]

3 голосов
/ 22 февраля 2011

Вы можете использовать доходность!в новом выражении последовательности:

let allLegalMoves = seq {
  for cell in AllCells do
    yield! LegalMovesAround cell
}
3 голосов
/ 22 февраля 2011

Вам известно о yield!?

что-то вроде

seq {
    for x,y in Allcells do
        yield! LMA(x,y)
}
1 голос
/ 22 февраля 2011

Вы должны быть в состоянии объединить их такими, какие они есть, а затем сгладить, что-то вроде этого:

 let validMoves = 
    AllCells 
    |> Seq.collect LegalMovesAround
    |> Seq.distinct

Возможно, это не лучшее решение с точки зрения производительности.

РЕДАКТИРОВАТЬ: Исправлен пример кода в соответствии с комментарием Томаса

...