知りたいwhileTrue:
機能します。 BlockClosure
にある実装を検索しました:
whileTrue: aBlock
^ [self value] whileTrue: [aBlock value]
パラメータのない別の実装:
whileTrue
^ [self value] whileTrue: []
しかし、それがどのように機能するかはわかりません。それは再帰的な方法ですが、これによりいくつかの質問をするようになりました:
[self value]
はBoolean
オブジェクトを返します。なぜwhileTrue:
Boolean
タイプに実装されていませんか?whileTrue
という名前の別の実装で、ブロックをまったく受信せず、self
を評価するのはなぜですか?whileTrue:
はコンパイラーによってインライン化されるため、実際の実装は表示されません。これがPharoのコメントです:
「通常はインラインでコンパイルされるため、オーバーライドできません。これは、メッセージがリテラルブロック以外に送信される場合です。レシーバの値がtrueである限り、引数aBlockを評価してください。」
#whileTrue:
のバイトコードを見ると、コンパイラがジャンプを使用してループを作成していることがわかります。
17 <70> self
18 <C9> send: value
19 <9C> jumpFalse: 25
20 <10> pushTemp: 0
21 <C9> send: value
22 <87> pop
23 <A3 F8> jumpTo: 17 <---- here's the jump
25 <7B> return: nil
#whileTrue
も直接インライン化されます(わずかに最適化されたバイトコード)。インライン化は、これをBoolean
に実装しない理由でもあります(ブール値を再評価する意味がないという事実は別として...)。
#whileTrue
があるので、エンドポイントだけを終端するような無限ループを簡単に作成できます。プロセスが終了すると、セマフォが通知され、例外が発生します。
私のSmalltalkは少し錆びており、現時点ではSmalltalkをインストールしていないため、ここに構文エラーがあるかもしれませんが、次のように考えます。
whileTrue: aBlock
↑ self value ifTrue: [aBlock value. self whileTrue: aBlock]
Rubyのバージョンは次のとおりです。実際にテストしましたが、上記(私が望む))は翻訳です:
class Proc
def vhile(block)
self.().iff(thn: -> {block.(); vhile(block)})
end
end
Smalltalkスタイルの条件文を機能させるには、次のモンキーパッチが必要です。
class TrueClass
def iff(thn:, els: ->{})
thn.()
end
end
class FalseClass
def iff(thn:, els: ->{})
els.()
end
end