DSL与函数式编程

samgui(三桂)
  1. 打孔机,机器语言(记得操作系统课上老师展示过…)
  2. 汇编语言:最底层的操作都通过代码来指定
  3. 面向过程语言:Picasal、C
  4. 面向对象语言:C++
  5. 虚拟机时代(垃圾收集、类型安全):Java、C#
  6. 动态语言:Python、Ruby

扯的有点远了,我想说的是:编程语言越来越抽象了…

在数学中函数的抽象定义是元素(输入)与元素(输出)之间的对应数学关系。例如:y=f(x)定义了xy之间的数学关系,函数计算完成之后x的值不会改变,并返回一个输出y

在编程语言中为了重复利用一些特定操作,于是产生了函数。函数被定义为:根据输入计算得到输出的一批程序指令。函数计算完成之后输入可能会改变,并返回一个输出或不返回。

编程语言中的函数与数学函数最大的区别在于:函数是有状态的,它可以修改外部变量或输入变量。而数学函数没有状态、没有变量。并且程序语言的函数除了计算值之外还可以做些额外的操作。这些操作可以是:打印日志、调整显示GUI等等。

函数式编程的定义是:将计算等同于数学函数的编程范式。“函数式编程”中的函数是数学函数而不是一般程序语言中的函数。

函数式编程与一般的命令式编程的区别:

//命令式编程:
function Counter(_i) {
    var i = _i || 0;
    this.add = function(j) {
        i = i+j;
    }
}
//函数式编程:
function Counter(_i) {
    var i = _i || 0;
    this.add = function(j) {
        return new Counter(i+j);
    }
}

两者的区别在于函数式编程的add方法并没有修改i变量,也就是Counter没有可变的状态。这赋予了函数式编程最大的优点:线程安全。虽然前端的javascript开发并没有涉及到多线程的情况,不过随着HTML5的普及,WebWorker的出现也会使的javascript渐渐出现多线程并行问题。

当然函数式编程的优点并不只在于线程安全这一个,而且更在于它在某些情况下的结构清晰,例如:修改给所有数组中的值加1。

//命令式编程:
function add(array) {
    for (var i=0,length=array.length;i<length;i++)
        array[i]++;
}
//函数式编程:
function add(n) { return n+1; } //不修改输入变量
_(array).map(add);

两端段代码,相比之下后者的结构更加清晰,因为它相比命令式编程更进一步抽象了。函数式编程达到了和DSL一样的目的:我们可以更关注做什么(what)而不是怎么做(how),提供更清晰的代码结构。除了例子中map之外,还有延迟计算、Memorization等等这些都是函数式编程中的Good parts。

之前那段代码中用到了一个javascript库就是understandcore.js,这个库提供了在js中实现函数式编程的功能。当然做到完全的使用函数式编程是不可能的!

  1. 因为我们总会遇到需要在函数中做其他操作的情况,例如打印日志;
  2. 还有性能问题,第一个例子中函数式编程明显在性能上有很大劣势;

所以“函数式编程”也需要在适当的时候使用才能发挥作用,不能滥用!

##参考

http://blog.zhaojie.me/2010/04/trends-and-future-directions-in-programming-languages-by-anders-2-declarative-programming-and-dsl.html

http://news.csdn.net/a/20100311/217407.html

http://en.wikipedia.org/wiki/Functional_programmin