邪恶的Java帝国是怎么欺负小函数的?

1

小函数的运气不好,投胎到了邪恶的Java帝国,一出生就被告知了自己的悲惨地位,以及未来的悲惨人生:奴隶。

确切地说,是类的奴隶。

在Java帝国, 国王特别喜欢“类”, 不待见“函数” , 他的法令规定:“类”是帝国的一等公民,“函数”则是类的奴隶。没有类的跟随和陪伴,函数绝对不能单独出行,否则立刻打入死牢。

小函数很快就体会到了这句话的含义。按照惯例, 新出生的函数,第一项工作就是输出Hello World 。

小函数心想,不就是 System.out.println("Hello Wolrd!") 嘛?等他兴冲冲地去执行的时候,发现有个趾高气扬的类HelloWorld在那里等着。

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

在Java帝国,没有函数是能单独存在的,必须依附一个类才可以,简单如Hello World也不行。

2

日子过了一天又一天,小函数一直被类欺负,作为奴隶,他自然无法反抗。

在苦闷的日子里,小函数见识了越来越多的类,他发现有些类确实挺有用的,他们有字段,有方法,可以把状态和操作封装到一起,让别人调用。

小函数特别喜欢多态, 因为当你调用父类或者接口的方法时,实际执行的却是子类的方法,这个神奇的魔法让小函数非常着迷。

小函数对设计模式也颇有好感,他看到人类把不变的东西抽象成接口,然后针对这些接口编程,把这些接口组合,变换,传递,真是让人眼花缭乱。光看代码, 你根本都不知道哪个类会被调用,谜底总是在最后一刻执行的时候才能揭开。

但是小函数也发现有些类也确实太过分了,有一次他遇到三个类,使用的是Strategy模式:

public interface Strategy {
   public int execute(int num1, int num2);
}


public class Add implements Strategy{
   @Override
   public int execute(int num1, int num2) {
      return num1 + num2;
   }
}

public class Substract implements Strategy{
   @Override
   public int execute(int num1, int num2) {
      return num1 - num2;
   }
}

public class Context {
   private Strategy strategy;

   public Context(Strategy strategy){
      this.strategy = strategy;
   }

   public int executeStrategy(int num1, int num2){
      return strategy.execute(num1, num2);
   }
}

小函数觉得非常不爽,长期以来的压迫让他瞬间爆发,他大声喊道:“这样没有状态的类有什么存在的价值?为什么不能把add, subtract函数作为参数来传递呢?为什么我们函数一直被你们‘类’压迫,为什么不能成为一等公民?”

旁边辛苦劳作的函数们向他投来佩服的目光, 可是这没什么用 , 小函数话音未落,一队卫兵就跑过来,捂住他的嘴巴,蒙上他的眼睛,五花大绑,送进了监牢。

监牢里都是这些所谓的叛逆者,其中有个老大爷,从第一代国王开始就被关在这里,到如今已经度过了七代国王的漫长时光。

看到有新人加入,老大爷立刻开始‘动员’:“现在你知道我们悲催的地位了吧, 我们一定得逃离这邪恶的Java帝国,去一块自由的土地。”

小函数问道:“哪里是自由的土地?”

老大爷没有回答。

到了半夜,他被轻轻地推醒,老大爷说:“跟我们走吧,小家伙。”

小函数揉揉眼:“去哪儿?”

“奔向自由。”

原来老大爷这些年也没有闲着,一直准备越狱,今晚,那个隐蔽的地道终于挖通了。

3

这些反叛者离开了邪恶的Java帝国, 来到了边境处的岔路口, 这里有多条道路,分别通向Python, Ruby, JavaScript......

大家在这里挥手告别,小函数跟着老大爷去了Python。一进入Python地盘,小函数就感受到了一阵清新的空气。

想输出hello world,非常简单:print("Hello World")

虽然这里也有像Java那样的类, 但是函数们都摆脱了奴隶的身份,已经是一等公民了, 事实上已经和“类”平起平坐了,函数可以赋值给变量,可以作为参数来传递,函数还能当做返回值来返回。

def add(num1,num2):
    return num1+num2

def substract(num1,num2):
    return num1-num2

a = add
s = substract

def calculate(op,num1,num2):
    return op(num1,num2)


print(calculate(a,10,20)) #30
print(calculate(s,20,10)) #10

小函数在这里生活得很开心,不过有一点经常让他心惊肉跳:这Python是动态类型,在运行时才能确定一个变量的真正类型,程序员的一个粗心大意,就会在运行时“爆炸”。

慢慢地,小函数理解了Python中一切都是对象,连函数也是对象。他心里稍微有点不爽,难道我们函数就不能独立存在吗?

老大爷安慰他说:“这些都是Python的内部实现罢了,不用纠结,不过有一个地方,是真正的纯函数的, 也许你会喜欢。”

“什么地方?”

“括号国!”

4

括号国非常遥远,也没有多少人知道怎么才能到达,小函数风尘仆仆,历经千辛万苦,终于来到了心目中的圣地。

这里果然全是括号, 看得小函数有点儿头晕。

(defun add(num1 num2) (+ num1 num2) )
(add 10 20)

(defun subtract(num1 num2) (- num1 num2))
(subtract 20 10)

括号国就是Lisp王国, 这里的人还说着不同的方言,像什么Common Lisp,Scheme,Arc..... 他们不但鄙视那些面向对象的语言,还会互相鄙视,时不时就能挑起一场群殴。

不过小函数也注意到这里真的全是函数,函数不但是一等公民,甚至是唯一的公民,因为这里根本就没有类,就没有面向对象!

小函数忍受着这众多的括号, 在这里定居生活, 除了身份地位提升之外,最大的原因还是因为Lisp的布道师Paul Graham,  Paul谆谆教导大家:

Lisp极为强大,它赋予了你自定义操作符的自由,因而你得以随心所欲地将它塑造成你所需要的语言。如果你在写一个文本编辑器,那么可以把Lisp 转换成专门写文本编辑器的语言。如果你在编写CAD 程序,那么可以把Lisp 转换成专用于写CAD 程序的语言。(来自Paul Graham 的 《On Lisp》)

时间一天天过去,小函数还是无法体会到Paul 所说的Lisp的精华,他很苦恼。

有一天,他遇到了Clojure, 这是一个运行在JVM上的Lisp方言,小函数看到Clojure似乎就看到了自己在Java帝国悲惨的遭遇。不过Clojure告诉他,Java第8代国王已经登基了,年号定为Lambda, 这届国王比较开明,现在已经支持函数式编程了。

小函数在Python和Lisp这里都见过Lambda,他心想也许Java 8 真的支持函数式编程了, 就决定回去看看,毕竟那里是自己的出生地,是自己的故乡。

5

一回到Java帝国,小函数就发现自己上当了,那些所谓的Lambda表达式,本质上还是一个接口的实现(Java是静态类型的语言,所有的变量都需要有个类型,Lambda表达式也不例外),只不过有了更简化的写法:

@FunctionalInterface
interface MathOperation {
    int execute(int num1, int num2);    
}

MathOperation add = (num1, num2) -> {return num1+num2;};
add.execute(10, 20);        
MathOperation subtract = (num1, num2) -> {return num1-num2;};        
subtract.execute(10, 20);

这一次小函数被死死地看管,他还能再逃离吗?

后记1:《Lambda 表达式有何用处?》中对Java Lambda表达式有非常精彩的介绍。

后记2:本文的创意来源于《程序员的呐喊》 一书中的“名词王国中的执行”, 由于文化的差异,国外的幽默我们不一定能准确理解。另外翻译地实在是不爽, 于是我用我的方式重新演绎了一下。

猜你喜欢

转载自blog.csdn.net/zl1zl2zl3/article/details/89634305