GNU Smalltalk
| File:GNU Smalltalk logo.svg | |
|---|---|
| Stable release | 3.1 / {{Expansion depth limit exceeded|2008|10|19}} |
| Preview release | 3.0c / {{Expansion depth limit exceeded|2008|08|10}} |
| Operating system | Unix (Linux, Cygwin, Mac OS X/Darwin) |
| Type | Programming language |
| License | GPL + LGPL |
| Website | http://smalltalk.gnu.org/ |
GNU Smalltalk is an implementation of the Smalltalk programming language by the GNU Project.
The implementation, unlike other Smalltalk environments, uses text files for program input and interprets the contents as Smalltalk code. In this way, GNU Smalltalk acts more like an interpreter rather than an environment in the traditional Smalltalk manner.
GNU Smalltalk includes bindings for many free software libraries including SQLite, libSDL, cairo, gettext.
Examples
These examples only work on GNU Smalltalk 3.0 and later versions. Classic Hello world example:
<source lang="smalltalk"> 'Hello World!' displayNl </source>
Some basic Smalltalk code:
<source lang="smalltalk"> "Everything, including a literal, is an object, so this works:" -199 abs "199" 'gst is cool' size "11" 'Slick' indexOf: $c "4" 'Nice Day Isnt It?' asLowercase asSet asSortedCollection asString "' '?acdeinsty'" </source>
Collections
Constructing and using an array:
<source lang="smalltalk"> a := #(1 'hi' 3.14 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))" </source>
Constructing and using a hash:
<source lang="smalltalk"> hash := Dictionary from: { 'water' -> 'wet'. 'fire' -> 'hot' }. hash at: 'fire' "Prints: hot"
hash keysAndValuesDo: [ :k :v |
('%1 is %2' % { k. v }) displayNl ]
"Prints: water is wet
fire is hot"
hash removeKey: 'water' "Deletes 'water' -> 'wet'" </source>
Blocks and iterators
Parameter-passing a block to be a closure:
<source lang="smalltalk"> "remember a block." remember := [ :name | ('Hello, %1!' % { name }) displayNl ].
"When the time is right -- call the closure!" remember value: 'world' "=> 'Hello, world!'" </source>
Returning closures from a method:
<source lang="smalltalk"> Integer extend [
asClosure [
| value |
value := self.
^{ [ :x | value := x ]. [ value ] }
]
]
blocks := 10 asClosure.
setter := blocks first.
getter := blocks second.
getter value "=> 10"
setter value: 21 "=> 21"
getter value "=> 21"</nowiki>
</source>
Using block to send info back to the caller:
<source lang="smalltalk"> Integer extend [
ifEven: evenBlock ifOdd: oddBlock [
^self even
ifTrue: [ evenBlock value: self ]
ifFalse: [ oddBlock value: self ]
]
]
"Invoke the above method, passing it a block." 10 ifEven: [ :n | n / 2 ] ifOdd: [ :n | n * 3 + 1 ] "=> 5" </source>
Iterating over enumerations and arrays using blocks:
<source lang="smalltalk"> array := #(1 'hi' 3.14) array do: [ :item | item displayNl ] "=> 1" "=> hi" "=> 3.14"
(3 to: 6) do: [ :item | item displayNl ] "=> 3" "=> 4" "=> 5" "=> 6" </source>
A method such as inject:into: can accept both a parameter and a block. It iterates over each member of a list, performing some function on while retaining an aggregate. This is analogous to the foldl function in functional programming languages. For example:
<source lang="smalltalk">
- (1 3 5) inject: 10 into: [ :sum :element | sum + element ] "=> 19"
</source>
On the first pass, the block receives 10 (the argument to inject) as sum, and 1 (the first element of the array) as element, This returns 11. 11 then becomes sum on the next pass, which is added to 3 to get 14. 14 is then added to 5, to finally return 19.
Blocks work with many built-in methods:
<source lang="smalltalk"> (File name: 'file.txt') withWriteStreamDo: [ :file |
file nextPutAll: 'Wrote some text.'; nl ]
"File is automatically closed here"
(File name: 'file.txt') linesDo: [ :each |
each displayNl ]
"=> Wrote some text." </source> Using an enumeration and a block to square the numbers 1 to 10:
<source lang="smalltalk"> (1 to: 10) collect: [ :x | x squared ] "=> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]" </source>
Classes
The following code defines a class named Person. By deriving from Magnitude, it automatically defines all comparison methods except one (<). With the addition of that one, asSortedCollection can sort by age. Note that we can override the way the object is printed/displayed (the default is to share the programmer-print and user-display representation) by overriding printOn:.
<source lang="smalltalk"> Magnitude subclass: Person [
| name age |
Person class >> name: name age: age [
^self new name: name; age: age; yourself
]
< aPerson [ ^self age < aPerson age ]
name [ ^name ]
name: value [ name := value ]
age [ ^age ]
age: value [ age := value ]
printOn: aStream [ aStream nextPutAll: ('%1 (%2)' % { name. age }) ]
]
group := {
Person name: 'Dan' age: 23.
Person name: 'Mark' age: 63.
Person name: 'Cod' age: 16.
}.
group asSortedCollection reverse </source>
The above prints three names in reverse age order: <source lang="text"> OrderedCollection (Mark (63) Dan (23) Cod (16) ) </source>
Exceptions
An exception is raised with a halt call:
<source lang="smalltalk">
self halt
</source>
An optional message can be added to the exception; there's also error: which raises a different kind of exception:
<source lang="smalltalk">
self halt: 'This is a message'
self error: 'This is a message'
</source>
These are actually wrappers for the actual exception raising method, signal:
<source lang="smalltalk">
Error signal
Error signal: 'Illegal arguments!'
</source>
Exceptions are handled by on:do: blocks.
<source lang="smalltalk"> [ something to do ]
on: Exception do: [ :ex | handle exception in ex ]
</source>
Of course you can catch only particular exceptions (and their subclasses):
<source lang="smalltalk"> [ something to do ]
on: Warning do: [ :ex | handle exception in ex ]
</source>
It is possible to use the exception object, which is made available to the handler clause, to exit or resume the first block; exiting is the default, but can also be mentioned explicitly:
<source lang="smalltalk"> [ Error signal: 'foo' ]
on: Error do: [ :ex | ex return: 5 ]
(Warning signal: 'now what?') printNl "=> nil" [ (Warning signal: 'now what?')
printNl ] on: Warning do: [ :ex | ex resume: 5 ] "=> 5"
</source>
See also
External links
If you like SEOmastering Site, you can support it by - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 and more...