与空序列匹配

Jos*_*rty 5 f# pattern-matching guard-clause seq

我正在学习F#而且我已经开始使用序列和match表达式.

我正在编写一个Web浏览器,它正在通过类似于以下内容的HTML进行查看,<span>并在paging类的父级中获取最后一个URL .

<html>
<body>
    <span class="paging">
        <a href="http://google.com">Link to Google</a>
        <a href="http://TheLinkIWant.com">The Link I want</a>
    </span>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

我尝试获取最后一个URL如下:

type AnHtmlPage = FSharp.Data.HtmlProvider<"http://somesite.com">

let findMaxPageNumber (page:AnHtmlPage)= 
    page.Html.Descendants()
    |> Seq.filter(fun n -> n.HasClass("paging"))
    |> Seq.collect(fun n -> n.Descendants() |> Seq.filter(fun m -> m.HasName("a")))
    |> Seq.last
    |> fun n -> n.AttributeValue("href")
Run Code Online (Sandbox Code Playgroud)

但是,当我正在搜索的课程缺少页面时,我遇到了问题.特别是我得到带有消息的ArgumentExceptions:Additional information: The input sequence was empty.

我的第一个想法是构建另一个匹配空序列的函数,并paging在页面上找不到类时返回一个空字符串.

let findUrlOrReturnEmptyString (span:seq<HtmlNode>) =
    match span with 
    | Seq.empty -> String.Empty      // <----- This is invalid
    | span -> span
    |> Seq.collect(fun (n:HtmlNode) -> n.Descendants() |> Seq.filter(fun m -> m.HasName("a")))
    |> Seq.last
    |> fun n -> n.AttributeValue("href")

let findMaxPageNumber (page:AnHtmlPage)= 
    page.Html.Descendants()
    |> Seq.filter(fun n -> n.HasClass("paging"))
    |> findUrlOrReturnEmptyStrin
Run Code Online (Sandbox Code Playgroud)

我的问题是,现在Seq.Empty不是文字,不能用于模式.大多数具有模式匹配的示例[]在其模式中指定空列表,因此我想知道:我如何使用类似的方法并匹配空序列?

rmu*_*unn 10

ildjarn在评论中给出的建议很好:如果您认为使用match会创建更易读的代码,那么创建一个活动模式来检查空seqs:

let (|EmptySeq|_|) a = if Seq.isEmpty a then Some () else None

let s0 = Seq.empty<int>

match s0 with
| EmptySeq -> "empty"
| _ -> "not empty"
Run Code Online (Sandbox Code Playgroud)

在F#interactive中运行它,结果将是"empty".


Tea*_*Dev 9

您可以使用when警卫进一步限定案件:

match span with 
| sequence when Seq.isEmpty sequence -> String.Empty
| span -> span
|> Seq.collect(fun (n:HtmlNode) -> n.Descendants() |> Seq.filter(fun m -> m.HasName("a")))
|> Seq.last
|> fun n -> n.AttributeValue("href")
Run Code Online (Sandbox Code Playgroud)

ildjarn是正确的,在这种情况下,if...then...else可能是更可读的替代方案.


Ily*_*mov 5

使用保护子句

match myseq with
| s when Seq.isEmpty s -> "empty"
| _ -> "not empty"
Run Code Online (Sandbox Code Playgroud)