第27回 Smalltalk勉強会 - Smalltalkの超能力
2010 Masashi Umezawa
動機
 もっとクラス名、メソッド名をわかりやすく
できないか?
 長い名前とか、読むのが大変
 ぱっと見ただけでわかるほうがいい
 クラス名やメソッド名で改行つきの文字列を
使えれば、表現力が格段と高まるのではない
か?
例
 いらないクラスということがすぐにわかる
Object subclass: #'
/ \
/ ─ ─\
/ (●) (●) \ よく考えたら俺いらないな
| (__人__) |
/ ∩ノ ⊃ /
( \ / _ノ | |
.\ “ /__| |
\ /___ /
'
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Test-Multilines'
実装にあたって
 技術的には簡単
 もともとクラス名やメソッド名はSymbolのインスタンス
 Symbol自体には改行を含めることができる
○ #'改行文字列' のようにシングルクォートでくくればよい
 開発環境の制限を外していくだけ
Multiline class
 クラス名の先頭文字と使える文字に改行を追加
Character >> canBeGlobalVarInitial
self = Character cr ifTrue: [^true].
^ (EncodedCharSet charsetAt: self leadingChar)
canBeGlobalVarInitial: self.
 基本これだけ
Multiline method (1)
 開発環境の抵抗がなかなか強かったので、
メソッド追加で対処
ClassDescriptiopn >> addAAMethod: aa body: bodyCode
| code aaSymbol |
code := 'tmp' , String cr , bodyCode.
aaSymbol := aa asSymbol.
self compile: code classified: ''.
self addAndClassifySelector: aaSymbol
withMethod: (self methodDict at: #tmp)
inProtocol: 'AA' notifying: nil.
self removeSelector: #tmp
Multiline Method (2)
 各クラスのMethodDictionaryをいじって
あげればよい
 tmpという名前でまずメソッドをコンパイル
 コンパイルされたバイトコード(CompiledMethod)を
アスキーアート(AA)をキーとして登録しなおす
 tempのメソッドは消しておく
 これでできた!
パーサライブラリの拡張 (1)
 ワークスペース等で実行しやすいように既存の
Smalltalkパーサライブラリを拡張する
 DSL系を実装するには常套手段
 Smalltalkでは自分をコンパイルするコンパイラクラスを
クラス毎に指定できる
○ compilerClassメソッドのオーバーライド
 今回は単にデフォルトのスキャナに手を入れるだけ
パーサライブラリの拡張 (2)
 スキャナにバッククォートのトークンを加える
 AAをバッククォートで囲むと、クラスやメソッドの識別子と
してパースされるようにしたいため
Scanner class >> initialize
...
newTable at: $` asciiValue put: #xBackQuote.
...
 バッククォートを選んだ理由
 他で使われていない
 存在感が薄いのでアスキーアートを邪魔しない
パーサライブラリの拡張 (3)
Scanner >> xBackQuote
self step.
buffer reset.
[hereChar = $`
and: [aheadChar = $`
ifTrue: [self step. false]
ifFalse: [true]]]
whileFalse:
[buffer nextPut: self step.
(hereChar = 30 asCharacter and: [source atEnd])
ifTrue: [^self offEnd: 'Unmatched string quote']].
self step.
token := buffer contents asSymbol.
tokenType := #word
 まじめに読む必要なし
 xSingleQuoteメソッドをパクる
 tokenTypeを#wordにする => 識別子になる
デモ
 AAクラスの定義
 AAメソッドの定義
 実行
`
|┃三 ∩___∩
|┃ | ノ ヽ
|┃ ≡ / ● ● | きたクマー!
____,|ミ\___| (..●..) ミ
|┃=___ |∪| \
|┃ ≡ / ヽノ 人 \ ガラッ` new
`
/⌒ヽ
∩ ^ω ^) うはwww
| ⊂ノ
| _⊃
し ⌒`
まとめ
 Smalltalkで、内部DSLをつくるのは非常に
簡単
 グラフィカルな表現もお手のもの
 まじめな開発ではAAクラスとか使わないで
ください

MultilineクラスとMultilineメソッド