web-dev-qa-db-ja.com

マクロと同じくらい強力なデコレータをどのように作成しますか?

簡単な背景:私は使いやすいまま、LISPと同じくらい強力になりたいPythonic言語を設計しています。 「パワフル」とは、「柔軟で表現力のある」という意味です。

Python関数デコレータを紹介されたばかりで、気に入っています。デコレータがではないことを示唆する この質問 を見つけましたLISPマクロと同じくらい強力です この質問 への3番目の答えは、それらが機能していない理由は、関数でしか操作できないためです。

しかし、任意の式でデコレータを使用できるとしたらどうでしょう。 (私の言語では、式は関数や他のすべての要素と同じようにファーストクラスなので、それを行うのはかなり自然なことです。)それにより、デコレータはLISPマクロと同じくらい強力になりますか?それとも RacketHon などの構文規則、またはその他の手法を使用する必要がありますか?

[〜#〜]編集[〜#〜]

構文構造の例を提供するように求められました。 「式デコレーター」の場合は、式のデコレーターになります(「$(...)」は式オブジェクトを作成します)。

@Decorator("Params")
$(if (true):
    printf("Was true")
else:
    printf("Wasn't true"))

また、上記のようにIdoで構文ルールを使用する必要がある場合は、パターンマッチング構文を使用します。

# Match a bool expression, a comma, and a string.
macro assert(expr:bool lit string) { e , s }:
    if (!e):
        error s
    else:
        printf("All good")

上記はこれと一致します:

assert i == 0, "i should have been 0"

それは大まかなスケッチですが、それはあなたにアイデアを与えるはずです。

7
Gavin Howard

短い答え:できません。

Pythonなど、現在の状態に近いものではありません。理由は簡単です。関数はオブジェクトです。式はオブジェクトではありません。式はアクティビティを記述します-オブジェクトを操作するアクティビティと結果を生成します。式の入力と出力はオブジェクトですが、式自体はそうではありません。式はオブジェクトではないため、装飾できません。

Pythonメタプログラミングのこの制限は言語にかなり組み込まれています。Pythonセマンティクスを変更することは不可能ではありません。 forbiddenfruit のようなモジュールで公式に「不可能」な方法でビルトインオブジェクトが組み込まれたmonkeypatch MacroPykarnickel のようなモジュール、そして現在明らかに機能していない MetaPython はいくつかのマクロを提供しますAST書き換えおよび関連するテクニックを介して機能します。ただし、これらのいずれも本番環境での使用は認定されておらず、ほとんどがポップアップし、1つまたは2つの言語反復をサポートしてから蒸発します。ダブルバック-flip-with-twistの動きは、それらをまったく機能させるために必要なものであり、期間、一般性、または「依存できるコード」のコンテキストでは持続可能ではありません。

イントロスペクションとリフレクションをうまく使用して、プログラムで現在何が起こっているかを検査するモジュールがあります。私の たとえば モジュールは、たとえば、多くのPython 2およびPython 3バージョン、さらには代替Python PyPyのような実装です。ただし、Pythonメタモジュールが実際にプログラムのセマンティクスを変更できるものはほとんどありません。 GvR は、メタプログラミング機能にかなり抵抗しています。withステートメントたとえば、セマンティクスは、サポートできるメタプログラミングの量を制限するという特定の目的のために制限されていました。

しかし、それはPython今日のように存在します。Python++言語に、装飾できる任意のコードブロック(神話的な複数行のラムダ、よく言及されますが実際にはPythonでは見られない)があると想像してください。ラムダはオブジェクトであり、コードブロックは非常にオブジェクト化可能です。every式をオブジェクトに作成するオーバーヘッドはおそらく望まないでしょうが、ブロックでエンコードして興味深い表現をしてから装飾できる環境を想像するのは難しくありません。

メタプログラミングと高度なマクロ機能を統合するために機能してきた2つの標準(つまり、Lispy以外の言語)とかなりPythonic言語は JuliaNim (以前はNimrodと呼ばれていました)です。それらがプログラムの表現と変換に対処する方法は非常に強力であり、設計の良い研究ポイントになります。

8
Jonathan Eunice