f# - 如何在 F# 中检查值是否为空
问题描述
以这段代码为例,如何检查输入是否为空?类似的代码抛出空引用异常
let private Method ( str:string) : string =
let a = str
a.[a.Length-1]
解决方案
虽然isNull
这是一个超级简单且完全有效的答案,但我认为与其他几个人一起玩会很有趣,因为 F# 很有趣 :)
首先让我们设置一个小函数来快速测试结果
open System
let test f a =
try
printfn "Input %A, output %A" a (f a)
printfn "Input %A, output %A" "" (f "")
printfn "Input %A, output %A" null (f null)
with
| :? Exception as ex -> printfn "%s" ex.Message
我们的第一个功能只是建立一个基线。
抛出异常
//string -> string
let getLast1 ( s:string) : string = s.[s.Length-1] |> string
printfn "=== getLast1 ==="
test getLast1 "bing"
=== getLast1 ===
输入“bing”,输出“g”
索引超出了数组的范围。
下一个使用 an 检查值if
,如果不是有效值,则返回空字符串。
返回空字符串
//string -> string
let getLast2 ( s:string) : string =
if (String.IsNullOrEmpty s) then ""
else s.[s.Length-1] |> string
printfn "=== getLast2 ==="
test getLast2 "bing"
=== getLast2 ===
输入“bing”,输出“g”
,输入“”,输出“”,
输入,输出“”
我们至少现在正在执行所有路径。
让我们尝试一种更实用的方法:使用模式匹配
返回option
//string -> string option
let getLast3 (s:string) =
match s with
| null -> None
| _ ->
match (s.ToCharArray()) with
| [||] -> None
| [|x|] -> Some x
| xs -> Array.tryLast xs
|> Option.map string
printfn "=== getLast3 ==="
test getLast3 "bing"
=== getLast3 ===
输入 "bing", 输出 Some "g"
输入 "", 输出 <null> //注意 <null> 实际上None
在这里。
输入<null>,输出<null> //注意<null>其实None
在这里。
这行得通,但它不是最容易阅读的功能。这不是太糟糕,但如果我们试图打破它。
组合函数
//'a -> 'a option
let sanitize x = if (isNull x) then None else Some(x)
//string -> char[]
let toCharArray (s:string) = s.ToCharArray()
//'a[] option -> 'a option
let last xs =
xs |> Option.map Array.tryLast //tryLast returns an 'a option
|> Option.flatten // turns 'a option option to a' option
现在我们有了构建块,我们可以构建新的 last 函数:
//string -> string option
let getLast4 s =
s |> sanitize
|> Option.map toCharArray
|> last
|> Option.map string
printfn "=== getLast4 ==="
test getLast4 "bing"
=== getLast4 ===
输入 "bing", 输出 Some "g"
输入 "", 输出 <null> //注意 <null> 实际上None
在这里。
Input , output <null> //注意 <null> 实际上None
在这里。
老实说getLast2
可能还好。如果我发现自己正在检查一个空字符串,我宁愿返回Some
或None
从if
. 我只是想展示如何远离null
和转向使用内置Array
函数。
推荐阅读
- java - TDengine JDBC 可以找到方法 setTimestamp()
- java - 创建我的 android 项目的 jar 或 aar 文件
- c++ - 将数据从 ECEF 参考更改为本地参考
- android - Android文本注释不会在文本中找到注释
- c++ - C++中的成员反射列表
- javascript - e参数如何知道它应该包含javascript回调函数中的事件对象的值
- flutter - 评估项目 ':spotify_sdk' 时出现问题。> 在项目 ':spotify_sdk' 中找不到路径为 ':spotify-auth' 的项目
- android - 如何在android中模拟用于单元测试的服务
- https - 如何在启用 tls 的情况下连接到 nomad/consul UI?
- git - 为什么 Git 文件/对象会损坏?