一方ではSmalltalk と Ruby、他方ではRuby と Pythonの比較を見てきましたが、Python と Smalltalk の間ではありません。特に、実装、構文、拡張性、哲学の基本的な違いを知りたいです。
たとえば、Python にはメタクラスがないようです。Smalltalk にはジェネレータの概念がありません。どちらも動的に型付けされていると言われていますが、Python は動的なメソッドのディスパッチを行っていないと思います。これは正しいです?
一方ではSmalltalk と Ruby、他方ではRuby と Pythonの比較を見てきましたが、Python と Smalltalk の間ではありません。特に、実装、構文、拡張性、哲学の基本的な違いを知りたいです。
たとえば、Python にはメタクラスがないようです。Smalltalk にはジェネレータの概念がありません。どちらも動的に型付けされていると言われていますが、Python は動的なメソッドのディスパッチを行っていないと思います。これは正しいです?
たとえば、Python にはメタクラスがないようです。
確かにそうです-すべてのクラスに対して新しいメタクラスを暗黙的に生成するわけではありません。親クラスと同じメタクラスを使用するかtype
、デフォルトで使用します。Python の設計哲学、別名「The Zen of Python」はimport this
、対話型インタープリターのプロンプトで実行することで熟読できます。ここで適切な点は、2 番目の「明示的は暗黙的よりも優れている」です。
Python 2.X では、次の構文でカスタム メタクラスを指定します。
class sic:
__metaclass__ = mymeta
...
Python 3.X では、よりエレガントに、名前付き引数の構文を使用します。
class sify(metaclass=mymeta):
...
Smalltalk にはジェネレータの概念がありません。
Python のジェネレーターはファースト クラス (通常はスタンドアロン) 関数であり、Smalltalk には「スタンドアロン」関数の概念がありません。クラス内にメソッドがあります。しかし、それは確かにイテレータを持っています - もちろん、クラスとして:
iterator := aCollection iterator.
[iterator hasNext] whileTrue: [iterator next doSomething].
Smalltalk には第一級の「コード ブロック」があるので (Ruby はそこから取ってきた)、他の「制御構造」と同様に、コード ブロックを適切なメソッドに送信することで反復を実行します。コレクション(考えてselect:
ください):
aCollection select: [:item | item doSomething].
したがって、Smalltalk (および Ruby) では、コード ブロックを反復に送ります。Python は逆の処理を行い、反復によって値が周囲の「呼び出し」コードに送信されます。非常に異なって見えますが、最終的に「深く」異なっているわけではありません。
if
ファーストクラスのコード ブロックとは、Smalltalk が「制御構造」ステートメントやorなどのキーワードを必要としない、または持たないことを意味します。これらは、コード ブロックを適切なメソッド (ブール値のメソッドなど) のwhile
引数として送信することで実現できます。ifTrue:
(Ruby は、第一級のコード ブロックに加えてキーワード/ステートメントを持つことを選択します。私は、Python [[明示的に]] と Smalltalk [[暗黙的に]] の両方が、C のように、「実行するための単一の方法を提供しようとしている」と言うでしょう。操作」であるのに対し、Ruby は「それを行うには多くの方法がある」という Perl っぽい学校に属しています)。
どちらも動的に型付けされていると言われていますが、Python は動的なメソッドのディスパッチを行っていないと思います。これは正しいです?
いいえ、絶対に間違っています。Pythonは動的メソッドのディスパッチを極端に行います。たとえば、次のように考えてください。
for i in range(10):
myobject.bah()
Python のセマンティクスにより、これは in のメソッドに対して10回のルックアップを実行します-- 以前のメソッドの実行によって内部的に完全に再構築され、現在のメソッドが以前のメソッドとは完全に異なる場合に備えて (プログラマーはそのような猛烈なダイナミズムに頼る必要がありますが、Python はそれをサポートしています)。これが次の理由です。bah
myobject
myobject
bah
themethod = myobject.bah
for i in range(10):
themethod()
Python コードでの一般的な手動最適化 -- ループ内で 10 回ではなく、ループの前に 1 回の動的ルックアップを行います (脚ごとに 1 回) (これは、コンパイラが「一定の折り畳み」自体を行うことを禁じられているため、「一定の巻き上げ」の場合です)動的ルックアップに関する Python の極端な規則によるものです -- それが無害であることが保証されていることを証明できない限り、実際にはそのような証明は難しすぎるため、Python の実装は通常気にしません)。
Python は統一された名前空間を使用します。メソッドは、呼び出し可能であることを除いて、他のものと同じようにオブジェクトの属性です。これが、メソッドを呼び出さずに抽出する (「バインドされたメソッド」として知られている)、変数に参照を設定する (または、リストや他のコンテナーに格納する、関数から返すなど) がプレーンであり、上記の一定巻き上げの例のような簡単な操作。
Smalltalk と Ruby では、メソッドとその他の属性に対して別々の名前空間があります (Smalltalk では、メソッド以外の属性はオブジェクト自体のメソッドの外では見えません)。そのため、「メソッドを抽出する」と「結果のオブジェクトを呼び出す」には、より内省的な儀式が必要です (ただし、一般的なこれにより、特定のケースでは、ディスパッチのケースがわずかに単純になる可能性があります-特に、引数のないメソッドを「言及するだけ」で暗黙的に呼び出しますが、Pythonでは、Cのように、呼び出しは括弧を追加することで明示的に実行されますが、「単に言及するだけです」、まあ...「言及するだけ」で、呼び出しを含むあらゆる種類の明示的な操作で利用できるようになります;-)。
Python には確かにメタクラスがあります。
Smalltalk にはいくつかの珍しい機能があります。
Smalltalk にはジェネレータの概念がありません。
確かに、言語内からほとんどの Smalltalk 方言で実装できます。GNU Smalltalk には、ストリーム ライブラリの一部としてジェネレータが付属しています。
私はコーダーズアットワークを読んでいます。これは、トッププログラマーへのインタビューが満載の本当に素晴らしい本です。いずれにせよ、そのうちの 1 人は smalltalk の発明者であり、彼の言語とそれが Python とどのように関係しているかについて詳しく話しています (彼は Python もかなり好きです)。彼が python で抱えていた唯一の問題は、コードが遅いことでした... 彼は本当に Python のバックエンドとして smalltalk jit コンパイラーを使用したかったのですが、残念ながら、彼が勤務していた会社のソフトウェアが原因で、これは不可能でした。
とにかく...ポイントごとの比較ではないかもしれませんが、とにかくこの本は本当に良い読み物です.
Wikipediaの動的メソッドディスパッチに関するページによると:
Smalltalk の実装
Smalltalk は型ベースのメッセージ ディスパッチャを使用します。各インスタンスには、定義にメソッドが含まれる単一の型があります。インスタンスがメッセージを受信すると、ディスパッチャーはメッセージからメソッドへのマップで対応するメソッドを検索し、そのメソッドを呼び出します。[...]
Python、Ruby、Objective-C、Groovyなど、他の多くの動的型付け言語も同様のアプローチを使用しています。
強調が追加され、1 つの段落が省略されました。したがって、少なくともその部分は 2 つの言語間で類似しているように見えます。