什么是函数式编程
2010-09-14 13:13:57 来源:WEB开发网如果你用一些常见的语言编程的话,这就是其工作的方式,如果它能以任何方式运行起来的话,你一定十分惊讶。
在一个惰性语言中,就会有一些其他奇怪的事情发生。传递给函数的参数只有当函数实际用到它们的时候才会进行计算。还记得前面give_me_a_three函数会抛弃它的参数,总是返回3么?在惰性语言中,上面的调用并不会失败,因为give_me_a_three从不会看它第一个参数,所以第一个参数并不会被计算,所以被零除并不会发生。
惰性语言还能让你做一些很古怪的事情,比如定义一个无限长的列表。前提是你不会真的去迭代整个列表,这就没问题(换句话说,比如你只要获取前10个元素)。
OCaml是一个严格语言,不过它有一个Lazy模块可以让你写一些惰性表达式。下面有一个例子。首先我们给1/0创建一个惰性表达式:
# let lazy_expr = lazy (1/0);;
val lazy_expr : int lazy_t = <lazy>
注意这种惰性表达式的类型是int lazy_t。
因为give_me_a_three接受'a(任何类型)作为参数,所以我们可以将惰性表达式传递给该函数:
# give_me_a_three lazy_expr;;
- : int = 3
如果要计算一个惰性表达式,必须使用Lazy.force函数:
# Lazy.force lazy_expr;;
装箱类型和拆箱类型
Exception: Division_by_zero.
当讨论函数式语言的时候,有一个术语你会经常听到,这就是“装箱”。当我第一次听到这个术语的时候,我也很困惑,其实如果你以前用过C/C++或者Java,那么对你来说装箱类型和拆箱类型之间的区别是相当简单的(在Perl中,一切东西都是被装箱过的)。
如何去思考一个被装箱的对象呢,在C中这种对象就是使用malloc在堆上分配的(或者在C++中等同于new),同时/或者通过一个指针来引用的对象。看一下这个C程序的例子:
view plaincopy to clipboardprint?
#include<stdio.h>
void
printit(int*ptr)
{
printf("thenumberis%dn",*ptr);
}
void
main()
{
inta=3;
int*p=&a;
printit(p);
}
#include <stdio.h>
void
printit (int *ptr)
{
printf ("the number is %dn", *ptr);
}
void
main ()
{
int a = 3;
int *p = &a;
printit (p);
}
变量a是分配在栈上的,所以肯定是被拆箱过的。
函数printit接受一个装箱过的整数并将其打印出来。
拆箱了的整数要比装箱了的快很多。另外,因为单独分配更少,所以对于拆箱的对象的类型垃圾收集更加快速也更加简单。
在C/C++中,你应该对构造以上两种类型的数组是没有问题的。在Java中,有两种类型,int是拆箱型的,而Integer是装箱型的,因此相对不如前者有效。在OCaml中,所有的基本类型都是拆箱型的。
更多精彩
赞助商链接