"Inspired by http://norvig.com/spell-correct.html"
"s = SpellCheck new. s initialize. s correct: 'misplet'"
Dictionary extend [
at: key [ ^ self at: key ifAbsent: [ 1 ] ] "make it a defaulting at:"
incrAt: key [ self at: key put: ((self at: key) + 1) ] "increments value" ]
Collection extend [
ifEmpty: block [ self isEmpty ifTrue: [ ^ block value]. ^ self ] "not in gst by default"
bestUsing: d [ ^ self inject: 'xxx' into: [ :sofar :this | ((d at: sofar) > (d at: this)) ifTrue: [ sofar ] ifFalse: [ this ] ] ] ]
String extend [
swapAt: i [ ^ (self copyFrom: 1 to: i), (self at: (i+2)) asString, (self at: (i+1)) asString, (self copyFrom: (i+3) to: self size) ]
removeAt: i [ ^ (self copyFrom: 1 to: i), (self copyFrom: (i+2) to: self size) ]
insert: l at: i [ ^ (self copyFrom: 1 to: i), l asString, (self copyFrom: (i+1) to: self size) ]
replace: l at: i [ ^ (self copy) at: i put: l; yourself ]
findWords [ ^ (self asString tokenize: '[^a-zA-Z]+') collect: [ :each | each asLowercase ] ] ]
Object subclass: SpellCheck [
| nwords alphabet |
initialize [ | lines |
lines := (File name: 'bigtext.txt') contents.
nwords := self train: lines findWords.
alphabet := 'abcdefhgijklmnopqrstuvwxyz' ]
train: features [ | model |
model := Dictionary new.
features do: [ :each | model incrAt: each asLowercase ].
^ model ]
edits1: word [ | s n |
s := Set new.
n := word size.
0 to: (n - 2) do: [ :i | s add: (word swapAt: i) ].
1 to: (n - 1) do: [ :i | s add: (word removeAt: i) ].
alphabet do: [ :letter |
1 to: n do: [ :i | s add: (word replace: letter at: i) ].
0 to: n do: [ :i | s add: (word insert: letter at: i) ] ].
^ s asArray ]
known_edits2: word [ | s |
s := Set new.
(self edits1: word) do: [ :e1 |
(self edits1: e1) do: [ :e2 |
(nwords keys includes: e2) ifTrue: [ s add: e2 ] ] ].
^ s asArray ]
known: words [ ^ ( words select: [ :each | nwords keys includes: each ] ) asSet asArray ]
correct: word [ | candidates |
candidates := (self known: {word}) ifEmpty: [
(self known: (self edits1: word)) ifEmpty: [
(self known_edits2: word) ifEmpty: [ {word} ] ] ].
^ candidates bestUsing: nwords ]
]
54 lines of not very idiomatic Smalltalk including blank lines and comments (such as they are). More than twice as many lines as Peter Norvig's Python solution, but 1/6th of the size of the Java solution!
It felt very strange - and frustrating - to be developing in Smalltalk without the full support of the traditional environment, especially as I was trying to pick up the subtle differences from Squeak Smalltalk, but the ability to 'extend' the core classes from within the scripts means that it will be very easy to be able to hack out scripts using this tool.















