我一直在看与布赖恩·贝克曼这个MSDN视频 ,我想更好地了解的东西,他说:
每imperitive程序员经过学习的这个阶段,其功能可与表查找替换
现在,我是一个C#程序员谁没上过大学,所以一路上我错过了每个人都行也许别的地方学会了理解。
什么是布莱恩的意思是:
的功能可以与表查找来代替
是否有正在做的这个实际例子和它适用于所有的功能呢? 他给出的正弦函数,我可以做的意义的例子,但我怎么做的这个意义上说更一般地说?
我一直在看与布赖恩·贝克曼这个MSDN视频 ,我想更好地了解的东西,他说:
每imperitive程序员经过学习的这个阶段,其功能可与表查找替换
现在,我是一个C#程序员谁没上过大学,所以一路上我错过了每个人都行也许别的地方学会了理解。
什么是布莱恩的意思是:
的功能可以与表查找来代替
是否有正在做的这个实际例子和它适用于所有的功能呢? 他给出的正弦函数,我可以做的意义的例子,但我怎么做的这个意义上说更一般地说?
布赖恩只是还表明,功能是数据量太大。 在一般功能仅仅是到另一个组映射: y = f(x)
是组映射{X}设置{Y}: f:X->Y
。 该表是映射,以及: [x1, x2, ..., xn] -> [y1, y2, ..., yn]
如果功能上有限集进行操作(这是在编程的情况下),那么它可以用代表该映射表代替。 由于布赖恩提到的每一个程序员必须经历的理解这个阶段,该功能可以只为性能原因,查表所取代。
不过,这并不意味着所有的功能,可以轻松地或者应与表取代。 它只是意味着你在理论上可以做到,对于每一个功能。 所以结论是,该功能是数据,因为表是(当然在编程的情况下)。
有数学中一个可爱的把戏,创建一个表作为评估函数调用,作为重写规则的副作用。 考虑经典慢,斐波那契
fib[1] = 1
fib[2] = 1
fib[n_] := fib[n-1] + fib[n-2]
前两行创建用于输入1及2表项这是完全一样的话说
fibTable = {};
fibTable[1] = 1;
fibTable[2] = 1;
在JavaScript中。 数学的第三行显示“请安装重写规则将替换的任何发生fib[n_]
取代图案可变后n_
与发生的实际的参数,用fib[n-1] + fib[n-2]
“。 重写器将迭代该过程,并最终产生的值fib[n]
重写的指数数之后。 这就像递归函数调用的形式,我们在JavaScript中获得与
function fib(n) {
var result = fibTable[n] || ( fib(n-1) + fib(n-2) );
return result;
}
注意它首先检查了两个值我们已经明确地做递归调用之前存储在表。 Mathematica的评估会自动执行此检查,因为规则呈现的顺序很重要 - 数学检查更具体的规则第一和更多的一般规则后。 这就是为什么数学有两种分配形式, =
和:=
:前者是具体的规则,其右手边可以在规则规定的时间进行评估; 后者是一般规则,其右手边在应用规则时,必须进行评估。
现在,在数学,如果我们说
fib[4]
它被改写成
fib[3] + fib[2]
然后
fib[2] + fib[1] + 1
然后
1 + 1 + 1
终于到3,这不会对下一个改写改变。 你可以想像,如果我们说的fib[35]
我们将产生巨大的表现,填补了内存和融化的CPU。 但关键是用下面的替换最终重写规则:
fib[n_] := fib[n] = fib[n-1] + fib[n-2]
这是说“请更换的每个实例fib[n_]
与表达,将安装新的特定规则的价值fib[n]
同时,产生的价值。” 这一个运行得更快,因为它扩展的规则库 - 值的表! - 在运行时。
我们可以在JavaScript这样做
function fib(n) {
var result = fibTable[n] || ( fib(n-1) + fib(n-2) );
fibTable[n] = result;
return result;
}
这将运行要比FIB事先定义更快。
这就是所谓的“automemoization” [原文如此 - 没有“记忆”,而是“记忆化”在为自己创建备忘录。
当然,在现实世界中,你必须管理得到创建表的大小。 要检查在数学表,做
DownValues[fib]
为了检查它们在JavaScript中,做到这
fibTable
在一个REPL诸如由Node.js的支持
在函数式编程的背景下,有引用透明的概念。 即引用透明的函数可以与它的值被替换为任何给定的参数(或一组参数),在不改变程序的行为。
引用透明
例如,考虑函数F是需要1个参数n。 F是引用透明,所以F(n)的可以被F的以n计算的值来代替。 这使得该程序没有区别。
在C#中,这将是这样的:
public class Square
{
public static int apply(int n)
{
return n * n;
}
public static void Main()
{
//Should print 4
Console.WriteLine(Square.apply(2));
}
}
(我不是很熟悉C#,从Java背景的,所以你必须原谅我,如果这个例子是不是很语法正确)。
很明显这里说的功能应用不能超过4任何其他值时为2的参数调用,因为它只是返回其参数的平方。 该函数的值仅取决于它的参数,N; 换句话说,引用透明。
我问你,那么,有什么区别之间Console.WriteLine(Square.apply(2))
和Console.WriteLine(4)
答案是,没有任何区别可言,对于所有意图的目的。 我们可以完成整个程序,替换的所有实例Square.apply(n)
与返回的值Square.apply(n)
其结果将是完全一样的。
那么,什么也布赖恩·贝克曼表示与他有关与表查找替换函数调用语句? 他指的是引用透明功能这个属性。 如果Square.apply(2)
可以被替换为4
对程序的行为没有任何影响,那么为什么不只是缓存,当第一个调用时的值,并把它放在由函数的自变量索引的表。 对于值的查找表Square.apply(n)
会看起来有点像这样:
n: 0 1 2 3 4 5 ...
Square.apply(n): 0 1 4 9 16 25 ...
而对于任何呼叫Square.apply(n)
而不是调用该函数,我们可以简单地找到了在该表n中的缓存值,并替换函数调用这个值。 这是相当明显,这很可能会导致程序中的一个大的速度增加。