I'm using a 3rd party vendor's API in F#. On initialization the API returns a C# object that is nested msg container. It is populated with status messages and may include errors message. The vendor provides a C# sample parsing routine which I have ported F#.
The code sample loops through a nested msg container extracting fatal and nonfatal errors, and then return a List of tuples of type BBResponseType * string
Response Enum:
type BBResponseType =
    | Status = 0
    | Data = 1
    | Error = 2
    | FatalError = -1 
My port to F# looks like this:
 member private this.ProcessStatusMsg(eventObj: Blpapi.Event) = 
     let responseLst = List<(BBResponseType * string)>()
     for msg in eventObj do
         if msg.MessageType.Equals(SUBSTARTED) then
             if msg.GetElement(EXCEPTIONS).NumValues > 0 then // <- check for errors/exceptions                        
                 let e = msg.GetElement(EXCEPTIONS)
                 for i in 0..e.NumValues-1 do                                
                     let error = e.GetValueAsElement(i)
                     let field = error.GetElementAsString(FieldID)
                     let reason = error.GetElement(REASON)
                     let message = sprintf "Subscription Started w/errors( Field:   %s \n   Reason:   %s)" field (reason.GetElementAsString(DESCRIPTION))                                
                     responseLst.Add(BBResponseType.Error, message)
             else                                
                 let message = sprintf "Subscription Started"         
                 responseLst.Add(BBResponseType.Status, message)
         if msg.MessageType.Equals(SUBSCFAILURE) then // <- check for subscriptions failure
             if msg.HasElement(REASON) then
                 let reason = msg.GetElement(REASON)
                 let desc = reason.GetElementAsString(DESCRIPTION)
                 let message = sprintf "Real-time Subscription Failure:    %s" desc                            
                 responseLst.Add(BBResponseType.FatalError, message)
             else
                 let message = sprintf "Subscription Failure:  (reason unknown) "                                                
                 responseLst.Add(BBResponseType.FatalError, message)
     responseLst
After I finished it, I looked at it and thought, "Wow, that's about as non-functional as you can get and still code in F#."
It does seem a lot clearer and succinct than the C# version, but I was thinking that there must be a better way to do all this without using so many loops and if/then's.
How can I do a better job of parsing these nested structures using pattern matching and recursion?
Few pointers:
seq { } computation expression for creating sequence.Message -> (BBResponseType * string) and use this function inside the seq expressionIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With