I have this list in C#:
List<string> words = new List<string> { "how", "are", "you" };
I can easily print the content of the list with:
foreach(string word in words)
Debug.WriteLine(word);
Now I want to do the same in F# (I understand from over here that a List<T>
is similar to a ResizeArray):
let words = ResizeArray<string>()
words.Add("how")
words.Add("are")
words.Add("you")
for word in words do
Debug.WriteLine(sprintf "%s" word)
Now the problem is, that in the for-loop word
becomes null. What am I doing wrong here?
EDIT: Here is the full code. I have changed it to printf as suggested. Unfortunately I still get null in word when inside the for-loop:
let myFunction =
let words = ResizeArray<string>()
words.Add("how")
words.Add("are")
words.Add("you")
for word in words do
printf "%s" word // <-- word becomes null
words
[<EntryPoint>]
let main argv =
ignore myFunction
0 // return an integer exit code
I suspect this is due to the lazy evaluating nature of F#. So, word
is not actually assigned till it is used by the printf
statement, and hence you cannot see the value in the debugger.
If you add another statement in your loop and set a breakpoint there, you will see the value of assigned value of word
. See the snippet below -
let myFunction =
let words = ResizeArray<string>()
words.Add("how")
words.Add("are")
words.Add("you")
for word in words do
printf "%s" word //
printf "%s" word // <-- SET A BREAKPOINT HERE AND VERIFY THE VALUE OF 'word'
words
I understand you want your code to look like C#. But F# is a functional language (not strictly, but that's main paradigm) and in these features lies the power of the language. First your collection. A more idiomatic type is a List. It's immutable which is one of the functional features of the language.
let words = ["how"; "are"; "you"]
Since it's immutable you expand it by creating a new collection. You can append an item at the beginning:
let moreWords = "Hello" :: words
or join one list with another one:
let evenMore = moreWords @ ["I"; "am"; "fine"]
Then iterating. For loop is purely imperative construct. Since we switched to a functional collection use one of the built-in List functions to iterate:
let prnt lst = lst |> List.iter (fun x -> printfn "%s" x)
This takes a list. Iterates it item by item. And executes the (fun x -> printfn "%s" x)
function on each item.
Or you can play a bit and write your own function to go through all the elements and execute a function on each of them. One approach would be to use recursion and list matching:
let rec loopFn lst fn =
match lst with
| [] -> fn
| head::tail ->
fn head
loopFn tail fn
This funciton takes a list and another function as arguments. Matches the list. If it's empty (| []
) - performs the function. Otherwise splits the list to head and the rest (head::tail
) executes the function on the head
(fn head
) and loops further on the remaining items (loopFn tail fn
).
To print the items pass to the function the list of words and a print function:
loopFn words (fun x -> printfn "%s" x)
or since printfn
is a function itself you can simplify the call a bit:
loopFn words (printfn "%s")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With