`
riali
  • 浏览: 41617 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

你的编程语言可以这样做吗?

阅读更多

繁体中文翻译见: 你的程式語言可以這樣做嗎?

emu翻译的版本

你的编程语言可以这样做吗?

From The Joel on Software Translation Project

<!-- start content -->

你的编程语言可以这样做吗?

有一天,你在浏览自己的代码,发现有两大段代码几乎一样。实际上,它们确实是一样的——除了一个关于意大利面(Spaghetti)而另一个关于巧克力慕思(Chocolate Moose)。

   // 一个小例子:
   
   alert("偶要吃意大利面!");
   alert("偶要吃巧克力慕思!");

嗯,这个例子碰巧是用javascript写的,不过你就算不懂JavaScript,应该也能明白它在干什么。

拷贝代码不好。于是,你创建了个函数

   function SwedishChef( food )
   {
       alert("偶要吃" + food + "!");
   }
   SwedishChef("意大利面");
   SwedishChef("巧克力慕思");

Ok,这只是一个很小很小的例子而已,相信你能想像到个更实际一点的例子。这段代码有很多优点,你全都听过几万次了:可维护性、可读性、抽象性 = 好!

现在你留意到有另外两段代码几乎跟它们一模一样,除了一个反复调用一个叫BoomBoom的函数,另一个反复调用一个叫PutInPot的。除此之外,這两段代码简直没什么两样:

alert("拿龙虾");
PutInPot("龙虾");
PutInPot("水");
alert("拿鸡肉");
BoomBoom("鸡肉");
BoomBoom("椰子酱");

现在要想个办法,使得你可以将一个函数用作另一个函数的参数。这是个重要的能力,因为你更容易将框架代码写成一个函数(emu注:还记得template method模式吧?)。

   function Cook( i1, i2, f )
   {
       alert("拿" + i1);
       f(i1);
       f(i2);
   }
   Cook( "龙虾", "水", PutInPot );
   Cook( "鸡肉", "椰子酱", BoomBoom );

看看,我们居然把函数当成调用参数传递了!

你的编程语言能办到吗?

等等……假如我们已经有了PutInPot和BoomBoom这些函数的具体实现代码(而且又不需要在别的地方重用它们),那么用内联语法把它们写进函数调用里面不是比显式的声明这两个函数更漂亮吗?

   Cook( "龙虾", 
         "水", 
         function(x) { alert("pot " + x); }  );
   Cook( "鸡肉", 
         "椰子酱", 
         function(x) { alert("boom " + x); } );

耶,真方便!请注意我只是随手创建了个函数,甚至不用考虑怎么为它起名,只要拎着它的耳朵把它往一个函数里头一丢就可以了。

当你一想到作为参数的匿名函数,你也许想到对那些对数组里的每个元素进行相同操作的代码。

   var a = [1,2,3];
   for (i=0; i<a.length; i++){
       a[i] = a[i] * 2;
   }
   for (i=0; i<a.length; i++){
       alert(a[i]);
   }

常常要对数组里的所有元素做同一件事,因此你可以写个这样的函数来帮忙:

   function map(fn, a){
       for (i = 0; i < a.length; i++){
           a[i] = fn(a[i]);
       }
   }

现在你可以把上面的东西改成:

   map( function(x){return x*2;}, a );
   map( alert, a );

另一个常见的任务是将数组内的所有元素按照某总方式汇总起来:

   function sum(a){
       var s = 0;
       for (i = 0; i < a.length; i++)
           s += a[i];
       return s;
   }
   
   function join(a){
       var s = "";
       for (i = 0; i < a.length; i++)
           s += a[i];
       return s;
   }
   
   alert(sum([1,2,3]));
   alert(join(["a","b","c"]));

sumjoin长得很像,你也许想把它们抽象为一个将数组内的所有元素按某种算法汇总起來的泛型函数:

   function reduce(fn, a, init){
       var s = init;
       for (i = 0; i < a.length; i++)
           s = fn( s, a[i] );
       return s;
   }
   
   function sum(a){
       return reduce( function(a, b){ return a + b; }, a, 0 );
   }
   
   function join(a){
       return reduce( function(a, b){ return a + b; }, a, "" );
   }

许多早期的编程语言没法子做这种事。有些语言容许你做,却又困难重重(例如C有函数指针,但你要在別处声明和定义函数)。面向对象语言也不确保你用函数可以干些啥(把函数当对象处理?)。

如果你想将函数视为一类对象,Java要求你建立一个有单方法的对象,称为算子对象。许多面向对象语言要你为每个类都建立一个完整文件,像这样开发可真叫快。如果你的编程語言要你使用算子对象来包装方法(而不是把方法本身当成对象),你就不能徹底得到现代(动态)编程语言的好处。不妨试试看你可否退货拿回些钱?

不用再写那些除了经过一个数组对每个元素做一些事情之外一无是处的函数,有什么好处?

让我们看回map函数。当你要对数组内的每个元素做一些事,你很可能不在乎哪个元素先做。无论由第一个元素开始执行,还是是由最后一个元素执行,你的结果都是一样的,对不?如果你手头上有2個CPU,你可以写段代码,使得它们各对一半的元素工作,于是乎map快了两倍。

或者,发挥一下想像力,设想你在全球有千千万万台服务器分布在全世界的若干个数据中心,你有一个真的很大很大的数组,嗯,再发挥一下想像力,设想这个数组记录有整个互联网的内容。还了,现在你可以在几千台服务器上同时执行map,让每台服务器都来解决同一个问题的一小部分。

那么在这个例子里面,编写一段非常快的代码来搜索整个互联网这个问题,其实就和用一个简单的字符串搜索器(算子)作为参数来调用map函数一样简单了。

希望你注意到一个真正有意思的要点,如果你想要把map/reduce模式变成一个对所有人都有用,对所有人都能立刻派上用场的技术,你只需要一个超级天才来写最重要的一部分代码,来让map/reduce可以在一个巨大的并行计算机阵列上运行,然后其他旧的但是一向在单一个循环中运行良好的代码,仍可以保持正确的运行,惟一的差别只是比原来单机运行快了n倍。这意味着它们都一不留神突然变成可以被用来解决一个巨大的问题的代码。

让我再啰嗦一下,通过把“循环”这个概念加以抽象,你可以把用任何你喜欢的方式来实现“循环”过程,包括可以实现让循环迭代速度随着硬件计算能力保持令人满意的同步增长。

你现在应该可以明白不久为何对那些对除了Java之外什么都沒被学过的计算机系学生表示不满了: (http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html)

不理解函数式编程,你就发明不了像MapReduce这样让Google的计算能力如此具有可扩展性的算法。Map和Reduce这两个术语源自Lisp语言和函数式编程.MapReduce概念对于任何还能记得他们的6.001-equivalent编程课上讲过“真正的函数式的程序应该没有任何副作用,可以轻易并行运行”的人来说是非常容易理解的。Google发明了MapReduce而微软没有,这一定程度上可以解释了为什么在google已经转下了他们的下一个目标(建设世界上最大型的超级并行计算机阵列Skynet)的时候微软还在想方设法让他们的最基础的搜索程序跑起来。我不觉得微软能完全了解在这一波浪潮中他们落后了多远。

我希望你现在明白,把函数当成基本类型的(动态)编程语言能让你在编程过程中更好的进行抽象化,也就是使代码精悍、功能更内聚、更具可重用性及更具有扩展性。很多的Google应用使用Map/Reduce模式,因此一有人对其优化或修正缺陷,它们就都可以从中得益。

我准备要再罗嗦一下,我认为最有生产力的编程语言莫过于能让你在不同层次上都可以进行抽象化的。老掉牙的FORTRAN 语言以前是不让你写函数的。C 有函数指针,可是它们都非常丑丑丑丑丑丑丑丑陋,不允许匿名声明,又不能在用它们时实现它们而偏偏要放在別处去实现。Java让你使用算子对象,一种更丑陋的东西。正如Steve Yegge所述,Java是個名词王国(http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html)

作者注:这里提起了FORTRAN,不过我上次使用FORTRAN是27年前的事了。FORTRAN是有函数的,我码字那会儿脑子里面想的大概是GW-BASIC语言。(emu注,basic确实只有所谓的子程序和go-sub语句,作用只是重新组织代码结构而已,没有参数和调用堆栈,因此没有真正的函数调用)

分享到:
评论

相关推荐

    西门子对于一个安全控制器哪种编程语言适合对它编程?.pdf

    在讨论西门子安全控制器的编程语言时,首先需要明确的是安全控制器(F-CPU)与常规控制器的区别。安全控制器的主要职责是在工业环境中负责安全功能,它们被设计来减少因设备故障而导致的安全风险。编程这些安全控制器...

    单片机编程语言中学习哪种编程语言好?

    单片机编程语言主要可以分为三大类:机器语言、汇编语言和高级语言。 机器语言是最底层的编程语言,它由一系列的二进制代码组成,直接对应CPU的指令集。由于机器语言直接由机器执行,运行速度快,但是它的编写和...

    07丨编程语言原理:面向对象编程是编程的终极形态吗?.pdf

    ”这个问题引发了一场关于编程语言原理的探讨。 在计算机科学的历史中,编程经历了多次演变。从早期的机械计算,到莱布尼兹的逻辑语言设想,再到雅卡尔的可编程织布机和Ada Lovelace的循环与子程序概念,编程的雏形...

    什么是仓颉编程语言,它的特点是什么?

    仓颉编程语言:什么是仓颉编程语言,它的特点是什么? 仓颉编程语言:什么是仓颉编程语言,它的特点是什么? 仓颉编程语言:什么是仓颉编程语言,它的特点是什么? 仓颉编程语言:什么是仓颉编程语言,它的特点是...

    《自制编程语言》相关资料1

    "自制编程语言相关资料" 本资源摘要信息是关于自制编程语言的相关资料,涵盖了编程语言的设计、实现和使用等方面。下面是从给定的文件中提取的知识点: 编程语言设计 * 编程语言的设计是指根据一定的规则和规范...

    编程语言原理(第10版

    根据提供的标题“编程语言原理(第10版)”及描述“编程语言原理(第10版 编程语言原理)”,我们可以推断出这本书主要讲述了编程语言的基础理论与实践应用,是学习和理解编程语言设计与实现的重要参考资料。...

    编程语言排行榜 编程语言排行榜

    编程语言排行榜编程语言排行榜编程语言排行榜编程语言排行榜编程语言排行榜编程语言排行榜编程语言排行榜编程语言排行榜编程语言排行榜编程语言排行榜编程语言排行榜

    自制编程语言基于C语言郑钢源代码

    《自制编程语言基于C语言郑钢源代码》的项目,是一项富有挑战性的技术实践,旨在帮助开发者理解编程语言的底层工作原理,以及如何...通过这个项目,你可以亲身体验到编程语言的奥秘,从而在软件开发的道路上更进一步。

    ST语言规则编程手册全面讲解ST语言

    ST语言,全称为Structured Text,是IEC 61131-3标准下的编程语言之一,常用于工业控制领域的PLC(可编程逻辑控制器)编程。ST语言以其丰富的表达能力和接近高级编程语言的语法特性,深受工程师们的青睐。本手册全面...

    Rust 编程语言入门.pdf

    Rust 编程语言入门 Rust 编程语言入门 Rust 编程语言入门 Rust 编程语言入门 Rust 编程语言入门 Rust 编程语言入门 Rust 编程语言入门 Rust 编程语言入门 Rust 编程语言入门 Rust 编程语言入门 Rust 编程语言入门 ...

    工业机器人使用的编程语言简介.pdf

    机器人的编程主要可以分为示教编程、动作级编程语言和任务级编程语言三个层次。在开发这些机器人时,常常使用C、C++、C++Builder、VB、VC等计算机语言,主要取决于其执行机构(伺服系统)的开发语言。机器人编程语言...

    编程语言原理(第10版)

    通过阅读《编程语言原理(第10版)》,读者不仅可以掌握编程语言的核心概念,还能深入了解语言设计的底层机制,从而具备分析、理解和设计新编程语言的能力。这不仅对软件开发人员,也对教学和研究工作具有深远的影响。

    编程语言Python算法集大全 .zip

    编程语言Python算法集大全 ,学习进步阶梯必备。编程语言Python算法集大全 ,学习进步阶梯必备。编程语言Python算法集大全 ,学习进步阶梯必备。编程语言Python算法集大全 ,学习进步阶梯必备。编程语言Python算法集...

    Plant Simulation编程语言SimTalk2.0官方说明_公众号@仿真社区Plant Simulation1

    Plant Simulation编程语言SimTalk 2.0官方说明 Plant Simulation编程语言SimTalk 2.0是Tecnomatix ...SimTalk 2.0语言是Plant Simulation软件中的一种强大且灵活的编程语言,可以帮助用户更好地模拟和控制模拟模型。

    (完整word)ST语言编程手册.doc

    ST 语言编程手册 ST 语言是一种编程语言,旨在提供一种简单、灵活和高效的编程体验。本手册将对 ST 语言的基本原理...ST 语言是一种功能强大且灵活的编程语言,它提供了多种编程机制和工具,可以满足不同的编程需求。

    ML编程语言

    ML语言的学习和研究,可以帮助我们理解编程语言中的一些基本概念,比如变量绑定、不可变性、函数绑定、数据结构、列表处理、选项类型等。 在函数式编程范式中,变量是不可变的,这意味着一旦变量被赋值,它就不能被...

    编程语言、技术问题解决方案和使用经验编程语言、技术问题解决方案和使用经验编程语言、技术问题解决方案和使用经验编程语言、技术问题解

    编程语言、技术问题解决方案和使用经验编程语言、技术问题解决方案和使用经验编程语言、技术问题解决方案和使用经验编程语言、技术问题解决方案和使用经验编程语言、技术问题解决方案和使用经验编程语言、技术问题...

    编程语言算法集/Rust

    编程语言算法集/Rust编程语言算法集/Rust编程语言算法集/Rust编程语言算法集/Rust编程语言算法集/Rust编程语言算法集/Rust编程语言算法集/Rust编程语言算法集/Rust编程语言算法集/Rust编程语言算法集/Rust编程语言...

Global site tag (gtag.js) - Google Analytics