我正在尝试将与特定(可选)关键字相关联的数据从文件读取到F#中的不可变。
当文件中存在关键字时,我的代码会执行我想要的操作:
let variable1 =
lines
|> Seq.find(fun x -> x.Contains "keyword1")
|> fun x -> x.Split(']').[1]
如果关键字不存在,Seq.find
会按预期中断。而不是使用tryFind几行,如果/然后我试图使它全部以F#方式在一行中工作,但我不知道如何处理tryFind的输出,因为后续的拆分操作需要类型字符串而不是比IsSome的未知类型。如何进一步满足红色波浪形需求的类型约束?
let variable1 =
lines
|> Seq.tryFind(fun x -> x.Contains "keyword1")
|> fun x -> if x.IsSome then x.Split(']').[1]
答案 0 :(得分:5)
如果你只是想对一场比赛采取行动,Option.map
就是你要走的路,正如ildjarn所提到的那样
let variable1 =
lines
|> Seq.tryFind(fun x -> x.Contains "keyword1")
|> Option.map (fun x -> x.Split(']')
或者,您可以使用地图/选择是否要对许多条目采取行动
let variables =
lines
|> Seq.map(fun x -> if x.Contains "keyword1" then Some x else None)
|> Seq.choose (fun x -> x.Split(']')
在任何情况下,then
表达式的每个分支else
和if .. then .. else ...
的返回类型都需要 相同类型 。
两个分支的常见类型是 整个 表达式if .. then .. else ...
的类型。这允许参考透明度,您可以随时插入一个复杂的表达式,其中接受一个更简单的表达式。
这是一个很大的自由,需要付出一点代价:你必须在两个分支中给出一个正确类型的表达式。
'例外'是你在一个计算表达式中定义了一些零,但即使在这种情况下,两个分支都提供,而不是由你...
答案 1 :(得分:4)
当你这样做时:
let variable1 =
lines
|> Seq.tryFind(fun x -> x.Contains "keyword1")
|> fun x -> if x.IsSome then x.Split(']').[1]
上一个x
的类型为string option
。我会做类似
let variable1 =
lines
|> Seq.tryFind(fun x -> x.Contains "keyword1")
|> function |Some(t) -> t.Split(']').[1] |None -> "" (*need a value for the None branch*)