7

XML ベースの Web サービスに対する Smalltalk API を作成しています。XML サービスは非常に規則的であるため、手動でメソッドを記述するのではなく、 を#doesNotUnderstand:介してメソッドを動的に追加するようにオーバーライドしMyApi class>>compile:、ワークスペースですべてのメソッドを 1 回呼び出してから、DNU を削除して素敵な API を用意することにしました。

これはうまく機能しますが、巨大な文字列を渡す#compile:だけで、私には本当に間違っているように感じます。Python や他の言語では、適切に構文チェックされたラムダをクラスにアタッチして、より安全な方法で同様の効果を得ることができます。例えば:

def himaker(name):
    def hello(self, times):
        for x in xrange(times):
            print "Hi, %s!" % name
    return hello
class C(object): pass
C.bob = himaker('Bob')
C.jerry = himaker('Jerry')
a = C()
a.bob(5)

SomeObject>>addHello: name
    | source methodName |
    methodName := 'sayHello', name, 'Times:'.
    source := String streamContents: [ :s |
         s nextPutAll: methodName, ' count'.
         s nextPut: Character cr.
         s nextPut: Character tab.
         s nextPutAll: 'count timesRepeat: [ Transcript show: ''Hi, ', name, '!'' ].' ]
    SomeObject class compile: source

確かにPythonバージョンと同じくらいきれいなものがあるに違いない?

4

4 に答える 4

4

ソース文字列にメソッドをより明確に反映させたい場合は、次のようにします。

SomeObject>>addHello: name
  | methodTemplate methodSource |
  methodTemplate := 'sayHello{1}Times: count
  count timesRepeat: [ Transcript show: ''Hi, {1}!'' ].'.   
  methodSource := methodTemplate format: { name }.
  self class compile: methodSource.

ソースの構文をチェックしたい場合は、次のようなテンプレート メソッドから始めることができます。

sayHelloTemplate: count
    count timesRepeat: [ Transcript show: 'Hi, NAME' ].

そして、次のように、それに応じてテンプレートを入力します。

addHello2: name
    | methodTemplate methodSource |
    methodTemplate := (self class compiledMethodAt: #sayHelloTemplate:) decompileWithTemps.
    methodTemplate selector: ('sayHello', name, 'Times:') asSymbol.
    methodSource := methodTemplate sourceText copyReplaceAll: 'NAME' with: name.
    self class compile: methodSource.

もちろん、いくつかのメソッドが抽出された場合、これはすべてより明確になります:)

于 2010-12-17T04:01:17.843 に答える
4

テンプレートメソッドがあるとします:

SomeClass>>himaker: aName
  Transcript show: 'Hi ...'

次に、それを他のクラスにコピーできます。システム ブラウザーを混乱させたくない場合は、セレクターとクラスを設定することを忘れないでください。または、気にしない場合は、メソッド辞書にコピーをインストールするだけです。

| method |

method := (SomeClass>>#himaker:) copy.

method methodClass: OtherClass.
method selector: #boo: .
OtherClass methodDict at: #boo: put: method.

method := method copy.
method selector: #bar: .
method methodClass: OtherClass2.
OtherClass2 methodDict at: #bar: put: method.
于 2010-12-18T08:19:36.993 に答える
0

私はブロックを使用します:

himaker := [:name | [:n | n timesRepeat: [Transcript show: 'Hi , ', name, '!']]]
hibob = himaker value: 'bob'.
hialice = himaker value: 'alice'.
hialice value: 2

あなたはまだhimakerをメソッドにすることができます

himaker: name
    ^[:n | n timesRepeat: [Transcript show: 'Hi, ', name, '!']]
于 2010-12-21T10:37:23.720 に答える
0

さて、コンパイルします。文字列を取ります。よりタイプセーフなものが必要な場合は、解析木を構築してそれを使用できます。

于 2010-12-19T13:56:13.437 に答える