Javascript函数式编程语言(2)

耦合是程序里模块间的大量依赖。由于函数式编程遵循编写一等公民的、高阶的纯函数, 这使得它们对全局变量没有副作用而彼此完全独立,耦合极大程度上的减小了。 当然,函数会不可避免地相互依赖,但是改变一个函数不会影响其他的,只要输入和输出的一对一映射保持正确。

数学正确性

最后一点更理论一些。由于根植于lambda演算,函数式编程可以在数学上证明正确性。 这对于一些研究者来说是一个巨大的优点,他们需要用程序来证明增长率、时间复杂度以及数学正确性。

我们来看看斐波那契数列。尽管它很少用于概念性证明以外的问题,但是用它来解释这个概念非常好。 对一个斐波那契数列求值标准的办法是建立一个递归函数,像这样:

fibonnaci(n) = fibonnaci(n-2) + fibonnaci(n–1)

还需要加上一个一般情形:

return 1 when n < 2

这使得递归可以终止,并且让递归调用栈里的每一步从这里开始累加。

下面列出详细步骤

var fibonacci = function(n) { if (n < 2) { return 1; }else { return fibonacci(n - 2) + fibonacci(n - 1); } } console.log( fibonacci(8) ); // Output: 34

然而,在一个懒执行函数库的辅助下,可以生成一个无穷大的序列,它是通过数学方程来定义整个序列的成员的。 只有那些我们最终需要的成员最后才会被计算出来。

var fibonacci2 = Lazy.generate(function() { var x = 1, y = 1; return function() { var prev = x; x = y; y += prev; return prev; }; }()); console.log(fibonacci2.length()); // Output: undefined console.log(fibonacci2.take(12).toArray()); // Output: [1, 1, 2, 3, 5,8, 13, 21, 34, 55, 89, 144] var fibonacci3 = Lazy.generate(function() { var x = 1, y = 1; return function() { var prev = x; x = y; y += prev; return prev; }; }()); console.log(fibonacci3.take(9).reverse().first(1).toArray()); //Output: [34]

第二个例子明显更有数学的味道。它依赖Lazy.js函数库。还有一些其它这样的库,比如Sloth.js、wu.js, 这些将在第三章里面讲到。

我插几句:后面这个懒执行的例子放这似乎仅仅是来秀一下函数式编程在数学正确性上的表现。 更让人奇怪的是作者还要把具有相同内部函数的懒加载写两遍,完全没意义啊…… 我觉得各位看官知道这是个懒执就行了,不必深究。

非函数式世界中的函数式编程

函数式和非函数式编程能混合在一起吗?尽管这是第七章的主题,但是在我们进一步学习之前, 还是要弄明白一些东西。

这本书并没要想要教你如何严格地用纯函数编程来实现整个应用。这样的应用在学术界之外不太适合。 相反,这本书是要教你如何在必要的命令式代码之上使用纯函数的设计策略。

例如,你需要在一段文本中找出头四个只含有字母的单词,稚嫩一些的写法会是这样:

var words = [], count = 0; text = myString.split(' '); for (i=0; count < 4, i < text.length; i++) { if (!text[i].match(/[0-9]/)) { words = words.concat(text[i]); count++; } } console.log(words);

函数式编程会写成这样:

var words = []; var words = myString.split(' ').filter(function(x){ return (! x.match(/[1-9]+/)); }).slice(0,4); console.log(words);

如果有一个函数式编程的工具库,代码可以进一步被简化:

复制代码 代码如下:


var words = toSequence(myString).match(/[a-zA-Z]+/).first(4);

判断一个函数是否能被写成更加函数式的方式是寻找循环和临时变量,比如前面例子里面的“words”和”count”变量。 我们通常可以用高阶函数来替换循环和临时变量,本章后面的部分将对其继续探索。

Javascript是函数式编程语言吗?

现在还有最后一个问题我们需要问问自己,Javascript是函数式语言还是非函数式语言?

Javascript可以说是世界上最流行却最没有被理解的函数式编程语言。Javascript是一个披着C外衣的函数式编程语言。 它的语法无疑和C比较像,这意味着它使用C语言的块式语法和中缀语序。并且它是现存语言中名字起得最差劲的。 你不用去想象就可以看出来有多少人会因Javascript和Java的关系而迷惑,就好像它的名字暗示了它会是什么样的东西! 但实际上它和Java的共同点非常少。不过还真有一些要把Javascript强制弄成面向对象语言的主意, 比如Dojo、ease.js这些库曾做了大量工作试图抽象Javascript以使其适合面向对象编程。 Javascript来自于90年代那个满世界都嚷嚷着面向对象的时代,我们被告知Javascript是一个面向对象语言是因为我们希望它是这样, 但实际上它不是。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wggypx.html