Why can't I print this array in F #?

I have this list in C #:

List<string> words = new List<string> { "how", "are", "you" }; 

I can easily print the contents of the list with:

 foreach(string word in words) Debug.WriteLine(word); 

Now I want to do the same in F # (I understand from here that List<T> is similar to 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 for-loop word becomes null. What am I doing wrong here?

EDIT: Here is the complete code. I changed it to printf as suggested. Unfortunately, I still get a zero word when inside a 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 
+5
source share
3 answers

I suspect this is due to the lazy evaluative nature of F #. Thus, word is not actually assigned until it is used by the printf operator, and therefore you cannot see the value in the debugger.

If you add another statement to your loop and set a breakpoint there, you will see the value of the assigned word value. See 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 
+2
source

I understand that you want your code to look like C #. But F # is a functional language (not strictly, but that basic paradigm), and in these features lies the power of the language. First create your collection. A more idiomatic type is the List. It is unchanged, which is one of the functional features of the language.

 let words = ["how"; "are"; "you"] 

Since it is immutable, you expand it by creating a new collection. You can add an element at the beginning:

 let moreWords = "Hello" :: words 

or join one list with another:

 let evenMore = moreWords @ ["I"; "am"; "fine"] 

Then iteration. For a cycle is a purely imperative construct. Since we switched to the functional collection, use one of the built-in List functions to iterate:

 let prnt lst = lst |> List.iter (fun x -> printfn "%s" x) 

It will take a list. Iterates over each element. And it executes a function (fun x -> printfn "%s" x) for each element.

Or you can play a little and write your own function to go through all the elements and execute a function for each of them. One approach is 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 is empty ( | [] ) - performs a function. Otherwise, the list is divided into heads, and the rest ( head::tail ) performs the function in head ( fn head ) and then on the remaining elements ( loopFn tail fn ).

To print items, go to the function in the word list and the print function:

 loopFn words (fun x -> printfn "%s" x) 

or since printfn is the function itself, you can simplify the call a bit:

 loopFn words (printfn "%s") 
+4
source

It works:

 for word in words do printf "%s" word 

But if you really need debug output, do you load the system.diagnostics namespace?

 open System.Diagnostics (Your code) 

This worked for me without loading the namespace:

 for word in words do System.Diagnostics.Debug.Write(sprintf "%s" word) 
+2
source

All Articles