[SML 7514] Re: 第6回Smalltalk勉強会@京都

濱崎治 osamu.hamasaki @ gmail.com
2009年 4月 4日 (土) 15:08:14 JST


濱崎です。
先日の第6回Smalltalk勉強会@京都は参加出来ず、残念でした。

2009/04/02 0:42 AOKI Atsushi <atsushi @ cc.kyoto-su.ac.jp>:

>
> 参考となるプログラム断片も公開(リンク)しておきました。
>
> http://www.cc.kyoto-su.ac.jp/~atsushi/Smalltalkers/index-j.html#SmalltalkSalonAtKyoto6
> http://www.cc.kyoto-su.ac.jp/~atsushi/Programs/20090329/index-j.html
>
> --- 青木淳@京都宇治
>

このリンクにあったプログラムを見て、どんなお話をされたのか概ねイメージ出来ました。
情報の公開、ありがとうございます。ダブルディスパッチなんかも、慣れるまでは何を
やっているのか判りづらいので、今回は大変だったのでは、と想像します。

ところで、公開して頂いたプログラム断片のうち、数を表すオブジェクト群の#generalityの値を
調べるプログラムですが、下から2番目のものについて、以下の点で違和感を感じました。

・#generalityを実装しているクラスを探しているが、見つけてきた「クラス」に#generalityを
送信している。普通は、見つけてきたクラスの「インスタンス」にメッセージを送らないと
メッセージを理解してくれない。(#generalityはたまたまクラスの方も応答してくれるように
なっているので、このプログラムでもそれなりに動きますが。。。)

ということで、見つけてきたクラスのインスタンスに#generalityを送信して、値を答えて
もらうようにしたプログラムを書きました。こうすることにより、ソースコードを解析して
値を取り出す必要もなくなっています。

インスタンスを生成する為に#basicNewを使っているのですが、SmallIntegerは#basicNewを
受け付けないので、例外を捕まえて#zeroを送り直しています。
また、ArithmeticValueは#generalityを定義していますが、抽象クラスなので#generalityの
メソッドは、以前に勉強会で話題になった、

self subclassResponsibility

と書かれています。なので、ここも例外を捕まえてリストする対象から外しています。

あとついでに、「#generalityを実装しているクラス」ではなく、「#generalityに答えられる
クラス」をリストするようにしてみました。実装しているクラスをリストしたい場合は、

Smalltalk
allBehaviorsDo:
[:aClass | (aClass canUnderstand: messageSelector) ifTrue: [classes add:
aClass]].

の部分を

Smalltalk
allBehaviorsDo:
[:aClass | (aClass includesSelector: messageSelector) ifTrue: [classes add:
aClass]].

に変更して下さい。

#「メッセージを定義しているクラスを探ためだけにMethodCollectorを使うのは、大げさな感じが
#した」というのもあり、こんな風に変えてみました。

以上です。

------- 以下、プログラム ----------

| classes messageSelector generalityTable aStream aModel |
messageSelector := #generality.
classes := OrderedCollection new.
Smalltalk
allBehaviorsDo:
[:aClass | (aClass canUnderstand: messageSelector) ifTrue: [classes add:
aClass]].
classes := classes select: [:class | class isMeta not and: [class isObsolete
not]].
generalityTable := Dictionary new.
classes
do:
[:aClass |
| instanceCreationMessage anInstance |
instanceCreationMessage := #basicNew.
[anInstance := aClass perform: instanceCreationMessage]
on: Error
do:
[:exception |
instanceCreationMessage := #zero.
exception retry].
[| aCollection |
aCollection := generalityTable
at: (anInstance perform: messageSelector)
ifAbsentPut: [OrderedCollection new].
aCollection add: aClass]
on: SubclassResponsibilityError
do: [:exception | exception return]].
aStream := String new writeStream.
[generalityTable associations asSortedCollection
do:
[:association |
aStream
nextPutAll: association key printString;
nextPutAll: ' ('.
association value
do: [:aClass | aStream nextPutAll: aClass printString]
separatedBy: [aStream space].
aStream
nextPutAll: ')';
cr;
flush]] ensure: [aStream close].
aModel := ValueHolder with: aStream contents.
TextEditorView
    open: aModel
    label: 'Implementors of ' , messageSelector printString
    icon: (Icon constantNamed: #workspace)
    extent: 350 @ 220.
(aModel dependents detect: [:each | each isKindOf: TextEditorView])
    controller
    selectFrom: 1
    to: aModel value size.
^generalityTable
-------------------

Osamu Hamasaki
-------------- next part --------------
HTMLの添付ファイルを保管しました...
URL: http://www.smalltalk.jp/pipermail/sml/attachments/20090404/2ae7c622/attachment.htm


SML メーリングリストの案内