0

I'm parsing a string separated by newlines. For that, I have:

for line in str.Split([|Environment.NewLine|], StringSplitOptions.None) do

which gives me each line fine. What I'd like to do is take line and, if it starts with a certain string, add the remainder to a dictionary with the starting string as the key. Essentially, I want to implement the following logic in F#:

if line equals "[end]" then
    break
else if line startsWith "string1" then
    add the rest of line to a dictionary with the key "string1"
else if line startsWith "string2" then
    add the rest of line to a dictionary with the key "string2"
else
    continue

From what I've found, I should use a match..with statement to do this instead of transliterating that to F#, along the lines of this.

So far I have:

open System
open System.IO
open System.Collections.Generic

let str =
    "Some string that
    spans multiple lines
    with prefixes
    [end]"

let (|Prefix|_|) (p:string) (s:string) =
    if s.StartsWith(p) then
        Some(s.Substring(p.Length))
    else
        None

let dict = new Dictionary<string, string>();

for line in str.Split([|Environment.NewLine|], StringSplitOptions.None) do
    match line with
    | Prefix "[end]" -> dict                         // stop searching
    | Prefix "spans" rest -> dict.Add("spans", rest) // add to dictionary
    | _ -> ()                                        // continue searching

Which gives me the following error, which I'm not sure how to handle:

test.fs(20,5): error FS0001: Type mismatch.
Expecting a string -> 'a option but given a string -> string -> string option    
The type ''a option' does not match the type 'string -> string option'

I'm using MonoDevelop/the open source F# compiler if that matters for anything, but I don't think it would.

Community
  • 1
  • 1
ipavl
  • 828
  • 11
  • 20

1 Answers1

2

So there were a few mistakes that I fixed:

The string literal should be

let str =
    "Some string that
spans multiple lines
with prefixes
[end]"

or otherwise you get some spaces at the start of each line that you don't want

The match should look like

for line in str.Split([|Environment.NewLine|], StringSplitOptions.None) do
    match line with
    | Prefix "[end]" rest -> ()          
    | Prefix "spans" rest -> dict.Add("spans", rest) 
    | _ -> ()     

Here, F# doesn't really have something like break so I have left the first and last cases doing nothing. I think this should do what you want.

John Palmer
  • 25,356
  • 3
  • 48
  • 67
  • Thank you, that works. The `str` bit was just from me making a simplified example, but I'm sure I'd make that mistake at some point in actual code so I'll keep that in mind. – ipavl Oct 15 '14 at 02:59