Let's write β

プログラミング中にできたことか、思ったこととか

SmalltalkでdoesNotUnderstand:をつかってローマ数字の変換

おとといあたりに' Last Resort'というワードを聞き僕がまずおもいうかんだのは、
どこかのプレゼンで目にした「method-missing is last resort」というフレーズでした、
そして次に連想されたのは以前メタプログラミングRubyで読んだRubyのmethod-missingを利用して
ローマ数字の変換をするというカオスなコードでした。
しかし、このmethod-missingを利用するテクニックRailsのソースを読んでみるといろいろな所で利用されて
いて、けっこうRubyで変態行為を働く時には普通のテクニックのようでした。

それならSmalltalkでもやってみようとおもい、smalltalkにある同じメソッド(むしろ順序的には逆でしょうが)
#doesNotUnderstand:を利用してみようとおもいました。
これはメッセージが送信された時に対応するメソッドが存在しなかった時に代理でよばれる物で、通常は
デバッガーの起動を行う処理がわりあてられているメソッドです。
こちらを利用すると、Proxyを作成したりExtendsをしたりと色々あそべるようです
が、とりあえず前述のローマ数字変換をしてみようとおもいまして書いてみました。

Object subclass: #Roman
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'RomanNumber'

"以下Roman>>doesNotUnderstand:"

doesNotUnderstand: aMessage
	| romanStr |
	romanStr := aMessage selector asString.
	romanStr := romanStr copyReplaceAll: 'IV' with: 'IIII'.
	romanStr := romanStr copyReplaceAll: 'IX' with: 'VIIII'.
	romanStr := romanStr copyReplaceAll: 'XL' with: 'XXXX'.
	romanStr := romanStr copyReplaceAll: 'XC' with: 'LXXXX'.
	Transcript show: romanStr.
	^ (romanStr count: [:ch | ch = $I]) +
		((romanStr count: [:ch | ch = $V]) * 5) +
		((romanStr count: [:ch | ch = $X]) * 10) +
		((romanStr count: [:ch | ch = $L]) * 50) +
		((romanStr count: [:ch | ch = $C]) * 100)

これでWorkspaceで

Roman XII. 12

Roman J. 0

と変換できている事が確認できました。またわかるように存在しない数は今のところ0になるようにしています。