`

四个程序员的一天

阅读更多
你,一个DotNet程序员,刚刚加入一个新项目组。除了你之外,其他的成员包括:Ceer,一直从事C项目的程序员,他刚刚转入C#不到一个月; Jally,整天抱着本Design Pattern(没错,就是GoF的那本)在啃的前Java程序员;以及Semon,你对他完全不了解,只是听PM介绍说他是搞Scheme的(传说中的第二古老的语言LISP的方言之一)。不过你也没在意,毕竟计算机这玩意,老东西是不吃香的。

  周一,刚打开电脑,老板就跑到你们组的办公座面前:“好吧,伙计们,现在有个function需要你们来搞定。具体是这样的:用户输入2个数,并输入一个操作符。你根据输入的情况来得出相应的运算结果。“

Example: Foo(+, 1, 2) = 3; Foo(*, 3, 6) = 18; Foo(/, 2, 4) = 0.5


  Ceer最先作出反应:简单嘛,判断一下输入的操作符就好了。说着,他很快在白板上写出如下代码:

 

public class CStyle_Calculator
{
 static public double Foo(char op, double x, double y)
 {
  switch(op)
   case ’+’: return x + y; break;
   case ’-’: return x - y; break;
   case ’*’: return x * y; break;
   case ’/’: return x / y; break;
   default: throw new Exception(”What the Hell you have input?");
 }
}
 
  Jally只看了一遍,就捂着鼻子连连摇头:好一股的代码臭味。还不如看我用OO的方法来解决:

public interface I操作符 //谁说代码不能写中文的?恩恩
{
 double 运算(double x, double y);
}

public class OO_Calculator
{
 private I操作符 m_op;
 public OO_Calculator(I操作符 op)
 {
  this.m_op = op; //依赖注入【注2】
 }

 public double Foo(double x, double y)
 {
  return this.m_op.运算(x, y);
 }
}

public class 加法:I操作符
{
 public double 运算(double x, double y)
 {
  return x + y;
 }
}

public class 减法:I操作符
{
 public double 运算(double x, double y)
 {
  return x - y;
 }
}

public class 乘法:I操作符
{
 public double 运算(double x, double y)
 {
  return x * y;
 }
}

public class 除法:I操作符
{
 public double 运算(double x, double y)
 {
  return x / y;
 }
}

public class TheMainClass
{
 static public void Main()
 {
  I操作符 我的加法 = new 加法();
  OO_Calculator 我的加法器 = new OO_Calculator(我的加法);
  double sum = 我的加法器.Foo(3, 4);
  System.Console.WriteLine(sum);
  //sum = 7

  //其他3个我就不废话了
 }
} 
 
  你看着Jally把白板写得密密麻麻之后,耸耸肩,暗叹,你们这些用java的废柴,就一个运算器还搞出Interface这些东西,烦不烦啊。 让你们见识见识DotNet的强大吧. 那个运算符我直接用delegate传进去不就好了么.

public delegate double TheOperator(double x, double y);

public class Operators
{
 static public double Add(double x, double y)
 {
  return x + y;
 }

 static public double Sub(double x, double y)
 {
  return x - y;
 }

 //乘,除法 我也懒得废话了
}

public class DotNet_Calculator
{
 public double Foo(TheOperator op, double x, double y)
 {
  return op(x, y);
 }
}

public class TheMainClass
{
 static public void Main()
 {
  TheOperator myAdd = new TheOperator(Operators.Add);
  TheOperator mySub = new TheOperator(Operators.Sub);

  DotNet_Calculator dc = new DotNet_Calculator();
  double sum = dc.Foo(myAdd, 2, 4); //sum = 6
  System.Console.WriteLine(sum);
  double sub = dc.Foo(mySub, 3, 7); //sub = -4
  System.Console.WriteLine(sub);
 }
}
 
//dot net 下面还可以用CodeDom动态构造C#代码,然后在内存编译运行。
//如果觉得专门写个Operators很烦的话,可以试试C#2.0的匿名方法

  很好,当你写完代码之后,挑衅的看着Jally,Ceer却开始抱怨起来:”这不就是C里面的函数指针么,我也会...“

  “然则DotNet下面的Delegate是类型安全滴...”你继续洋洋得意.

  而Semon,看了看你们3位华丽的代码,啥也没说,只是在键盘上敲下了2行代码

(define (Foo op x y)
(op x y)) 
 
  然后就下班了...

  【注: scheme的代码稍微解释下:(+ 1 2) = 3, (* 3 4) = 12.】

  至于Semon的解法:

(define (Foo op x y)
(op x y)) 
 
  看明白了么,上面的代码只有一个作用:第一行是函数头,定义了一个叫Foo的函数。该函数接受3个参数op, x, y。

  第二行定义了函数的行为:把第一个参数op当作运算符,计算后面2个参数。

  所以:(Foo + 1 2) = 3. (Foo / 12 6) = 2.

  好了好了,不编故事了。

  我只是想简单的让大家在繁忙的工作之余,也瞅瞅Function Programming(函数编程)世界的美妙。函数编程,最大的特点是它是将函数作为语言里1st class的元素来对待的。一个函数可以接受另一个函数作为参数,也可以把一个函数作为结果来返回。这样的函数我们称为Higher-order function。

  那么,Function Programming和我们传统的面向对象有啥区别捏? 恩,这个嘛,扯得远可以扯到图灵机和冯·诺以曼这2种体系的差异...@_@不过那个太学术性,俺就不说了。不过有句话可以较好的概括FP和OO的区别(好吧,这个也是抄“紫皮书”上面的):
 
  “Pascal是为了建造金字塔...Lisp是为了建造有机体...”“作为Lisp的内在数据结构,表对于这种可用性起着重要的提升作用...”“采用100函数在一个数据结构上操作,远远优于采用10个操作在十个数据结构上工作”“金字塔矗立在那里千年不变,而有机体则必须演化,否则就会消亡”。

  而另一个总结得比较好的话是:(同样是抄来的)

  一个对象:一组相同的运算上面,外加不同的数据。(想想你的object,是不是这样的?)

  一个Closure:一组相同的数据,外加不同的操作。(Delegate就是这样的思想,有兴趣的话也可以去看看Ruby)

  基本上,恩,没啥说的了。 如果你感兴趣的话,可以去看MIT SICP的课程(有在线版的,MIT也作为Open Course开设了的) 
19
14
分享到:
评论
25 楼 匡建武 2016-01-18  
Good
24 楼 IamSungod 2010-04-18  
俺来凑个热闹,写一段可运行的Scala代码:
object TestOperation {
  def main(args : Array[String]) : Unit = {
	  println (Foo(_+_,1,2))
	  println (Foo(_/_,3,4))
  }
  
  def Foo(op:(Double,Double) => Double,x:Double,y:Double) =
  {op(x,y)}
}
23 楼 justjavac 2009-05-14  
xieye 写道

看一大堆简单的代码的时间 < 看很少但难懂的代码的时间

经典,哈哈,精辟
22 楼 justjavac 2009-05-14  
luck_donkey 写道

看起来简单就是美,越接近问题的领域的语言使用起来就显得越简单。

21 楼 wufan0023 2008-03-14  
代码实现的方式真的非常多,但OO的结果就是好一点。
20 楼 lz726 2008-03-13  
不同的写法又不同的好处.具体问题具体分析.
19 楼 luck_donkey 2008-03-13  
看起来简单就是美,越接近问题的领域的语言使用起来就显得越简单。
18 楼 java9981 2008-03-13  
oop是为了应付复杂多变的问题的,
如果问题稍有变化,不知会如何,
如加入一种自定义操作
17 楼 Kaede 2008-03-12  

呵呵 很多人都是 被各种思想 套牢了
做点东西 就结合各种编程思想。

先这样的问题,简单 解决问题 就好。
16 楼 ericxu131 2008-03-12  
看来我就类似那个java的废柴
15 楼 xieye 2008-03-12  
看一大堆简单的代码的时间 < 看很少但难懂的代码的时间
14 楼 xiucai315 2008-03-12  
不适应看中雯编程..谁叫我没用过呢?不过看了真的挺受用的
13 楼 wintersun 2008-03-12  
就像Design Pattern一样,不同的模式,需要应用在具体合适的场合,不能一概而论。函数编程、闭包也有自己的使用范围,OO也有自己的适用场合,不是一杆子打死。两者结合将是最强大的组合。 欢迎加入Groovy!呵呵,怎么变成打广告了!
12 楼 hax 2008-03-12  
fp虽好,楼主也不能这样投机取巧。只因scheme允许运算符作为函数使用而已。如果是其他要自定义的函数,那其实这个小例子上也看不出什么差异。

因为c#已经变得很接近fp了。



我再给个johnson的写法:

function foo(op, x, y) {
return eval('x'+op+'y')
}

foo('+', 1, 2)   ==> 3
11 楼 tangfeng 2008-03-12  
Scheme的代码量很大时,你读代码也会疯!
10 楼 sunwei_07 2008-03-11  
刚看到描述Semon的时候,2行代码。第一感觉:好酷
但是如果真的那么简单,每人都容易学会,那我还有存在的意义么……大家都会
9 楼 daisy 2008-03-11  
太牛了,原来编程可以这样呀! 
8 楼 weiertzw 2008-03-11  
晕,在python中国社区都看烂了快。。。
7 楼 lenovo 2008-03-11  
收藏一下 
6 楼 hyl1234 2008-03-11  
不错,的确很多事情换个方向去想,会方便的很多。

相关推荐

    什么样的人适合做程序员?程序员应该具有什么样的素质程序员四大禁忌

    ②禁得起熬夜,一个程序不是一天两就能做好的,有时写程序刚进入状态,此时即使夜已深,也不能(不愿)停下来。 ③要严谨细心,程序设计语言不是人的自然语言,本身就是严格的,程序员有一处不小心,都可能导致所...

    疯狂程序员(一个大学生程序员的成长经历)

    第一天到学校,其实没有一点新鲜的感觉。绝影的舅舅和舅妈就在这里教书,早在这学校还不叫“大学”的时候,绝影已经在学校足球场学骑自行车了。 要说念大学,最忌讳的就是在自己家门口念。哪怕你就住北大院子,也...

    程序员如何提高英语水平.pdf

    英语沟通能力的难度按顺序可分为"听说写读"这四个方面。其中,想"听说"能达到英美人的水平确实很难。但另一方面令人费解的是,不少外国人在"写读"(特别是写)方面的能力也不怎么高明。这对"程序员如何能提高英语水平...

    程序员的SQL金典.rar

     11.7.4 计算销售单制单日期所在月份的第一天和最后一天  11.8 结果集转置  11.8.1 将结果集转置为一行  11.8.2 把结果集转置为多行  11.9 递归查询  11.9.1 Oracle中的CONNECT BY子句  11.9.2 Oracle中的SYS...

    程序员的SQL金典4-8

     11.7.4 计算销售单制单日期所在月份的第一天和最后一天  11.8 结果集转置  11.8.1 将结果集转置为一行  11.8.2 把结果集转置为多行  11.9 递归查询  11.9.1 Oracle中的CONNECT BY子句  11.9.2 Oracle中的SYS...

    程序员英语单词 带音标

    音标都是我自己一个一个自己查的,给点辛苦分吧!花了三四天时间,10分不想贵!

    C/C++程序员面试指南.杨国祥(带详细书签).pdf

    面试题27:张老师的生日是哪一天 面试题28:谁是M小姐的情人 面试题29:他们分别是哪国人 面试题30:他们分别是做什么的 面试题31:他们都会说什么语言 面试题32:怎么把马匹从甲村拉到乙村 面试题33:谁打碎了花瓶 ...

    JSP程序员成长手册

    5:sql 学习时间,只需要知道insert ,delete ,update ,select,create/drop table的话一天你应该知道了。 6:xml 学习时间,我不知道我还没有学会呢。呵呵。不过我知道DTD是用来做什么的。 7:ejb 学习时间,...

    奔跑吧,程序员:从零开始打造产品、技术和团队

    奔跑吧,程序员:从零开始打造产品、技术和团队这本书的文稿躺在我邮箱里好几天没有去看,主要原因是个人不太喜欢这个书名。在我 的想象中,这又是一本攒出来再蹭蹭娱乐节目热点的平庸之作。但是当我想起来,真正 ...

    《程序员》杂志2012年第7期

    本文从移动设备、Metro UI、编程的变化、Windows Store四个方面分析了Windows 8在移动互联网时代带来的影响与面对的挑战。 (3)游戏画面的印象价值和审美属性分析 (4)Cocos2D-X for XNA游戏开发指南(下)—...

    程序员的SQL金典6-8

     11.7.4 计算销售单制单日期所在月份的第一天和最后一天  11.8 结果集转置  11.8.1 将结果集转置为一行  11.8.2 把结果集转置为多行  11.9 递归查询  11.9.1 Oracle中的CONNECT BY子句  11.9.2 Oracle中的SYS...

    程序员的SQL金典7-8

     11.7.4 计算销售单制单日期所在月份的第一天和最后一天  11.8 结果集转置  11.8.1 将结果集转置为一行  11.8.2 把结果集转置为多行  11.9 递归查询  11.9.1 Oracle中的CONNECT BY子句  11.9.2 Oracle中的SYS...

    程序员的SQL金典3-8

     11.7.4 计算销售单制单日期所在月份的第一天和最后一天  11.8 结果集转置  11.8.1 将结果集转置为一行  11.8.2 把结果集转置为多行  11.9 递归查询  11.9.1 Oracle中的CONNECT BY子句  11.9.2 Oracle中的SYS...

    worldwindjava源码-97-Things-Every-Programmer-Should-Know:总结程序员应该知道的97件事

    世界风java源代码总结每个程序员应该知道的 97 件事 +10 作者:Kevlin Henney Takuto Wada,Dai Natsume 1. 技术债务 有技术债务是有意的,技术债务是由于粗心造成的。两者应该区分。这种技术债的存在应该永远记住并...

    四天学会Ajax技术

    十八个月前,Ruby 成了关注的中心,不知道 Ruby 的程序员只能坐冷板凳了。今天,如果想跟上最新的技术时尚,那您的目标就是 Ajax。 但是,Ajax 不仅仅 是一种时尚,它是一种构建网站的强大方法,而且不像学习一种...

    阿里巴巴笔试题大全

    阿里巴巴笔试题大全,包含近年笔试面试题,对程序员求职非常有用,物超所值

    四天学会ajax.doc

    Ajax 由 HTML、JavaScript™ 技术、DHTML 和 DOM 组成,这一杰出的方法可以将笨拙的...十八个月前,Ruby 成了关注的中心,不知道 Ruby 的程序员只能坐冷板凳了。今天,如果想跟上最新的技术时尚,那您的目标就是 Ajax。

    2009.6.19—30举办3S研讨会暨Google Earth与Google Map等仿真建模与共享及ARCGIS与遥感高级程序员培训班

    赠送网上三维建模软件及有关虚拟现实三维建模软件及其三个实例(.exe仿真交互式软件)及PPT;另赠送GOOGLE EARTH的演示示例及相关PPT与数据及二次开发资料;基于地图控件与VB开发的电子地图浏览器一套(用于GIS系统...

    GPT-4自我修复!国外小哥开发神级“金刚狼”,无限自我Debug

    要问程序员,一天中最烦的时候是什么? 那一定是给写好的程序Debug了。而现在,这种局面要得到改善了! 国外一名叫BioBootloader的开发者基于GPT-4搞了一个叫「金刚狼」的项目,能够自我修复Python脚本。 从名字就...

Global site tag (gtag.js) - Google Analytics