为什么我喜欢Smalltalk?

openkk 13年前
     <p id="page-note">本文是从 <a href="/misc/goto?guid=4958190601831965586">Why I love Smalltalk</a> 这篇文章翻译而来。</p>    <p style="text-align:center;"><img title="2011091607520653.gif" border="0" alt="2011091607520653.gif" src="https://simg.open-open.com/show/dd713a8d8121b7dd38c3e1f1d30d4309.jpg" /></p>    <p> C,C++,Python等,这些算是传统的语言吧,我从这些语言上学会了基本的编程技术。这之后,又有四种语言,它们让我学到了一些新的东西。这些语言改变了我思考的模式,虽然我从来没有使用过它们,但它们都是绝对值得你学习一下的。它们是:</p>    <ul>     <li>Smalltalk</li>     <li>Lisp</li>     <li>Erlang</li>     <li>Haskell</li>    </ul>    <p> 你也许还会把Prolog加入这个列表中,但我没有学过Prolog。本文是关于Smalltalk这种语言的。</p>    <p> 我的目的并不是教大家怎么使用Smalltalk,而是向你展示一些Smalltalk能做到、而其它语言做不到的一些事情(声明:有些语言也能做到,它们都是Smalltalk的一些方言)。不用说,我需要向你先介绍一下这种语言的一些基本知识,之后我才能向你展示更有价值的东西,那么就开始吧,第一个程序:</p>    <blockquote>     1 + 1    </blockquote>    <p> 很显然,计算的结果是2.如果你想把它存到一个变量里,这样做:</p>    <blockquote>     m := 1 + 1    </blockquote>    <p> 句子都要以点号(句号)结尾,像这样:</p>    <blockquote>     m := 1.     <br /> m := m + 1    </blockquote>    <p> 在<a href="/misc/goto?guid=4958190602578158770">Squeak</a>——这是Smalltalk语言的一种版本实现——里,有一个对象叫做Transcript,你把消息发送给它,它能把消息显示到屏幕上。它很像一个Log窗口。你要这样去用它:</p>    <blockquote>     Transcript show: 'Hello world'    </blockquote>    <p> 运行的效果会是这样:</p>    <p style="text-align:center;"><img title="为什么我喜欢Smalltalk?" border="0" alt="为什么我喜欢Smalltalk?" src="https://simg.open-open.com/show/d65a5b6cfc3cb2cf2ed85d043a257f41.jpg" /></p>    <p> Smalltalk的这种语法非常的独特。消息(message)——这在其它语言里也叫做“方法”——是<code>show:</code> (包括冒号),它接受一个参数。我们用下面的写法可以让这个句子运行10遍:</p>    <blockquote>     10 timesRepeat: [     <br /> Transcript show: 'Hello world'     <br /> ]    </blockquote>    <p> 现在你开始能看出Smalltalk的独特之处了。我把消息<code>timesRepeat:</code>发送到对象“10”——一个<code>Integer</code>类。这N次的循环操作是由这个<code>Integer</code>来执行的,你认真想想,其实很有道理。</p>    <p> 第二个有趣的部分是代码段落(block),是在方括号里面的部分。你可能认为它跟其他种语言里的代码段落语法是同样的道理,比如Java的:</p>    <blockquote>     for(int i=1; i<11; i++){     <br /> System.out.println("Hello world");     <br /> }    </blockquote>    <p> 但你要是从Smalltalk的视角来看,你会发现它强大的多。它实际上是个<a href="/misc/goto?guid=4958184380951356631">闭包(closure)</a>。看这段:</p>    <blockquote>     t := [     <br /> Transcript show: 'Hello world'     <br /> ]    </blockquote>    <p> 现在,我有了一个叫做<code>t</code>的变量,它的类型是<code>BlockClosure</code>,通过这个变量,我可以做我想做的任何事情。如果我向它发送<code>class</code>消息,它会返回它的class类型:</p>    <blockquote>     t class    </blockquote>    <p> 如果我向它发送<code>value</code>消息,它会运行,会在Transcript里留下“Hello World”字符:</p>    <blockquote>     t value    </blockquote>    <p> 让我们多看几段程序。一个没有任何参数的消息:</p>    <blockquote>     10 printString    </blockquote>    <p> 带有一个参数的消息:</p>    <blockquote>     10 printStringBase: 2    </blockquote>    <p> 带有两个参数的消息:</p>    <blockquote>     10 printStringBase: 2 nDigits: 10    </blockquote>    <p> 很可爱,不是吗?这个方法叫做<code>printStringBase:nDigits:</code>。我没在其它地方见过这样的语法;只有Objective-C是个例外,因为它是从Smalltalk承袭过来的。</p>    <p> 小玩意已经说的不少了,现在说点复杂点儿的东西。我们来创建一个类:</p>    <blockquote>     Object subclass: #MyClass     <br /> instanceVariableNames: ''     <br /> classVariableNames: ''     <br /> poolDictionaries: ''     <br /> category: 'Pupeno'    </blockquote>    <p> 注意,一个类的创建是通过向其它类发送消息—包括名字和一些参数,告诉它我要继承它。这是一个消息,跟其它类型的方法调用一样。对象是类,类也是对象。Smalltalk的对象模式非常的优雅,但这是另外一个话题。</p>    <p> 现在我们有了一个类,我们来创建一个方法,叫做greet:就在这个类里。</p>    <blockquote>     greet: name     <br /> "Greets the user named name"     <p>message</p>     <p>message := 'Hello ', name.<br /> Transcript show: message.</p>    </blockquote>    <p> 在方法定义里,首先我们给这个方法加了一个注释,然后是管道(“”)包着的本地变量,然后是方法的实现,我把”Hello“放到了变量message里,然后用逗号符把它和变量name连接起来。然后我把它发送到Transcript里。</p>    <p> 运行起来的结果像这样:</p>    <p style="text-align:center;"><img title="为什么我喜欢Smalltalk?" border="0" alt="为什么我喜欢Smalltalk?" src="https://simg.open-open.com/show/2db3e4b5329e17d63692cbe552e75943.jpg" /></p>    <p> 好了,我们来用一用它:</p>    <blockquote>     m := MyClass new.     <br /> m greet: 'Pupeno'    </blockquote>    <p> 为了创建一个类<code>MyClass</code>的对象,我们向这个类发送<code>new</code>消息。这个<code>new</code>并不是像Java里的关键字。<code>new</code>是一个方法。你可以看它的源代码,覆盖它,等等。不要动它,除非你十分清楚你在做什么。</p>    <p> 事实上,如果你想一下,你会发现我们没有看到任何的关键字。看看我们写过的这些代码,没有什么要记住的关键字!更重要的,目前为止,你已经基本的认识Smalltalk了。Smalltalk就是这些,但就像是一个小积木块,这些小块能让你搭建出你想要的任何东西。</p>    <p> 不错,就这些,我要说的就这些。我们看到了,Smalltalk里没有循环,它有整数类,这个类里实现了<code>timesRepeat:</code>消息,可以用来把事情重复执行N次。像这样用于循环操作的方法到处都是。</p>    <p> 你会问,有没有<code>if</code>这个关键字?Smalltalk里肯定有一个<code>if</code>关键字,不是吗?不,没有。你所谓的<code>if</code>语法在Smalltalk里可以用你刚才看到的类和消息传递的机制实现。为了好玩,我们来实现一个。</p>    <p> 我们从创建一个<code>PBoolean</code>类开始,然后两个继承它的类——<code>PTrue</code> 和 <code>PFalse</code>。</p>    <blockquote>     Object subclass: #PBoolean     <br /> instanceVariableNames: ''     <br /> classVariableNames: ''     <br /> poolDictionaries: ''     <br /> category: 'Pupeno'     <p>PBoolean subclass: #PTrue<br /> instanceVariableNames: ''<br /> classVariableNames: ''<br /> poolDictionaries: ''<br /> category: 'Pupeno'</p>     <p>PBoolean subclass: #PFalse<br /> instanceVariableNames: ''<br /> classVariableNames: ''<br /> poolDictionaries: ''<br /> category: 'Pupeno'</p>    </blockquote>    <p> 我们之前创建了一个类,MyClass,我们要给它定义一个<code>equals:</code>方法,它能返回true和false,也就是我们的<code>PTrue</code> 和 <code>PFalse</code>。</p>    <blockquote>     equals: other     <br /> ^ PTrue new    </blockquote>    <p> 这个小帽子,<code>^</code>,是返回的意思。我写的是硬编码让它返回true。现在我们可以在程序来用它了:</p>    <blockquote>     m1 := MyClass new.     <br /> m2 := MyClass new.     <br /> m1 equals: m2    </blockquote>    <p> 得到的是true。我们已经接近目标了,但还不是<code>if</code>。<code>if</code>应该是个什么样子?它的样子应该是这样:</p>    <blockquote>     m1 := MyClass new.     <br /> m2 := MyClass new.     <br /> (m1 equals: m2) ifTrue: [     <br /> Transcript show: 'They are equal'; cr     <br /> ] else: [     <br /> Transcript show: 'They are false'; cr     <br /> ]    </blockquote>    <p> 估计你在想,怎么才能实现这样的效果。我在<code>PTrue</code>里加入了一个方法:</p>    <blockquote>     ifTrue: do else: notdo     <br /> ^ do value    </blockquote>    <p> 这个方法看上去是接受2个参数,但执行时接受第一个,忽略第二个。对于<code>PFalse</code>,正好相反:</p>    <blockquote>     ifTrue: notdo else: do     <br /> ^ do value    </blockquote>    <p> 这就可以了。一个可以用的<code>if</code>!如果让我说,我觉得这真的很神奇。如果你去检查Squeak了的代码,你会发现它里面的<code>if</code>就是这样实现的:</p>    <p style="text-align:center;"><img title="为什么我喜欢Smalltalk?" border="0" alt="为什么我喜欢Smalltalk?" src="https://simg.open-open.com/show/a99a893c6fe73bc5a709f0f03ee61293.jpg" /></p>    <p> 如果你使用的编程语言能允许你创建像if条件这样的基本功能,那它就可以让你创建任何你想要的东西。<br /> <br /> 来自: <a id="link_source2" href="/misc/goto?guid=4958190603986173430" target="_blank">外刊IT评论</a></p>