我只是在学习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
我的问题是:
n * factorial (n-1)
?->
之后使用表达式?答案 0 :(得分:1)
发表评论:
真正匹配的更常见版本是
|true,result -> result
你需要->
之后的位来实际返回一个值。
在错误匹配中,您需要通过计算
来实际计算阶乘n * factorial(n-1)
事实上,错误案例的更好版本将是
|false, _ ->
let r = n * factorial(n-1)
factorials.Add(n,r)
r
答案 1 :(得分:1)
// 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
更好solution。
修改
1.为什么我需要在错误匹配结束时调用n * factorial(n-1)?
我认为你来自一个命令性的背景,很可能是C#,因为你使用了词典。功能代码不是命令式代码。在用函数式语言编码时,必须考虑函数。函数以将结果放在堆栈上结束,除了异常之外,所有退出函数的方法都必须以相同的类型签名结束
所以对于这个匹配函数
match factorials.TryGetValue(n) with
| true, _ -> n * factorial(n-1)
| false, _ ->
factorials.Add(n, n * factorial(n-1))
n * factorial(n-1)
该功能有两种结束方式。一个通过真实,一个通过虚假。因此,这两个分支都以每个分支中最后一个函数的int退出。
即。
n * factorial(n-1)
2.为什么在 - &gt;之后我需要一个表达式?在真正的比赛中?
匹配语句获取匹配结果,例如factorials.TryGetValue(n)
并匹配可能的模式。由于此匹配的签名是(bool * int),因此您已将所有模式与(true,)和(false,)匹配。现在,对于每个匹配模式,您必须具有详细说明要执行的操作的代码。 - &gt;将模式与详细说明要执行的代码分开。将匹配和模式视为switch语句。您需要为每个开关选项执行一些操作。