GNU Smalltalk

GNU Smalltalk是Smalltalk編程語言的GNU計劃實現。
這個實現不同於其他Smalltalk環境，使用文本文件作為程序輸入，並將其內容解釋為Smalltalk代碼。在這種方式下，GNU Smalltalk表現得更像是一種解釋器，而非傳統Smalltalk方式下的一種環境。GNU Smalltalk包括了對很多自由軟件庫的綁定，包括SQLite、libSDL、cairo、gettext和Expat等。

**簡單例子**
下面的例子可工作在GNU Smalltalk 3.0和以後版本上。經典的Hello, World!例子：
'Hello, World!' displayNl
GNU Smalltalk聲明瞭三個文件：stdin、stdout和stderr，作為文件串流類（FileStream）的全局實例，並綁定了適合傳遞給C虛擬機的值。對象類（Object）定義了特有於GNU Smalltalk的四個方法：print、printNl、store和storeNl。它們對接收者做一次printOn:或storeOn:至Transcript對象。這個對象是文本蒐集器類（TextCollector）的唯一實例，它通常將寫操作委託給stdout。 
一些基本的Smalltalk代碼：
"所有東西，包括一個文字，都是一個對象，所以如下可行:"
-199 abs.                                               "199"
'gst is cool' size.                                     "11"
'Slick' indexOf: $c.                                    "4"
'Nice Day Isnt It?' asLowercase asSet asSortedCollection asString "' ?acdeinsty'"
兩個"包圍的是註釋；$c是字符常量c；兩個'包圍的是字符串，字符串中的是'的轉義序列。

**蒐集**
構造和使用一個數組：
a := #(1 'hi' 3.14e0 1 2 (4 5)).
a at: 3.       "3.14"
a reverse.     "((4 5) 2 1 3.14 'hi' 1)"
a asSet        "Set(1 'hi' 3.14 2 (4 5))"
構造和使用一個散列表，它是散列蒐集類（HashedCollection）的子類即字典類（Dictionary）的實例：
hash := Dictionary from: { 'water' -> 'wet'. 'fire' -> 'hot' }.
hash at: 'fire'     "'hot'".
hash keysAndValuesDo:
('%1 is %2' % { k. v }) displayNl .
"=> fire is hot
**> water is wet"
"刪除 'water' -> 'wet'"
hash removeKey: 'water'
GNU Smalltalk在字符串類（String），和作為它的超類的數組式蒐集類（ArrayedCollection）之間，又介入了特有的字符數組類（CharacterArray），它的%方法，將其接收者中具有的特殊轉義序列，替換為由參數給出的蒐集中的元素，其中%n被替代為這個蒐集的第n個元素（1 或A ）。這裡給它的蒐集，是在{和}之間包圍的，當前Smalltalk變體一般都提供的動態數組，其中的元素可以在運行時間求值。

**塊和迭代器**
參數傳遞到是為閉包的一個塊：
"remember被綁定到一個塊."
remember :=  ('Hello, %1!' % { name }) displayNl .
"時機成熟時 -- 調用這個閉包!"
remember value: 'world'
"=> Hello, world!"
從一個方法返回由兩個閉包構成的一個數組：
Integer extend 
asClosure 

value := self.
^{  value := x .  value  }

.

blocks := 10 asClosure.
setter := blocks first.
getter := blocks second.
getter value.       "10"
setter value: 21.   "21"
getter value        "21"
這裡用extend為現存的類擴展新方法是GNU Smalltalk特有的語法。
下面的考拉茲猜想例子，展示將兩個塊傳遞給接收者，並將結果信息發送回到調用者：
Integer extend 
ifEven: evenBlock ifOdd: oddBlock 
^self even
ifTrue:  evenBlock value: self 
ifFalse:  oddBlock value: self 

.
10 ifEven:  n / 2  ifOdd:  n * 3 + 1     "5"
蒐集類（Collection）的collect:方法，將接收者的每個元素傳遞給一個塊來求值，返回這些結果的蒐集。這類似於函數式編程語言中map函數。例如計算從1到10的平方：
(1 to: 10) collect:  x squared  "(1 4 9 16 25 36 49 64 81 100 )"
可迭代類（Iterable）定義了由子類實現的do:方法，將一個塊迭代於接收者的每個元素之上。這也被稱為隱式迭代器。例如迭代於數組和區間之上：
array := #(1 'hi' 3.14e0).
array do:  item displayNl .
"=> 1"
"=> hi"
"=> 3.14"
(3 to: 6) do:  item displayNl 
"=> 3"
"=> 4"
"=> 5"
"=> 6"
可迭代類的inject:into:方法，接受一個參數和一個塊二者；它迭代於接收者的每個元素之上，在其上執行某個函數並保持結果為一個聚集。這類似於函數式編程語言中foldl函數。這個方法是憑藉調用do:方法實現的。例如：
#(1 3 5) inject: 10 into:  sum + element  "19"
在第一個趟時，這個塊接受10（要注入的實際參數）作為sum ，和1（這個數組的第一個元素）作為元素，結果為11。11接著成為在下一趟時的sum，這時向它加上3得到14。14接著加上5，最終返回19。
塊可以和很多內建方法一起工作，下面例子向一個文件寫一行文本，然後再讀取它的每一行並顯示：
(File name: 'file.txt') withWriteStreamDo:
file nextPutAll: 'Wrote some text.'; nl 
(File name: 'file.txt') readStream linesDo:
each displayNl  ; close
"=> Wrote some text."
文件類（File）的特有於GNU Smalltalk的name:方法，返回具有絕對路徑的文件名。GNU Smalltalk有特有的文件路徑類（FilePath），它的withWriteStreamDo:方法，對接收者調用writeStream方法打開一個只寫的文件串流類（FileStream）實例，在其上調用一個塊，並在這個塊的動態範圍結束處保證（ensure:）關閉這個串流；它的readStream方法，在接收者上打開一個只讀的文件串流類（FileStream）實例。
串流類（Stream）的特有於GNU Smalltalk的linesDo:方法，對它的接收者的每一行都求值它的參數塊一次。 在GNU Smalltalk中，文件串流類（FileStream）的超類，不再是作為可定位串流類（PositionableStream）子類的讀寫串流類（ReadWriteStream），而是其特有的作為串流類（Stream）子類的文件描述符類（FileDescriptor），它的close方法關閉這個文件。

**類**
GNU Smalltalk建立新類採用特有的語法形式：
超類名字 subclass: 新類名字 

pragmas
消息模式1  諸語句 
消息模式2  諸語句 
...
類變量1 := 表達式.
類變量2 := 表達式.
...
類似的，為現存的類擴展新方法採用特有的語法形式：
類表達式 extend 
...
在Smalltalk有關書籍中有一個常見版式約定，將一個類中的方法引用為類名字 >> 方法名字，這不是Squeak/Pharo語法的一部份，GNU Smalltalk將類名字 class >> 方法名字作為定義類方法的語法形式。
下面的代碼定義叫做Person的一個類，這個類有兩個實例變量name和age，它們有各自的變異子與訪問子。定義了有兩個關鍵字參數的類方法，用來創建新的類實例。定義了單獨用age來進行比較的方法，通過從Magnitude派生，這個類自動繼承了所有的其他比較方法的定義。這個類還通過覆寫printOn:的方式，定製了這個對象的打印（print）/顯示（display）方式：
Magnitude subclass: Person 

Person class >> name: name age: age 
^self new name: name; age: age; yourself


這裡用asSortedCollection方法對蒐集進行排序，然後用reverse方法來做反轉。最終結果是按age反序打印了三個人的信息：
OrderedCollection (Mark (63) Dan (23) Cod (16) )

**異常**
要發起能夠捕獲的異常，需要調用異常類（Exception）及其子類的signal或signal:方法。錯誤類（Error）表示不可恢復的致命錯誤，警告類（Warning）表示重要但可恢復的錯誤，停機類（Halt）表示通常是漏洞（bug）的可恢復錯誤。例如：
Error signal.
Error signal: 'Illegal arguments!'
異常通過塊閉包（BlockClosure）的on:do:方法來處理，還可以只捕獲特定的異常（和它們的子類）：
做些事情
on: Exception do: 
處理ex中異常
做些事情
on: Warning do: 
處理ex中異常
處理器子句使用它能獲得的異常對象，可以退出或恢復一個塊；退出是缺省的，但也可以顯式的指示：
Error signal: 'foo' 
on: Error do: 
ex return: 5
(Warning signal: 'now what?') printNl     "=> nil"
(Warning signal: 'now what?') printNl
on: Warning do: 
ex resume: 5 
"=> 5"
在因異常狀況而要進入調試器，可以調用對象類（Object）的halt方法，或增加了一個消息參數的halt:方法；這二者實際上調用了對象類的error:方法，它通過原始操作停止執行And/or啟動調試器，並展示這個錯誤消息：
self halt. "halt encountered"
self halt: 'This is a message'.
self error: 'This is a message'

**參見**
 Ruby syntax- GLASS

**引用**

**外部鏈接 ==