Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

编程语言与自然语言(壹)

  编程语言与自然语言他们都是“语言”,当然会有很多这样那样的关联。编程语言的发展很多地方都是参考着自然语言的。有时候,对某种编程语言,我们写起代码来会觉得很爽。这就是因为这种编程语言与自然语言的相似度高,所以我们写代码就像说话一样爽。
  很早以前,编程语言几乎都是函数式(面向过程)的,实现功能需要通过调用大堆函数来完成。这是因为函数在这种东西很容易编译,或者说容易转换成计算机逻辑。虽然近几年来面向对象的编程模式几乎全面普及了,但是函数式语言依然有一定的生存空间。下面我们看个PHP的CURL使用例子
$c=curl_init();
curl_setopt($c,CURLOPT_URL,'http://www.web-tinker.com');
curl_setopt($c,CURLOPT_RETURNTRANSFER,true);
$r=curl_exec($c);
?>
  这个代码是用HTTP的GET方法请求访问目标URL,并获取服务器响应的网页代码(这只是个例子,不要吐槽优化)。PHP就是典型的函数式编程语言,虽然也可以使用类继承的面向对象模式,但是本质就是函数式的。在这个代码中,一开始创建的了变量“$c”,而后面的每一句都有用到这个变量,这就会感觉很繁琐。另外,函数式语言有大量的函数,因此函数名也需要加前缀以防止冲突。所以函数名也很冗长。总之,函数式语言的使用是繁琐的。可能由于这个例子太常简单了,看不出麻烦所在。但是用过Windows API的就很清楚,那些复杂的函数与结构体会让你蛋疼到爆。即使每个函数都有详细的文档,但是面对十多个参数,而且参数类型还是结构体的函数,就有种想砸电脑的冲动了。就为了调用一个函数,我要写上好几十甚至上百行代码去构造参数。为了避免这种情况,人们就会去把他们封装成对象,也就是换成面向对象的模式来开发。下面就是把上面的例子换成面向对象的写法,不过PHP是没有提供这个封装的,需要自己封装。 $c=new CURL;
$c->setopt(CURLOPT_URL,'http://www.web-tinker.com');
$c->setopt(CURLOPT_RETURNTRANSFER,true);
$r=$c->exec();
  这样就省去了一堆麻烦的句柄(资源对象)引用。不过,并不是所有函数都像CURL这样需要对一个句柄连续引用的。比如一些简单的通用函数,iconv、json_encode等。这样的简单函数如果也封装成类,反而会让使用变得麻烦。因为类的使用需要经过一个实例化的过程,也就是上面这个例子中的“new”。本来可以直接使用的函数,如果还要把它先“new”到一个变量中再调用其方法,显然很脑残。于是,人们又引入了命名空间来分类存放这些函数,甚至分类存放封装好的类。
  这就是最常见的两种编程语言模式。接着,我们来说说语言成分。我想大家应该会经常会纠结变量或函数的命名吧?(我就经常纠结这个问题)给函数命名的时候,我们一般会使用动词,或者动词性质的词。函数式语言的句子,最核心的当然是函数。也就是说,是函数(动词)主导了句子。面向对象的模式虽然看似是对象在主导句子,实际上,对象只是封装了的函数式语言的一些东西而已。两种模式的本质是相同的,对象(或者说句柄)主导的不是句子,而是程序逻辑。这里暂时不讨论它,我们现在关心的是语言的句子,不是整个程序的逻辑。
  自然语言中也是谓语动词在主导着句子,根据谓语动词的不同,所接的宾语数量与类型也不同,甚至谓语动词还影响着主语。谓语动词有很多分类,比如不及物动词与及物动词(自动词与它动词)。不及物动词可以不需要宾语,比如“张三死了”,张三就这么死了,不需要宾语。如果换成面向对象的编程语言来理解就是“zhangsan.die()”。但是自然语言会有歧义,比如“张三死了”这句,他是现在死的,还是昨天死的?而“zhangsan.die()”就没有歧义,代码执行之前他还活着,执行之后他死了。因为编程语言的时间观念是线性的(多线程的情况会比较复杂),通常是一行代码一个时间点,代码的执行意味着时间的流逝。所以作为方法或函数名使用时,动词是不需要任何时态的。自然语言则不同,它的时间有跳跃性,如果不指定时间就会有歧义,而且自然语言的动词都需要时态支持。其实某些编程语言中也有这样的歧义句,我们称谓“未定义行为”(之前也有相关的文章“JavaScript中的未定义行为”如果有兴趣可以看看)。由于代码通常是一行一个时间点,所以在小于行的单位下执行多个代码就会出现歧义的问题。当然,有些编程语言的时间点是小于行的,所以这样的问题就比较少。
  现在回头来看看函数式语言中的写法“die(zhangsan)”,和刚才的面向对象的写法相比虽然功能上没有差别,但是会有一种诡异的感觉。这个“zhangsan”到底是主语还是宾语呢?刚刚我就说了,“die”在这里是不及物动词的用法,它本身没有宾语的需求。那么“zhangsan”就是主语了?感觉也不对吧,我们换个及物动词例子。比如“zhangsan.kill()”,“kill”是及物动词(这是现在对它的定义,虽然它也有不及物动词的用法),描述为“某人杀死了张三”。如果写成函数式的就很容易理解“kill(zhangsan)”。显然,“zhangsan”是宾语吧。那主语是谁?我们要找出这个凶手才行!是CPU执行了这个代码,但是CPU不是凶手是凶器,凶手是代码的作者。这代码谁写的?我写的,好吧,我就是凶手。也就是说,主语是我,我主观上要“kill zhangsan”所以才会写出这段代码。但是显然我无法变成代码把自己写在函数里,所以这里省略了主语。面向对象的“zhangsan.kill()”和这个代码是等价的,所以也是作为宾语。现在我们再回头看之前的“die”,那时候“zhangsan”是主语。现在我们就明白了,编程语言在语序上是主宾不分的,语言成分取决于谓语动词,也就是函数或方法的定义。既然在语序上没有差别,我们就可以把它统一成某一种,以便容易表达。所以,我们在编程语言中描述的对象都当作宾语。另外,宾语的英文是“object”,这就是为什么面向对象是“object oriented”。
  好吧,暂时就说这些,下次的文章再写,内容有点多了,我也需要整理下思路,文中有错误的地方希望大家指出以便修改。
网名:
3.80.55.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^