この記事の例では、JavaScript 関数プログラミングについて説明します。皆さんの参考に共有してください。具体的な分析は次のとおりです。
JS は、他の動的言語と同様に、高階関数を記述することができます。いわゆる高階関数は、関数を操作できる関数です。なぜなら、js では関数は完全なオブジェクトであり、関数型プログラミングの前提条件を提供する第一級の市民に属しているからです。
以下は、js チュートリアルのコード例です。その機能は、配列要素の平均と標準偏差を計算することです。まず、非関数型プログラミングの記述方法をリストします。
var data = [1,1,3,5,5]; var total = 0; for(var i = 0;i < data.length;i++) total += data[i]; var mean = tatal/data.length; //平均数为3 //计算标准差 total = 0; for(var i = 0;i < data.length;i++){ var deviation = data[i] - mean; tatal += deviation * deviation; } var stddev = Math,.sqrt(total/(data.length-1));//标准差为2
//将类数组对象转换为真正的数组 function array(a,n){ return Array.prototype.slice.call(a,n||0); } //将函数实参传递至左侧 function partial_left(f){ var args = arguments; return function(){ var a = array(args,1); a = a.concat(array(arguments)); return f.apply(this,a); }; } //将函数的实参传递至右侧 function partial_right(f){ var args = arguments; return function(){ var a = array(arguments); a = a.concat(array(args,1)); return f.apply(this,a); }; } //该函数实参被用做模版, //实参列表中的undefined值会被实际实参值填充。 function partial(f){ var args = arguments; return function(){ var a = array(args,1); var i = 0,j = 0; for(;i<a.length;i++) if(a[i] === undefined) a[i] = arguments[j++]; a = a.concat(array(arguments,j)); return f.apply(this,a); }; } //返回一个函数类似于f(g()) function compose(f,g){ return function(){ return f.call(this,g.apply(this,arguments)); }; }
var data = [1,1,3,5,5]; var sum = function(x,y){return x+y;}; var product = function(x,y){return x*y;}; var neg = partial(product,-1); var square = partial(Math.pow,undefined,2); var sqrt = partial(Math.pow,undefined,0.5); var reciprocal = partial(Math.pow,undefined,-1); //好吧,高潮来鸟 :) var mean = product(reduce(data,sum),reciprocal(data.length)); var stddev = sqrt(product(reduce(map(data,compose(square,partial(sum,neg(mean)))),sum),reciprocal(sum(data.length,-1))));
ary = (1..10).to_a ary.inject(0) {|sum,i|sum + i} //结果为55
var ary = [1,2,3,4,5,6,7,8,9,10] ary.reduce(function(sum,i){ return sum + i; },0);
map 関数も非常に単純で、配列の各要素を操作し、操作後に配列を返すのと似ています。js コードは次のようになります。 >
a = (1..3).to_a; #数组[1,2,3] a.map {|x| x*2} #返回新数组[2,4,6]
sum と product は要素を加算および乗算する関数を定義します。
neg は、product(-1,x) と同等の関数でもあり、負の x 値を意味します。
square 関数は Math.pow(x,2) と同等であり、x の 2 乗値を計算します。ここでは、partial の 2 番目のパラメーターが未定義であることに注意してください。つまり、ここでの仮パラメーターは、最初の実パラメータを入力します。明確にしておきます。square(x) 関数は Math.pow(x,2) と同じです。sqrt 関数は square に似ており、その関数は Math.pow(x,0.5) と同等であり、x の平方根を計算するのと同等です。
最後の関数 reciprocal は、Math.pow(x,-1) と同等です。つまり、x の負のべき乗を計算することは、x の逆数を計算することと同じです。
上記の関数を組み合わせる方法は次のとおりです :)
最後に、一見難しそうな標準偏差を、内側から外側に見てみるとよいでしょう:
まず、ネガを含むレイヤーを見てください:
//等价于函数sum(-1 * mean + x) partial(sum,neg(mean)
//下面在源代码上做了等价替换,可以再次等价于: //square(sum(-1*mean + x)),再次展开(我剥,我剥,我剥洋葱...): //Math.pow(sum(-1*mean + x),2); compose(square,sum(-1*mean + x))
map(data,Math.pow(sum(-1*mean + x),2))
//将前面新数组的每个元素值加起来。 reduce(map(...),sum)
//等价于求(data.length-1)的倒数 reciprocal(sum(data.length,-1))
//等价于新数组元素的和除以(data.length-1) product(reduce(...),reciprocal(...))
この記事が皆様の JavaScript プログラミング設計に役立つことを願っています。