Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Functional programming 正确理解F#预计算逻辑_Functional Programming_F# - Fatal编程技术网

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