2008-03-11
四个程序员的一天
关键字: 编程 java c 函数
你,一个DotNet程序员,刚刚加入一个新项目组。除了你之外,其他的成员包括:Ceer,一直从事C项目的程序员,他刚刚转入C#不到一个月; Jally,整天抱着本Design Pattern(没错,就是GoF的那本)在啃的前Java程序员;以及Semon,你对他完全不了解,只是听PM介绍说他是搞Scheme的(传说中的第二古老的语言LISP的方言之一)。不过你也没在意,毕竟计算机这玩意,老东西是不吃香的。
周一,刚打开电脑,老板就跑到你们组的办公座面前:“好吧,伙计们,现在有个function需要你们来搞定。具体是这样的:用户输入2个数,并输入一个操作符。你根据输入的情况来得出相应的运算结果。“
Jally只看了一遍,就捂着鼻子连连摇头:好一股的代码臭味。还不如看我用OO的方法来解决:
你看着Jally把白板写得密密麻麻之后,耸耸肩,暗叹,你们这些用java的废柴,就一个运算器还搞出Interface这些东西,烦不烦啊。 让你们见识见识DotNet的强大吧. 那个运算符我直接用delegate传进去不就好了么.
//dot net 下面还可以用CodeDom动态构造C#代码,然后在内存编译运行。
//如果觉得专门写个Operators很烦的话,可以试试C#2.0的匿名方法
很好,当你写完代码之后,挑衅的看着Jally,Ceer却开始抱怨起来:”这不就是C里面的函数指针么,我也会...“
“然则DotNet下面的Delegate是类型安全滴...”你继续洋洋得意.
而Semon,看了看你们3位华丽的代码,啥也没说,只是在键盘上敲下了2行代码
然后就下班了...
【注: scheme的代码稍微解释下:(+ 1 2) = 3, (* 3 4) = 12.】
至于Semon的解法:
看明白了么,上面的代码只有一个作用:第一行是函数头,定义了一个叫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开设了的)
周一,刚打开电脑,老板就跑到你们组的办公座面前:“好吧,伙计们,现在有个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开设了的)
评论
wufan0023
2008-03-14
代码实现的方式真的非常多,但OO的结果就是好一点。
swordinhand
2008-03-13
转载的吧
好几年以前在博客园上看过
好几年以前在博客园上看过
lz726
2008-03-13
不同的写法又不同的好处.具体问题具体分析.
luck_donkey
2008-03-13
看起来简单就是美,越接近问题的领域的语言使用起来就显得越简单。
java9981
2008-03-13
oop是为了应付复杂多变的问题的,
如果问题稍有变化,不知会如何,
如加入一种自定义操作
如果问题稍有变化,不知会如何,
如加入一种自定义操作
Kaede
2008-03-12
呵呵 很多人都是 被各种思想 套牢了
做点东西 就结合各种编程思想。
先这样的问题,简单 解决问题 就好。
ray_linn
2008-03-12
这不过是一个很无耻的例子而已,而且以前早在javaeye被我骂得狗血淋头了.
ericxu131
2008-03-12
xieye
2008-03-12
看一大堆简单的代码的时间 < 看很少但难懂的代码的时间
xiucai315
2008-03-12
不适应看中雯编程..谁叫我没用过呢?不过看了真的挺受用的
wintersun
2008-03-12
就像Design Pattern一样,不同的模式,需要应用在具体合适的场合,不能一概而论。函数编程、闭包也有自己的使用范围,OO也有自己的适用场合,不是一杆子打死。两者结合将是最强大的组合。 欢迎加入Groovy!呵呵,怎么变成打广告了!
hax
2008-03-12
fp虽好,楼主也不能这样投机取巧。只因scheme允许运算符作为函数使用而已。如果是其他要自定义的函数,那其实这个小例子上也看不出什么差异。
因为c#已经变得很接近fp了。
我再给个johnson的写法:
function foo(op, x, y) {
return eval('x'+op+'y')
}
foo('+', 1, 2) ==> 3
因为c#已经变得很接近fp了。
我再给个johnson的写法:
function foo(op, x, y) {
return eval('x'+op+'y')
}
foo('+', 1, 2) ==> 3
tangfeng
2008-03-12
Scheme的代码量很大时,你读代码也会疯!
sunwei_07
2008-03-11
刚看到描述Semon的时候,2行代码。第一感觉:好酷
但是如果真的那么简单,每人都容易学会,那我还有存在的意义么……大家都会
但是如果真的那么简单,每人都容易学会,那我还有存在的意义么……大家都会
daisy
2008-03-11
太牛了,原来编程可以这样呀!

weiertzw
2008-03-11
晕,在python中国社区都看烂了快。。。
lenovo
2008-03-11
收藏一下 
hyl1234
2008-03-11
不错,的确很多事情换个方向去想,会方便的很多。
zenny
2008-03-11
这个....本身这样的问题,就非常适合LISP来写,用这个来“引诱”大家,的确蛮震撼。看到这个FOO的问题,还没往下看,立马就联想到SICP,开头没几页就是这个样子的东东......不过,的确还是很美的,有数学的那种感觉。
freecode
2008-03-11
是要换换脑经了,不要整天oop的,把事搞得这么复杂。
发表评论
- 浏览: 35107 次
- 性别:

- 来自: 保定

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
一名合格的程序员需要掌握 ...
-- by xiaohuasuper -
一个程序员的爱恋
呵呵,我是作者 ^_^
-- by bluesnowstudio -
工厂模式----易懂版(转)
六、抽象工厂模式 先来认识下什么是产品族: 位于不同产品等级结构中,功能相关 ...
-- by justjavac -
工厂模式----易懂版(转)
五、小结 工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序 ...
-- by justjavac -
工厂模式----易懂版(转)
四、工厂方法模式 工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使 ...
-- by justjavac






评论排行榜