F# 避免使用Option.Value
我有这样一种类型:F# 避免使用Option.Value,f#,idioms,F#,Idioms,我有这样一种类型: type TaskRow = { RowIndex : int TaskId : string Task : Task option } 函数返回要进一步处理的这些记录的列表。执行该处理的某些函数仅与TaskRow项目相关,其中Task是Some。我想知道最好的办法是什么 天真的做法是这样做的 let taskRowsWithTasks = taskRows |> Seq.filter (fun row
type TaskRow =
{
RowIndex : int
TaskId : string
Task : Task option
}
函数返回要进一步处理的这些记录的列表。执行该处理的某些函数仅与TaskRow
项目相关,其中Task
是Some
。我想知道最好的办法是什么
天真的做法是这样做的
let taskRowsWithTasks = taskRows |> Seq.filter (fun row -> Option.isSome row.Task)
并将其传递给这些函数,只需假设Task
永远不会是None
,然后使用Task.Value
,如果我不传递一个特殊列表,就有可能出现NRE。这正是当前的C代码所做的,但对于F代码来说,这似乎有点不符合实际。我不应该“假设”事情,而是让编译器告诉我什么是可行的
更具“功能性”的做法是,每次值相关时进行模式匹配,然后对None
不执行/不返回任何操作(并使用choose
或类似操作),但这似乎是重复和浪费的,因为同一项工作会重复多次
另一个想法是引入第二种稍微不同的类型:
type TaskRowWithTask =
{
RowIndex : int
TaskId : string
Task : Task
}
然后,原始列表将被过滤到这种类型的“子列表”中,以便在适当的情况下使用。我想从功能的角度来看这是可以的,但我想知道是否有一种更好的、惯用的方式,而不必求助于这种“助手类型”
谢谢你的指点 我同意你的观点,更“纯功能”的方法是重复模式匹配,我的意思是使用带有
Seq的函数。选择进行过滤的
,而不是将其保存到另一个结构中
let tasks = Seq.choose (fun {Task = t} -> t) taskRows
问题在于性能,因为它会被多次计算,但您可以使用
Seq.cache
,这样在后台它会被保存到一个中间结构中,同时让您的代码看起来更“纯功能化”。知道任务已经被过滤,这有很大的价值,因此,有两种不同的类型可能会有所帮助。而不是定义两种不同类型(在F中,这不是很大的交易),也可以考虑定义一个通用的<代码>行< /代码>类型:
type Row<'a> = {
RowIndex : int
TaskId : string
Item : 'a }
如果初始
taskRows
值的类型为seq
,则生成的taskRowsWithTasks
序列的类型为seq为什么不seq。选择project
而不是map
+选择id
?是的,确实如此,为什么不呢?因为我没有想到它,这就是为什么,但显然,它更简单:)
let project = function
| { RowIndex = ridx; TaskId = tid; Item = Some t } ->
Some { RowIndex = ridx; TaskId = tid; Item = t }
| _ -> None
let taskRowsWithTasks =
taskRows
|> Seq.map project
|> Seq.choose id