F# return empty string in case of null

I'm trying to touch some F# language by developing a small "web crawler". I've got a functions declared like this:

let results = HtmlDocument.Load("http://joemonster.org//")

let images = 
results.Descendants ["img"]
|> Seq.map (fun x -> 

which of course should return for me a map of "src" and "alt" attributes for "img" tag. But when I'm encountering a situation when one of those are missing in the tag I'm getting an exception that TryGetAttribute is returning null. I want to change that function to return the attribute value or empty string in case of null. I've tried out answers from this ticket but with no success.

1 answer

  • answered 2018-03-11 12:46 Taylor Wood

    TryGetAttribute returns an option type, and when it is None you can't get its value—you get an exception instead. You can pattern match against the returned option value and return an empty string for the None case:

    let getAttrOrEmptyStr (elem: HtmlNode) attr =
      match elem.TryGetAttribute(attr) with
      | Some v -> v.Value()
      | None -> ""
    let images = 
      results.Descendants ["img"]
      |> Seq.map (fun x -> getAttrOrEmptyStr x "src", getAttrOrEmptyStr x "alt")

    Or a version using defaultArg and Option.map:

    let getAttrOrEmptyStr (elem: HtmlNode) attr =
      defaultArg (elem.TryGetAttribute(attr) |> Option.map (fun a -> a.Value())) ""

    Or another option now that Option.defaultValue exists, and using HtmlAttribute.value function for a terser Option.map call:

    let getAttrOrEmptyStr (elem: HtmlNode) attr =
      |> Option.map HtmlAttribute.value
      |> Option.defaultValue ""