Выбор между пониманиями и функциями более высокого порядка в основном зависит от стиля.Я думаю, что понимание иногда более читабельно, но это всего лишь личное предпочтение.Обратите внимание, что функция cartesian
может быть написана более элегантно, например:
let rec cartesian = function
| [] -> [[]]
| L::Ls ->
[ for C in cartesian Ls do for x in L do yield x::C ]
Интересный случай - при написании рекурсивных функций.Если вы используете последовательности (и их понимание), они удаляют ненужное распределение временных списков, и если вы используете yield!
в позиции хвостового вызова, вы также можете избежать исключений переполнения стека:
let rec nums n =
if n = 100000 then []
else n::(nums (n+1))
// throws StackOverflowException
nums 0
let rec nums n = seq {
if n < 100000 then
yield n
yield! nums (n+1) }
// works just fine
nums 0 |> List.ofSeq
Этоэто довольно интересный шаблон, потому что он не может быть написан таким же образом, используя списки.При использовании списков вы не можете вернуть какой-либо элемент, а затем выполнить рекурсивный вызов, поскольку он соответствует n::(nums ...)
, что не является хвостовой рекурсией.