Если вы хотите, чтобы функция возвращала null
(или значение по умолчанию для типов значений), когда последовательность пуста, просто вызовите существующий метод SingleOrDefault
.Вы можете вызывать методы C # из F # просто отлично.Имейте в виду, однако, что большинство собственных типов F # не допускают нулевых значений, поэтому это не всегда возможно.
Если вы хотите, чтобы ваша функция возвращала тип параметра, возвращаясь к None
, когда последовательностьсодержит ноль элементов или более одного, вы можете использовать Seq.truncate
для усечения до первых двух элементов:
let singleOrDefault s =
match s |> Seq.truncate 2 |> Seq.toList with
| [x] -> Some x
| _ -> None
или аналогично для перегрузки, которая также принимает предикат:
let singleOrDefaultP pred s =
match s |> Seq.filter pred |> Seq.truncate 2 |> Seq.toList with
| [x] -> Some x
| _ -> None
Если вы предпочитаете использовать обе версии, возможно, имеет смысл выразить одну в терминах другой, чтобы сохранить вещи СУХИМЫМИ:
let singleOrDefault s = singleOrDefaultP (fun _ -> true) s
Преимущество этого решения по сравнению с использованием дополнительной проверки Seq.isEmpty
заключается в том, чтопоследовательность оценивается только один раз и только так, как нужно.
Кстати, это именно то, что делает реализация по умолчанию SingleOrDefault
.
Такжеобратите внимание, что это решение вернет None
, когда последовательность содержит более одного элемента, вместо того, чтобы выдавать исключение, как это делает оригинал.Это предпочтительный, идиоматический способ борьбы с ошибками в F #.Однако, если вы предпочитаете оригинальный способ, это может быть легко достигнуто путем добавления к совпадению еще одного случая:
let singleOrDefault s =
match s |> Seq.truncate 2 |> Seq.toList with
| [x] -> Some x
| [_;_] -> failWith "Too many" // replace with your favourite exception
| _ -> None