澳门新葡亰官网7598522:函数式编程(javascirpt)
媒介
Javascript,有人称其为C+LISP,C只怕是尽人皆知,然则不停生动在人工智能领域的另一个古老而柔美的说话LISP,掌握的生怕不是很多.这个倒不是由于这个说话太难或者用途不广泛,而是大年夜多半人在吸收谋略机说话启蒙的时刻都走的是图灵机模式,而LISP,做为一种函数式编程说话,是另一个体系:lambda演算体系.这个体系的运算能力跟图灵机的运算能力是相称的。
以是Javascript本身是一种很自由的,支持函数式编程的一个神奇的说话,在WEB中的利用只是它的以个小小的部分。脚本可以用来脚本化很多器械,最主澳门新葡亰官网7598522要的利用是在UI层面,很机动(这也是Javascript用来脚本化HTML的一个紧张缘故原由)。我们这里要说的是一个100%java实现的 javascript引擎rhino,当然重点不是引擎本身,而是在其上解释澳门新葡亰官网7598522JavaScript的函数式编程。(rhino可以在此处 http://www.mozilla.org/rhino/找到)。
函数式编程概览
我们先看几个例子,从感官上对其有一个懂得,看一个幂谋略函数,用敕令式说话书写(敕令式说话如C,Java等),大年夜概便是下面这个样子:
function expt(b, n){
if(n == 0){return 1;}
else{
return expt(b, n-1)*b;//正常的递归调用
}
}
再看看函数式编程的写法:
function expt(b, n){
if(n == 0){
return 1;
}else{
return mul(expt(b, dec(n)), b);//所有操作均为函数
}
}
可以很显着的看到,有一大年夜堆的括号,没有操作符(如+-*/等),这是由于,操作符在函数式编程中被觉得是函数,与其他函数(数学函数,串处置惩罚函数等)的职位地方是一致的,当然这个不是最主要的,在函数式编程中最主要的是函数可以做为一个基础类型被返回,这一点时敕令式说话无法完成的。
比如,定义一个函数,输入两个参数,谋略这两个数的平方和:
function(x, y){ return add( expt(x, 2), expt(y, 2) ); }
你可以将这个函数赋值给一个变量,如下:
var func = function(x, y){ return add( expt(x, 2), expt(y, 2) ); }
然后,最神奇的是,下边这样:
func(3, 4);//这个表达式将返回25! 此时的func已经是一个函数了!
好了,简单的概述就此为止,下面我们看一些更高档的主题:高阶函数。
高阶函数
事实上,所有的有关函数式编程的文章必须要涉及到这个主题,这是由于,在敕令式说话中,我们的抽象是根据"类"(这恰是现在盛行的OO的基础思惟)来进行的,然则,在函数式编程中,没有法子表示类的观点,然则同样可以进行高档的抽象要领,使得一个函数加倍泛化,可以被"实例化"成其他的函数,这个便是高阶函数。澳门新葡亰官网7598522
来看个例子,我们有这样几种乞降运算:
function intSum(a, b){
function inc(x){ return x + 1; }
function澳门新葡亰官网7598522 identity(x){ return x; }
if(a > b){
return 0;
}else{
return intSum(inc(a) , b) + identity(a);
}
}
function cubeSum(a, b){
function inc(x){ return x + 1; }
function cube(x){ return x * x * x; }
if(a > b){
return 0;
}else{
return cubeSum(inc(a) , b) + cube(a);
}
}
function piSum(a, b){
function piTerm(x){ return 1/((x+2)*x); }
function piNext(x){ return x+4; }
if(a > b){
return 0;
}else{
return piSum(piNext(a) , b) + piTerm(a);
}
}
高阶函数供给了更高档的抽象,从而使得法度榜样的布局加倍清晰。下面我们再看看函数式说话的优雅的代码,匿名函数:
匿名函数
我们先对一些简单的操作进行简单澳门新葡亰官网7598522的包装(如四则运算,boolean运算等操作):
function abs(x){ return x>0?x:-x;}
function add(a, b){ return a+b; }
function sub(a, b){ return a-b; }
function mul(a, b){ return a*b; }
function div(a, b){ return a/b; }
function rem(a, b){ return a%b; }
function inc(x){ return x + 1; }
function dec(x){ return x - 1; }
function equal(a, b){ return a==b; }
function great(a, b){ return a>b; }
function less(a, b){ return a0; }
然后,在这些共用的语法糖(并非严格意义上的语法糖,然则它们切实着实是!)的根基上,做一些简单的函数定义:
// n*(n-1)*(n-2)*...*3*2*1
function factorial(n){
if(equal(n, 1)){
return 1;
}else{
return mul(n, factorial(dec(n)));
}
}
//对上边的函数的另一种定义要领
/*
* productmax){
return product;
}else{
fact_iter(mul(counter, product), inc(counter), max);
}
}
return fact_iter(1, 1, n);
}
function expt(b, n){
if(n == 0){
return 1;
}else{
return mul(expt(b, dec(n)), b);
}
}
function gcd(a, b){
if(b == 0){
return a;
}else{
return gcd(b, rem(a, b));
}
}
function search(fx, neg, pos){
function closeEnough(x, y){return less( abs( sub(x, y) ), 0.001)};
var mid = (function(x, y){return div( add(x, y), 2);})(neg, pos);
if(closeEnough(neg, pos)){
return mid;
}else{
var test = fx(mid);
if(positive(test)){
return search(fx, neg, mid);
}else if(negative(test)){
return search(fx, mid, pos);
}else{
return mid;
}
}
}
function halfIntervalMethod(fx, a, b){
var av = fx(a);
var bv = fx(b);
if(negative(av) && positive(bv)){
return search(fx, a, b);
}else if(negative(bv) && positive(av)){
return search(fx, b, a);
}else{
print("error happend!!");
}
}
//谋略一个函数的不动点
function fixedPoint(fx, first){
var tolerance = 0.00001;
function closeEnough(x, y){return less( abs( sub(x, y) ), tolerance)};
function Try(guess){
var next = fx(guess);
//print(next+" "+guess);
if(closeEnough(guess, next)){
return next;
}else{
return Try(next);
}
};
return Try(first);
}
// magic function sqrt, a little hard to read, hah?
function sqrt(x){
return fixedPoint(
function(y){
return function(a, b){ return div(add(a, b), 2);}(y, div(x, y));
},
1.0);
}