Search code examples
f#sequencesseq

How to invoke the function in Seq.whatever without "printf"?


I'm new to f# and I tried to write a program supposed to go through all files in a given dir and for each file of type ".txt" to add an id number + "DONE" to the file.

my program:

//const:
[<Literal>]
let notImportantString= "blahBlah"
let mutable COUNT = 1.0

//funcs:
//addNumber --> add the sequence number COUNT to each file.
let addNumber (file : string)  =
 let mutable str = File.ReadAllText(file)
 printfn "%s" str//just for check
 let num = COUNT.ToString()
 let str4 = str + " " + num + "\n\n\n DONE"
 COUNT <- COUNT + 1.0
 let str2 =  File.WriteAllText(file,str4)
 file

//matchFunc --> check if is ".txt"
let matchFunc (file : string) =
 file.Contains(".txt") 

//allFiles --> go through all files of a given dir
let allFiles dir =

seq
    { for file in Directory.GetFiles(dir) do
        yield file  
           }

////////////////////////////

let dir = "D:\FSharpTesting"
let a = allFiles dir 
         |> Seq.filter(matchFunc) 
         |> Seq.map(addNumber)
printfn "%A" a

My question:

Tf I do not write the last line (printfn "%A" a) the files will not change.(if I DO write this line it works and change the files) when I use debugger I see that it doesn't really computes the value of 'a' when it arrives to the line if "let a =......" it continues to the printfn line and than when it "sees" the 'a' there it goes back and computes the answer of 'a'. why is it and how can i "start" the function without printing??

also- Can some one tells me why do I have to add file as a return type of the function "addNumber"? (I added this because that how it works but I don't really understand why....)

last question- if I write the COUNT variable right after the line of the [] definition it gives an error and says that a constant cannot be "mutable" but if a add (and this is why I did so) another line before (like the string) it "forgets" the mistakes and works. why that? and if you really cannot have a mutable const how can I do a static variable?


Solution

  • if I do not write the last line (printfn "%A" a) the files will not change.

    F# sequences are lazy. So to force evaluation, you can execute some operation not returning a sequence. For example, you can call Seq.iter (have side effects, return ()), Seq.length (return an int which is the length of the sequence) or Seq.toList (return a list, an eager data structure), etc.

    Can some one tells me why do I have to add file : string as a return type of the function "addNumber"?

    Method and property access don't play nice with F# type inference. The type checker works from left to right, from top to bottom. When you say file.Contains, it doesn't know which type this should be with Contains member. Therefore, your type annotation is a good hint to F# type checker.

    if I write the COUNT variable right after the line of the [<Literal>] definition it gives an error and says that a constant cannot be "mutable"

    Quoting from MSDN:

    Values that are intended to be constants can be marked with the Literal attribute. This attribute has the effect of causing a value to be compiled as a constant.

    A mutable value can change its value at some point in your program; the compiler complains for a good reason. You can simply delete [<Literal>] attribute.