F#模式匹配和递归vs循环&if..then用于解析嵌套结构

And*_* P. 3 recursion f# pattern-matching nested-loops c#-to-f#

我在F#中使用第三方供应商的API.在初始化时,API返回一个嵌套的msg容器的C#对象.它填充了状态消息,可能包含错误消息.供应商提供了一个C#样本解析例程,我已经移植了F#.

代码示例循环通过嵌套的msg容器提取致命和非致命错误,然后返回类型的元组列表 BBResponseType * string

回复枚举:

type BBResponseType =
    | Status = 0
    | Data = 1
    | Error = 2
    | FatalError = -1 
Run Code Online (Sandbox Code Playgroud)

我到F#的端口看起来像这样:

 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
Run Code Online (Sandbox Code Playgroud)

在我完成它之后,我看着它,并想:"哇,这就像你可以得到的那样无功能,仍然在F#中编码."

它看起来比C#版本更清晰简洁,但我认为必须有更好的方法来完成所有这些而不使用如此多的循环和if/then's.

如何使用模式匹配和递归来更好地解析这些嵌套结构?

Ank*_*kur 5

几个指针:

  1. 而不是返回元组列表返回一个元组的seq - 使用seq { }计算表达式来创建序列.
  2. 将if/else部分提取为类型的函数,Message -> (BBResponseType * string)并在seq表达式中使用此函数
  3. 在这个新函数(将Message转换为元组)中使用模式匹配来确定要返回的是什么类型的(BBResponseType*字符串).