見出し画像

💎メタプログラミングの功罪? Ruby python jsなど

ゴーストメソッドの例をpythonで見せてもらえますか?

ゴーストメソッドとは、プログラミングにおいてあるクラスが持つメソッドが実行時にのみ存在するように動的に作成されるメソッドのことを指します。これは特に Python のような動的な言語でよく使われるテクニックです。Pythonでは __getattr__ マジックメソッドを使用して、ゴーストメソッドを実装することができます。以下にその例を示します。

class GhostMethods:
    def __getattr__(self, name):
        # ゴーストメソッドを動的に生成
        if name.startswith("print_"):
            # 実行時に "print_" で始まるメソッドへのアクセスがあった場合、
            # 対応する文字列を出力するメソッドを作成する
            def method(*args, **kwargs):
                print(f"{name[6:]}: {args} {kwargs}")
            return method
        raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")

# インスタンス作成
ghost = GhostMethods()

# ゴーストメソッドのテスト
ghost.print_hello("world", end="!")  # "hello: ('world',) {'end': '!'}" と出力される
ghost.print_goodbye("everyone")      # "goodbye: ('everyone',) {}" と出力される

属性検索の結果、その属性が通常の場所で見つからなかった場合に呼び出される(つまり、インスタンス属性でもなければ、selfのクラスツリーでも見つからない)。

https://python-reference.readthedocs.io/en/latest/docs/dunderattr/getattr.html

Rubyで

もとはRubyでいろいろいってたメタプログラミング


香ばしいruby言語のブラックマジック合戦が展開される本かと思ったが、週番で教育係になった先輩からやさしく教えてもらう体裁で、エピソード形式でつかいどころがよくわからなかった。

メタプログラミングとは、「プログラミングコードを記述するコード」を記述することを意味します。
前半では、メタプログラミングの背景にある基本的な考えを紹介しながら、動的ディスパッチ、ゴーストメソッド、フラットスコープといったさまざまな「魔術」を紹介します。

メタプログラミングは、プログラムが自らの構造や動作を変更・生成する技術を指します。メタプログラミングをサポートする言語では、コードが自身や他のコードについての情報を取得、変更、または生成する能力を持っています。以下は、メタプログラミングの一部の概念についての説明です。

  1. 動的ディスパッチ (Dynamic Dispatch):

    • 動的ディスパッチは、実行時にメソッドや関数の呼び出しを決定するテクニックを指します。これは、多くのオブジェクト指向プログラム言語での多態性の実装において重要な役割を果たします。

    • 例えば、JavaやRubyのようなオブジェクト指向言語では、スーパークラスの参照を通じてサブクラスのオブジェクトのメソッドを呼び出す際、実際に実行されるメソッドは実行時に決定されます。

  2. ゴーストメソッド (Ghost Method):

    • ゴーストメソッドは、明示的に定義されていないメソッドを動的に呼び出すテクニックを指します。Rubyのmethod_missingは、ゴーストメソッドの典型的な例です。

    • これにより、実行時にメソッド名や呼び出しのパラメータに基づいて動的な振る舞いや応答を生成することが可能となります。

  3. フラットスコープ (Flat Scope):

    • この用語は、特定の言語や文脈においてさまざまな意味を持つことがありますが、一般的には、ネストされたコードのブロックや関数が、それを包含している外側のスコープの変数や関数にアクセスできることを指します。

    • RubyのブロックやJavaScriptのクロージャは、フラットスコープの概念を持っている例と言えます。これらの言語のネストされた関数やブロックは、定義された時点の外側のスコープの変数を「キャプチャ」できます。

ゴーストメソッドがRailsで使われているという飲み屋での情報を頼りに買ってしまった。ここに著者本人のコメントもあった

「例えばalias_method_chainというメソッドは、一体どこにあるんだと探しました。どこにあるか分からないんです。こんなことJavaではあり得ません。結局、テキスト検索で発見したコードがこれですが……、このリストにあるうち、私に分からなかったのは、ここと、ここと、ここです」

作者の当時のビデオはyoutubeで見つからなかったが本人が話してる姿を見たければ動画がいくつかある。英語は普通にうまい

巻末に魔術書が載っている。最初が配列引数で271ページに説明があるみたいだ。引数自体にイディオムとして意味を持たせるというような意義がある。javascriptでもapplyの引数は配列引数だし、argumentsという配列もある。

Railsの例ではfindの引数の受け渡しで使われていて、横断的にRDBの問い合わせ言語であるSQLを、比較的若いrubyで縦横無尽に書こうとすると、黒魔術的な表現が横行するようだ。

Unmiss は Ruby の method_missing の実装で、javascript のクラスで使用することができます。基本的に、これはマッチするメソッドが見つからないときに呼び出されるメソッドです。これは、答えのないメッセージをインターセプトし、それを優雅に処理する方法を提供します。

https://github.com/ramadis/unmiss

Unmiss は ES6 Proxies を使って method_missing をシミュレートしているので、ノードのバージョン >= v6.4.0 で動作します。また、ほとんどのモダンブラウザをサポートしています。

method_missing が JavaScript と相性が悪いのは、Python に存在しないのと同じ理由です。どちらの言語でも、メソッドはたまたま関数である属性に過ぎず、オブジェクトはしばしば呼び出し可能ではないパブリック属性を持っています。Rubyでは、オブジェクトの公開インターフェースは100%メソッドです。
JavaScript で必要なのは、メソッドであろうとなかろうと、見つからない属性へのアクセスをキャッチするフックです。Pythonにはそれがあります: __getattr__特別なメソッドをご覧ください。
Mozillaによる__noSuchMethod__の提案は、この矛盾だらけの言語にさらに別の矛盾を持ち込みました。

JavaScript が進むべき道は Proxy メカニズム (ECMAscript Harmony にもあります) で、これは Ruby の method_missing よりも属性アクセスをカスタマイズする Python のプロトコルに近いものです。

https://stackoverflow.com/questions/9779624/does-javascript-have-something-like-rubys-method-missing-feature

No such method

Proxyを使ってmethod_missingみたいなことはできる

https://editor.p5js.org/setapolo/sketches/rE2KrfVgg

https://note.com/rodz/n/n167bee94e4c7


いいなと思ったら応援しよう!

あたり帳簿
お願い致します