Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FSharp - Unexpected behaviour with match and returning records based on array

Tags:

f#

I'm just really getting into FSharp and I've been struggling with this for quite a while because I cannot understand why I'm not getting my expected results on the match statement.

Based on the message number, I need to match certain values in the array (splits) to fields on the record that I want to return.

let UNMATCHED = "UNMATCHED"
let T0200 = "T0200" ;; let R0200 = "R0200"

let matchTypes = [| { MessageType = T0200; Regex = REGEX_T0200 }
                ; { MessageType = R0200; Regex = REGEX_R0200 }
...

let messageInfo (matchType:MatchType, line:string) =
    let matching = Regex.Match(line, REGEX_DATA)
    let splits = matching.Value.Replace("[","").Replace("]","").Split('|')
    let showSplit (x:string[]) = "[" + String.Join(";",x) + "]"
    let info =
        Console.WriteLine("matching against: " + matchType.MessageType)
        match matchType.MessageType with
            | T0200 -> 
                { MessageType = T0200; CustomerID = splits.[1]; CustomerName = "";
                        ItemID = splits.[2]; ItemDescription = "" }
            | R0200 ->
                { MessageType = R0200; CustomerID = splits.[1]; CustomerName = splits.[2];
                        ItemID = splits.[5]; ItemDescription = splits.[6] }
            ...
            | UNMATCHED ->  { MessageType = UNMATCHED; CustomerID = ""; CustomerName = "";
                        ItemID = ""; ItemDescription = "" }
            | _ ->  { MessageType = UNMATCHED; CustomerID = ""; CustomerName = "";
                        ItemID = ""; ItemDescription = "" }
    Console.WriteLine("messageInfo: {0}", (matchType, showSplit splits, info))
    info

However, this does not seem to work and from the output below, I get the expected result for the T0200 however for R0200 the mapping of the fields does not match to fields in the array - ie. it seems to use the same array indices as the T0200 statement. I have the exact same problem on all other subsequent messages.

matching against: T0200
messageInfo: ({MessageType = "T0200";
 Regex = "\sT0200\[([\w\s]*\|)*[\w\s]*\]";}, [3;000008757051;1401], {MessageType = "T0200";
 CustomerID = "000008757051";
 CustomerName = "";
 ItemID = "1401";
 ItemDescription = "";})
matching against: R0200
messageInfo: ({MessageType = "R0200";
 Regex = "\sR0200\[([\w\s]*\|)*[\w\s]*\]";}, [3;000008757051;Ricky Bobby;413792;0;1401;SNACKER;909;0], {MessageType = "R0200";
 CustomerID = "000008757051";
 CustomerName = "";
 ItemID = "Ricky Bobby";
 ItemDescription = "";})

I'm guessing there's something wrong the syntax on my match statement - what am I doing wrong?

I'm running on dotnet core 2.0.2 on ubuntu

Thanks

like image 645
onemorecupofcoffee Avatar asked May 16 '18 13:05

onemorecupofcoffee


1 Answers

MessageType is a string and T0200 is just a named string value. When you try to match on T0200 it's actually binding the string to T0200 and the always going into the first branch of your match. The pattern matching language doesn't allow you to match on value names like that. You can match on discriminated union cases, literal values and a few other things. See here.

like image 154
TheQuickBrownFox Avatar answered Nov 15 '22 07:11

TheQuickBrownFox