Blank Sequence Match

I am learning F # and I started playing with both sequences and expressions match.

I am writing a web scraper that scans HTML similar to the following and take the last URL in the parent <span>with the class paging.

<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>

My attempt to get the last url is as follows:

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")

However, I run into problems when the class I'm looking for is missing from the page. In particular, I get ArgumentExceptions with the message:Additional information: The input sequence was empty.

My first thought was to create another function that matched empty sequences and returned an empty string if the class was pagingnot found on the page.

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

, Seq.Empty . [] , : ?

+4
4

, 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"

F # interactive, "empty".

+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")

ildjarn , if...then...else .

+9

Based on the answer from @rmunn, you can make a more general sequence equality equation.

let (|Seq|_|) test input =
    if Seq.compareWith Operators.compare input test = 0
        then Some ()
        else None

match [] with
| Seq [] -> "empty"
| _ -> "not empty"
+2
source

Use point of protection

match myseq with
| s when Seq.isEmpty s -> "empty"
| _ -> "not empty"
0
source

Source: https://habr.com/ru/post/1650971/


All Articles