如何在没有"printf"的情况下调用Seq.whatever中的函数?

nat*_*ati 2 f# sequences seq

我是f#的新手,我试图编写一个程序,该程序应该遍历给定目录中的所有文件,并为每个类型为".txt"的文件添加一个id号+"DONE"到文件中.

我的节目:

//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
Run Code Online (Sandbox Code Playgroud)

我的问题:

如果我不写最后一行(printfn"%A"a)文件不会改变.(如果我写这行,它可以工作并更改文件)当我使用调试器时我发现它并没有真正计算当'a'到达线时,如果"让a = ......",它继续到printfn线,而当它"看到"'a'时,它返回并计算答案''一个'.它为什么以及如何在没有印刷的情况下"启动"功能?

还有 - 有人可以告诉我为什么我必须添加文件作为函数"addNumber"的返回类型?(我添加了这个,因为它是如何工作但我真的不明白为什么......)

最后一个问题 - 如果我在[]定义的行之后写COUNT变量它会给出一个错误,并说一个常量不能是"可变的"但是如果一个add(这就是为什么我这样做了)之前​​的另一行(比如字符串)它"忘记"错误和工作.为什么?如果你真的不能有一个可变的const我怎么能做一个静态变量?

pad*_*pad 9

如果我不写最后一行(printfn"%A"a),文件将不会改变.

F#序列是懒惰的.因此,为了强制评估,您可以执行一些不返回序列的操作.例如,您可以调用Seq.iter(有副作用,返回()),Seq.length(返回int序列的长度)或Seq.toList(返回列表,急切的数据结构)等.

有人可以告诉我为什么我必须添加file : string函数"addNumber"的返回类型?

方法和属性访问不适合F#类型推断.类型检查器从左到右,从上到下工作.当你说file.Contains,它不知道这应该与Contains成员的类型.因此,您的类型注释是F#类型检查器的一个很好的提示.

如果我在[<Literal>]定义的行之后写COUNT变量,它会给出一个错误,并说一个常量不能是"可变的"

引自MSDN:

可以使用Literal属性标记要作为常量的值.此属性具有将值编译为常量的效果.

可变值可以在程序中的某个点改变其值; 编译器抱怨有充分的理由.您只需删除[<Literal>]属性即可.