Functional programming 正确理解F#预计算逻辑
这个问题是从我的,关于可变值的问题扩展而来的。我很确定,这个问题的主要主题,预计算,与链接问题有很多关系 请参阅以下示例,这些示例来自我正在学习的书:Functional programming 正确理解F#预计算逻辑,functional-programming,f#,Functional Programming,F#,这个问题是从我的,关于可变值的问题扩展而来的。我很确定,这个问题的主要主题,预计算,与链接问题有很多关系 请参阅以下示例,这些示例来自我正在学习的书: let-isWord(单词:字符串列表)= 让wordTable=Set.of列表单词//昂贵的计算! 乐趣w->wordTable.Contains(w) val-isWord:words:string-list->(string->bool) 它接受字符串列表,并返回检查输入字符串是否在列表中的函数。有了这个可爱的小助手函数,以下是两个示例
let-isWord(单词:字符串列表)=
让wordTable=Set.of列表单词//昂贵的计算!
乐趣w->wordTable.Contains(w)
val-isWord:words:string-list->(string->bool)
它接受字符串列表,并返回检查输入字符串是否在列表中的函数。有了这个可爱的小助手函数,以下是两个示例:
让isCapital=isWord[“伦敦”、“巴黎”、“华沙”、“东京”];;
val isCapital:(字符串->布尔)
让isCapitalSlow word=isWord[“伦敦”;“巴黎”;“华沙”;“东京”]word
val isCapitalSlow:(字符串->布尔)
我认为这两个函数可以做同样的事情,但事实并非如此。书中说,第一个函数从给定的列表中预计算集合,第二个函数将在函数调用时计算集合
正如我在PL课程中所学到的,为了计算lambda演算表达式,每个参数都应该赋给主体。如果只缺少一个表达式,则不允许对表达式进行回避
基于此,我得出结论,第一个没有参数,因此它可以在给出列表时立即开始计算,但第二个在给出参数word
之前无法开始计算。在这里之前一切都很好,但在考虑了上面的相关问题后,我不确定自己是否正确理解了它
从它和相关问题的答案来看,评估似乎一直持续到无法评估为止,这可能是因为缺少信息、参数或任何东西。那么,像第一个例子一样,可以认为表达式的每个无条件部分只计算一次并预先计算吗
这一部分似乎会严重影响优化和性能,因此我想明确我对这一主题的理解。既然您似乎熟悉C#,我们可以将其改写为C#类: 我得出的结论是,第一个没有参数,因此它可以在给出列表时立即开始计算,但第二个在给出参数词之前无法开始计算 这是完全正确的 评估似乎一直持续到无法评估为止,可能是因为缺少信息、参数或任何东西 这基本上也是正确的,但它比你的公式简单得多。“缺乏信息”并不是一件非常复杂的事情——它只是一个事实,即lambda函数是值,在指定其参数之前无法进行计算 如果我们使用
fun x->..
符号重写所有内容,可能会更容易理解这一点:
let isWord = fun (words : string list) =
let wordTable = Set.ofList words
fun w -> wordTable.Contains(w)
let isCapital =
isWord ["London"; "Paris"; "Warsaw"; "Tokyo"]
let isCapitalSlow = fun word ->
isWord ["London"; "Paris"; "Warsaw"; "Tokyo"] word
评估从上到下进行
isWord
的表达式是一个函数,因此无法计算主体isCapital
的表达式是一个函数应用程序,因此可以对其进行计算。这依次计算wordTable
的值,并返回一个函数,该函数是一个函数,无法计算isCapitalSlow
的表达式是一个函数,无法计算isCapitalSlow“Prague”
,这将是一个函数应用程序,因此可以对其进行评估。然后,它将调用isWord
,并将城市列表作为参数,然后调用Set.ofList
来构建wordTable
,并生成一个函数,然后将word
作为参数进行计算未经检查,isCapital似乎是一个值。该值是一个函数,在调用isWord时返回。因此,在计算isCapital时,wordTable只计算一次。但是isCapitalSlow不是一个值——它是一个函数,因此每次调用它时都会调用isWord。如果仍然不清楚,请记住函数是F#语言的一流成员。isCapital是一个值,但该值是一个已计算的函数。另一方面,isCapitalSlow是一个编码(术语?)函数,而不是计算函数,因此不是值。isWord是一个计算函数的函数。每个F#某物都是一个值,没有它的任何参数都无法计算。就这么简单。谢谢你详细的回答!要澄清一点,每个F#某物都是一个表达式,包括
funx->x+1
或x+1
和1
。其中一些表达式是值,无法计算,例如1
或funx->x+1
。有些不是值,可以进行计算,例如1+2
(在lambda演算中,应用函数时通过替换得到)
Func<string, bool> isCapital =
new IsWord(new[] { "London", "Paris", "Warsaw", "Tokyo" }).Contains;
Func<string, bool> isCapitalSlow =
(word) => new IsWord(new[] { "London", "Paris", "Warsaw", "Tokyo" }).Contains(word);
let isWord words =
let wordTable = Set.ofList words
let contains word = wordTable |> Set.contains word
contains
let isWord = fun (words : string list) =
let wordTable = Set.ofList words
fun w -> wordTable.Contains(w)
let isCapital =
isWord ["London"; "Paris"; "Warsaw"; "Tokyo"]
let isCapitalSlow = fun word ->
isWord ["London"; "Paris"; "Warsaw"; "Tokyo"] word