Я пытаюсь выучить F #, переписав некоторые алгоритмы C #, которые у меня есть, в идиоматический F #.
Одной из первых функций, которые я пытаюсь переписать, является пакетное исполнение, где:
[1..17] |> batchesOf 5
, которое разделит последовательность на пакеты с максимум пятью в каждой, то есть:
[[1; 2; 3; 4; 5]; [6; 7; 8; 9; 10]; [11; 12; 13; 14; 15]; [16; 17]]
Моя первая попытка сделать это несколько уродлива, когда я прибегнул к использованию изменяемого объекта ref после того, как столкнулся с ошибками, пытаясь использовать внутри типа mutable закрытиеИспользование ref особенно неприятно, поскольку для разыменования его необходимо использовать оператор ! , который в выражении условия может быть противоречащим интуиции для некоторых разработчиков, которые будут читать его как логическийне .Другая проблема, с которой я столкнулся, заключается в том, что Seq.skip и Seq.take не похожи на псевдонимы Linq, поскольку выдают ошибку, если size превышает размер последовательности.
let batchesOf size (sequence: _ seq) : _ list seq =
seq {
let s = ref sequence
while not (!s |> Seq.isEmpty) do
yield !s |> Seq.truncate size |> List.ofSeq
s := System.Linq.Enumerable.Skip(!s, size)
}
В любом случае, какой самый элегантный / идиоматичный способ переписать это на F #?Сохранение исходного поведения, но желательно без изменяемой переменной ref .