Dan*_*iel 16 f# idioms sequence
我需要一个类似的函数Seq.head,但是None当序列为空时返回而不是抛出异常,即seq<'T> -> 'T option.
有很多方法可以做到这一点.这里有几个:
let items = Seq.init 10 id
let a = Seq.tryFind (fun _ -> true) items
let b = Seq.tryPick Some items
let c = if Seq.isEmpty items then None else Some (Seq.head items)
let d =
use e = items.GetEnumerator()
if e.MoveNext() then Some e.Current
else None
Run Code Online (Sandbox Code Playgroud)
b是我使用的那个.两个问题:
Seq.tryHead函数,这是否表明这不是必需的,是不常见的,或者在没有函数的情况下更好地实现?tryHead已添加到F#4.0的标准库中.
Ste*_*sen 14
我认为(b)可能是最惯用的,因为@Ramon给出了同样的原因.
我认为缺乏Seq.tryHead只是意味着它并不常见.
我不确定,但我的猜测是,一般来说,使用Hindley-Milner类型推断的函数式语言在集合类型上实现这些特定函数时很少,因为重载不可用,并且可以简洁地组成高阶函数.
例如,C#Linq扩展比F#Seq模块中的函数更详尽(它本身比具体集合类型上的函数更详尽),甚至有IEnumerable.FirstOrDefault.实际上每个重载都有一个变量,它执行一个map.
我认为强调模式匹配和具体类型list也是一个原因.
现在,上面的大部分都是猜测,但我想我可能有一个更接近客观的概念.我想了很多的时间tryPick和tryFind可以在第一时间被用来代替filter |> tryHead.例如,我发现自己经常编写如下代码:
open System.Reflection
let ty = typeof<System.String> //suppose this type is actually unknown at compile time
seq {
for name in ["a";"b";"c"] do
yield ty.GetMethod(name)
} |> Seq.tryFind((<>)null)
Run Code Online (Sandbox Code Playgroud)
而不是像
...
seq {
for name in ["a";"b";"c"] do
match ty.GetMethod(name) with
| null -> ()
| mi -> yield mi
} |> tryHead
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4412 次 |
| 最近记录: |