最近學(xué)習(xí)了一下Smalltalk,然后深深的喜歡上了這個(gè)古老的語(yǔ)言。Smalltalk語(yǔ)言只具有一個(gè)很小的語(yǔ)言核心,這個(gè)核心由大約10幾個(gè)關(guān)鍵字和一些基礎(chǔ)的面向?qū)ο笳Z(yǔ)義構(gòu)成。而且關(guān)鍵字都是象: . ; ( ) [ ] | := 之類(lèi)的簡(jiǎn)單符號(hào),并沒(méi)有提供最基本控制的流程。最開(kāi)始的時(shí)候這讓我很迷惑,雖然循環(huán)結(jié)構(gòu)可以用遞歸表示,但是分支怎么辦?然后發(fā)現(xiàn)了一個(gè)很酷的特性,Smalltalk可以?xún)H僅通過(guò)面向?qū)ο蟮恼Z(yǔ)義來(lái)實(shí)現(xiàn)分支結(jié)構(gòu)(其實(shí)就是State Pattern),具體的代碼如下

Boolean>>ifTrue: aBlock
  self subclassResponsibility

Boolean>>ifFalse: aBlock
  self subclassResponsibility

True>>ifTrue: aBlock
  ^aBlock value.

True>>ifFalse: aBlock
  ^nil.

False>>ifTrue: aBlock
  ^nil.

False>>ifFalse: aBlock
  ^aBlock value.

然后就可以,

4 〉3 ifTrue: [Transcript show: 'Hello']

因?yàn)樵赟malltalk里,一切皆對(duì)象且從左到右求值,于是4 > 3 返回true,true是類(lèi)True的唯一實(shí)例,然后就可以對(duì)它發(fā)送消息,ifTrue:,于是調(diào)用了^aBlock value.來(lái)對(duì)傳進(jìn)去的BlockClosure求值。


下面是類(lèi)似的java的類(lèi)似代碼。

 

 1public class abstract Boolean {
 2   public static final TRUE = new True();
 3   public static final FALSE = new False();
 4
 5   public abstract Object ifTrue(Block aBlock);
 6   public abstract Object ifFalse(Block aBlock);
 7}

 8
 9class True extends Boolean {
10
11   public Object ifTrue(Block aBlock) {
12       return aBlock.execute();
13   }

14
15   public Object ifFalse(Block aBlock) {
16       return null;
17   }

18}

19
20class False extends Boolean {
21
22   public Object ifTrue(Block aBlock) {
23       return null;
24   }

25
26   public Object ifFalse(Block aBlock) {
27       return aBlock.execute();       
28   }

29}

30

4 〉3 ifTrue: [Transcript show: 'Hello']就可以對(duì)應(yīng)翻譯為:

 

1Boolean condition = new Integer(4).isGreaterThan(new Integer(3));
2condition.ifTrue(new BlockClosure() {
3   public Object execite() {
4      System.out.println("Hello");
5      return null;
6   }

7}
);
8
9

這個(gè)看似簡(jiǎn)單的應(yīng)用,卻帶來(lái)了兩個(gè)有深刻影響的性質(zhì)。

第一,由于if,else等結(jié)構(gòu)不再是預(yù)定義的語(yǔ)法了,而與我們自己寫(xiě)的代碼一樣,屬于莫一個(gè)類(lèi)的特定消息,那么也就意味著,我們可以像ifTrue一樣,定義自己的分支結(jié)構(gòu)。
比如
   aUser ifNotRegistered: [ do redirect to register page ]
         ifExpired: [ do redirect to active page ]

在不考慮性能優(yōu)化的前提下,Smalltalk認(rèn)為和
   4 >3 ifTrue: [do something]
        ifFalse: [do somthing]

是具有一樣的語(yǔ)義的。并不因?yàn)锽oolean屬于Kernel就有什么不同。因此控制結(jié)構(gòu)也屬于一個(gè)可編程的因素,這就是Smalltalk的輕語(yǔ)法特性。

第二,在簡(jiǎn)單的語(yǔ)法和完全的面向?qū)ο笳Z(yǔ)義中,構(gòu)造與馮諾依曼式語(yǔ)言完全等價(jià)的能力(這種能力在語(yǔ)法上表現(xiàn)為賦值,分支,迭代和子程序調(diào)用),于是我們可以完全用一致的面向?qū)ο蟮姆椒▉?lái)構(gòu)造軟件。

很長(zhǎng)一段時(shí)間以來(lái),我都認(rèn)為面向?qū)ο蠓椒ㄕ撌窃诿钍降鸟T諾依曼式語(yǔ)言的基礎(chǔ)上,通過(guò)引入類(lèi)型系統(tǒng)然后修修補(bǔ)補(bǔ)的得到的,由于馮諾依曼語(yǔ)言式的語(yǔ)言是面向操作層面上的,只是為了更好的刻畫(huà)操作計(jì)算的一個(gè)命令的序列,因此馮語(yǔ)言不可避免的具有不完備的語(yǔ)義,混亂的抽象表達(dá)以及等等一系列的問(wèn)題。作為馮語(yǔ)言的一個(gè)大補(bǔ)丁的面向?qū)ο蠓椒ǎ乙蚕氘?dāng)然的以為他雖然有了些進(jìn)步,但是基礎(chǔ)問(wèn)題上面還是不能避免的,加之面向?qū)ο笕狈σ环N一致的構(gòu)造方法,很多時(shí)候我們不得不回歸到命令式或者過(guò)程式的方法來(lái)構(gòu)造系統(tǒng),從而破壞掉一種一致清晰的思路,在過(guò)程和對(duì)象之間不住地權(quán)衡(比如Domain Model之爭(zhēng)),這個(gè)讓人非常的不爽。在嘗試了一些面向?qū)ο笳Z(yǔ)言之后(我是在95年接觸C++的時(shí)候開(kāi)始了解面向?qū)ο蟮模笾饕褂肑ava做為開(kāi)發(fā)語(yǔ)言),我發(fā)現(xiàn)這個(gè)問(wèn)題是很難避免,于是我斷言這是面向?qū)ο蠹夹g(shù)本身的問(wèn)題,現(xiàn)在看來(lái)不過(guò)自己所學(xué)有限,沒(méi)有真正用過(guò)純面向?qū)ο笳Z(yǔ)言而已,汗顏得很啊。這里向面向?qū)ο蠓椒ǖ纻€(gè)歉,嘿嘿。