[英]How to define the order of execution in F#?
在纯函数式编程中,执行顺序无关紧要,因此未确定(即由编译器决定)。 如果您有副作用,执行顺序很重要。 那么如何在F#中定义?
我有一个函数,递归删除给定路径的所有空子文件夹。 此外,如果它们的名称在给定列表中,它将删除其中包含的一些文件。
算法很简单:
此外,该函数返回已删除元素的数量作为元组(已删除文件夹的数量,已删除文件的数量)。
这是我的代码:
let rec DeleteEmptyFolders path filenames =
// Deletes a file or folder using the given function.
// Returns 1 if the file could be deleted, otherwise 0.
let Delete delete name =
try
delete name;
1
with
| _ -> 0
// The function result (number of deleted folders and files).
let deletedFolders (a, _) = a
let deletedFiles (_, a) = a
let accumulator a b =
( deletedFolders a + deletedFolders b,
deletedFiles a + deletedFiles b )
// Deletes the given files and returns the number of deleted elements.
let DeleteFiles folder names =
names
|> Seq.map (fun n -> Path.Combine (folder, n))
|> Seq.map (fun n -> Delete File.Delete n)
|> Seq.reduce (+)
// Deletes the folder if it is empty
// (Directory.Delete will fail if it is not empty).
let DeleteFolder folder = Delete Directory.Delete folder
// The recursive call
let DeleteEmptySubFolders folder files =
Directory.EnumerateDirectories folder
|> Seq.map (fun p -> DeleteEmptyFolders p files)
|> Seq.reduce (accumulator)
// Three functions are executed: DeleteEmptySubFolders, DeleteFolder and DeleteFiles
// But it has to be done in the correct order: DeleteFolder must be executed last.
accumulator (DeleteEmptySubFolders path filenames) (DeleteFolder path, DeleteFiles path filenames)
我可以弄清楚首先执行DeleteEmptySubFolders,然后执行DeleteFolder和DeleteFiles。 这是函数在代码中出现的顺序。 但我不认为这是F#的规则,它正是编译器所决定的。 它可以是任何其他订单。
当然,我可以在代码的最后一行交换元素。 编译器会相应地更改执行顺序。 但由于这不是语言的规则,它只是运气。
在关于这个主题的另一个问题中 ,我已经读过,值(即没有参数的函数)按照它们被声明的顺序初始化。
let firstCall = DeleteFiles path filenames
let secondCall = DeleteEmptySubFolders path filenames
let thirdCall = DeleteFolder path
accumulator (secondCall) (thirdCall, firstCall)
现在呼叫恰好是正确的顺序。 但同样:这是F#的规则还是编译器的工作原理? (如果未使用这些函数,编译器可能决定根本不对这些值进行初始化)
如果我想告诉F#执行顺序是否重要以及何时应该完成每个调用,我该如何写最后一行? 是否有关键字或特殊语法将函数标记为无副作用?
F#不是纯函数式编程语言:函数和值将从上到下,从左到右计算。
我认为最好只编写代码
let firstCall = DeleteFiles path filenames
let secondCall = DeleteEmptySubFolders path filenames
let thirdCall = DeleteFolder path
accumulator (secondCall) (thirdCall, firstCall)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.