Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.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
Recursion F#中带记忆的递归阶乘函数_Recursion_F# - Fatal编程技术网

Recursion F#中带记忆的递归阶乘函数

Recursion F#中带记忆的递归阶乘函数,recursion,f#,Recursion,F#,我只是在学习F#,我拼凑了这个函数,但我不完全明白到底发生了什么,有人能解释一下吗 open System.Collections.Generic let factorials = Dictionary<int, int>() factorials.Add(1, 1) let rec factorial n = if n <= 1 then 1 else match factorials.TryGetValue(n) with

我只是在学习F#,我拼凑了这个函数,但我不完全明白到底发生了什么,有人能解释一下吗

open System.Collections.Generic

let factorials = Dictionary<int, int>()
factorials.Add(1, 1)

let rec factorial n =
    if n <= 1 then 1
    else
        match factorials.TryGetValue(n) with
        | true, _  -> n * factorial(n-1)
        | false, _ -> 
            factorials.Add(n, n * factorial(n-1))
            n * factorial(n-1)     

let a = factorial 9
open System.Collections.Generic
设阶乘=字典()
阶乘.加(1,1)
设rec阶乘n=
如果n*阶乘(n-1)
|错误,->
阶乘.加(n,n*阶乘(n-1))
n*阶乘(n-1)
设a=阶乘9
我的问题是:

  • 为什么我需要在假匹配结束时调用
    n*factorial(n-1)
  • 为什么在真正匹配的
    ->
    后面需要一个表达式

  • 针对评论:

    真正匹配的更常见版本是

    |true,result -> result 
    
    您需要
    ->
    后面的位来实际返回值

    在假匹配中,您需要通过计算

    n * factorial(n-1)
    
    事实上,更好的说法应该是

     |false, _ -> 
         let r = n * factorial(n-1)
         factorials.Add(n,r)
         r
    
    函数有两种结束方式。一个是真的,一个是假的。因此,这两个分支都以每个分支中最后一个函数的int退出

    i、 e

    2.为什么我需要在真正匹配中的->之后使用表达式


    match语句获取匹配的结果,例如,
    factorials.TryGetValue(n)
    ,并对可能的模式进行匹配。因为这个匹配的签名是(bool*int),所以您已经用(true)和(false)匹配了所有模式。现在,对于每个匹配模式,您必须有详细说明要执行的操作的代码。->将模式与详细说明要执行操作的代码分离。将匹配和模式视为switch语句。每个开关选项都需要执行一些操作。

    这是阶乘函数的简单记忆版本。TryGetValue返回布尔值(显然只有一个值),那么true和false之后的第二个元素是什么(答案中的结果)?另外,为什么我不能在假匹配中的“->”后面加上“factorials.Add(n,n*factorial(n-1))?
    Trygetvalue
    实际上也返回一个值-参见这里。这就是您的版本需要
    的原因。您可以使用您的版本,但这会进行两次递归调用,这是一种浪费。
    TryGetValue
    有一个out参数,F#作为第二个元素获取。感谢您的详细解释。您链接到的答案不包括记忆,这是本练习的重点。另外,我来自C#land,这就是为什么我要学习F#和函数编程,谢谢你的建议。你在问题或标题中提到记忆了吗?你会如何写一个带记忆的阶乘函数?函数不必返回max input的值,最好是返回字典(或类似的数据结构),其中包含输入的阶乘?
    // Access the library containing the Dictionary module
    open System.Collections.Generic
    
    // Crate a key value,pair named factorials, e.g. table, to hold the
    // the factorial number n and it's result.
    let factorials = Dictionary<int, int>()
    
    // Add an initial entry into the factorials table for the 
    // value for one and the result of the factorial of one, being one.
    factorials.Add(1, 1)
    
    // Define a recursive function for factorial
    // taking one integer parameter
    let rec factorial n =
        // If the parameter is less than or equal to one
        // then return one
        if n <= 1 then 1
        // If the parameter is greater than one then
        else
            // look up the result of the factorial in the factorials table.
            // Use TryGetValue when looking up value to avoid errors when
            // there is no matching key for the value.
            // There is a problem here with the way TryGetValue is used.
            // It should be used as
            //   let mutable factresult
            //   factorials.TryGetValue(n,factresult)
            // The problem causes the result of TryGetValue(n) to be
            // the tuple (bool * int) instead of bool with the 
            // value part updating the mutable factresult.
            // Next the patterns for the match are true,_ and false, _ 
            // which match the tuple of the TryGetValue(n)
            // but the _ means to toss out the value it matches
            // because it doesn't have a name, 
            // so the whole use of the factorials table is not needed.
            match factorials.TryGetValue(n) with
            // If there is an entry in the factorials table then take this action.
            // Take n and multiply it by the factorial of n-1.
            // As an example for 5 this becomes 5 * 4 * 3 * 2 * 1
            // Take the result of n * factorial(n-1) and push it on to the stack
            // as the result of the function. 
            | true, _  -> n * factorial(n-1)
            // If there is no entry in the factorials table then
            // calculate the result of the factorial of n, i.e. n * factorial(n-1))
            // and add it to the factorials table.
            // Take the result of n * factorial(n-1) and push it on to the stack
            // as the result of the function. 
            | false, _ -> 
                factorials.Add(n, n * factorial(n-1))
                n * factorial(n-1)     
    
    let a = factorial 9
    
       match factorials.TryGetValue(n) with
        | true, _  -> n * factorial(n-1)
        | false, _ -> 
            factorials.Add(n, n * factorial(n-1))
            n * factorial(n-1)
    
    n * factorial(n-1)