So, I am writing code to parse and IP Address expression and turn it into a regular expression that could be run against and IP Address string and return a boolean response. I wrote the code in C# (OO) and it was 110 lines of code. I am trying to compare the amount of code and the expressiveness of C# to F# (I am a C# programmer and a noob at F#). I don't want to post both the C# and F#, just because I don't want to clutter the post. If needed, I will do so.
Anyway, I will give an example. Here is an expression:
192.168.0.250,244-248,108,51,7;127.0.0.1
I would like to take that and turn it into this regular expression:
((192.168.0.(250|244|245|246|247|248|108|51|7))|(127.0.0.1))
Here are some steps I am following:
Operations:
Break by ";" 192.168.0.250,244-248,108,51,7 127.0.0.1
Break by "." 192 168 0 250,244-248,108,51,7
Break by "," 250 244-248 108 51 7
Break by "-" 244 248
I came up with F# that produces the output. I am trying to forward-pipe through my operations listed above, as I think that would be more expressive. Can anyone make this code better? Teach me something :)
open System
let createItemArray (group:bool) (y:char) (items:string[]) =
[|
let indexes = items.Length - 1
let group = indexes > 0 && group
if group then
yield "("
for i in 0 .. indexes do
yield items.[i].ToString()
if i < indexes then
yield y.ToString()
if group then
yield ")"
|]
let breakBy (group:bool) (x:string) (y:char): string[] =
x.Split(y)
|> createItemArray group y
let breakItem (x:string) (y:char): string[] = breakBy false x y
let breakGroup (x:string) (y:char): string[] = breakBy true x y
let AddressExpression address:string =
let builder = new System.Text.StringBuilder "("
breakGroup address ';'
|> Array.collect (fun octet -> breakItem octet '.')
|> Array.collect (fun options -> breakGroup options ',')
|> Array.collect (fun (ranges : string) ->
match (breakGroup ranges '-') with
| x when x.Length > 3
-> match (Int32.TryParse(x.[1]), Int32.TryParse(x.[3])) with
| ((true, a) ,(true, b))
-> [|a .. b|]
|> Array.map (int >> string)
|> createItemArray false '-'
| _ -> [|ranges|]
| _ -> [|ranges|]
)
|> Array.iter (fun item ->
match item with
| ";" -> builder.Append ")|("
| "." -> builder.Append "\."
| "," | "-" -> builder.Append "|"
| _ -> builder.Append item
|> ignore
)
builder.Append(")").ToString()
let address = "192.168.0.250,244-248,108,51,7;127.0.0.1"
AddressExpression address