F# でサード パーティ ベンダーの API を使用しています。初期化時に、API はネストされた msg コンテナーである C# オブジェクトを返します。ステータス メッセージが入力され、エラー メッセージが含まれる場合があります。ベンダーは、私が F# に移植した C# のサンプル解析ルーチンを提供しています。
コード サンプルは、入れ子になった msg コンテナーをループして致命的エラーと致命的でないエラーを抽出し、次のタイプのタプルのリストを返します。BBResponseType * string
応答列挙:
type BBResponseType =
| Status = 0
| Data = 1
| Error = 2
| FatalError = -1
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
完成した後、それを見て、「うわー、F# でコードを書いているのと同じくらい機能しない」と思いました。
C# バージョンよりもはるかに明確で簡潔に見えますが、多くのループや if/then を使用せずにこれらすべてを行うためのより良い方法があるに違いないと考えていました。
パターン マッチングと再帰を使用して、これらのネストされた構造をより適切に解析するにはどうすればよいでしょうか?