問題タブ [scala-quasiquotes]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
scala - quasiquote を使用したパターン マッチング ツリーの堅牢性
私はマクロを持っており、そのマクロの一部は、特定のメソッドへのすべての呼び出しを別のものに置き換えることで構成されています。これを達成するために、私は a を使用し、メソッドに入るTransformer
すべてのものをquasiquote と照合しようとします。以下のように書くとうまくいきそうです。Tree
transform
しかし、マクロでは常に完全修飾名を使用する必要があると考えました。そうしないと、問題が発生する可能性があります。だから私はそれを のように書きましたq"_root_.mypackage.myobject.mymethod[..$_]($value)"
が、それはもはや一致せず、 への呼び出しmymethod
は置き換えられなくなりました。scala docs
でシンボルの引用符を外す
という提案も見ましたが、それも機能しませんでした。
だから私の質問は: このコード (とq"mypackage.myobject.mymethod[..$_]($value)"
) は常にすべての呼び出しをmymethod
置き換え、他のメソッド呼び出しを決して置き換えませんか? そうでない場合、どうすればより堅牢にすることができますか?
scala - Quasiquote は、リテラルとして解釈する代わりに、ツリーの内容を解釈します
以下の Scala quasiquote の 2 つの使用法で、 と の間result1
で異なる出力が得られる理由を説明してくださいresult2
。準引用符を使用して再現することは可能result3
ですか? つまり、文字列の内容を解析して評価しますか?
scala - scala - quasiquote に値を挿入する
残念ながら、最も直感的な方法は、
結果は
$
quasiquotes 内ではtree
.
動作しますが、非常に醜く、Intellij の警告が表示され、c.literal
非推奨であり、代わりに準引用符を使用する必要があります。
それで...どうすればいいですか?
アップデート
フラビアンのコメントに応えて:
与える
scala - scala 文字列を解析して Tree にし、準引用符で使用します
一種のネストされた準引用評価を実行できるかどうか疑問に思っていました。
関数呼び出しがあるとしましょう
"add(x,y)"
それは(文字列)を返します
これを評価させるにはどうすればよいですか?
何かのようなもの
ここでの問題は、準引用符の最初の評価が文字列を返すことであり、2 番目の評価では何も実行されないことになります。
scala - Scala マクロを使用して新しい部分関数を作成または変換する方法は?
特定の部分関数を変換して新しい部分関数を作成するマクロを作成するのに問題があります。たとえば、指定された部分関数をその要素 (パターン バインダー、ガード条件、ボディ) に分解できるようにしたいと考えています。次に、パターン バインダーとガード条件を小さな断片に分解し、これらの断片から新しい部分関数を再構築します。しかし、デバッグできないマクロ展開で奇妙なエラーが発生します。
同じエラーを引き起こす最も単純な問題は、指定された部分関数をバインダー、ガード、および本体に分解し、それを同じ部分関数に再アセンブルするコードです。
単純な型ではこれを行うことができますPartialFunction[Int,Any]
が、ケース クラスを含む型ではできませんPartialFunction[MyCaseClass,Any]
。
動作するコードと動作しないコードを次に示します。
作業コード: 部分関数を取得し、準引用符を使用してそれを分解し、同じ関数を再度アセンブルして返します。
このマクロは、コンパイルしてテストに合格します。
Non-working codeInt
:部分関数の引数としての代わりにケース クラスを使用することを除いて、まったく同じマクロです。
コードはまったく同じで、タイプが異なるだけです (Complicated
ではなくSimple
)。
マクロ コードはコンパイルされますが、テストはコンパイルに失敗します (マクロ展開で失敗します)。
問題を可能な限り最小限に単純化しましたが、それでも失敗します。私の実際のコードでは、型はより複雑で、部分関数にはガードがある場合があり、引数とガードを再配置することで部分関数のコードを変換します。ガードがない場合は変換を機能させることができますが、部分関数の引数がケース クラスの場合は機能しません。おそらく、ガードの存在は問題の根源ではありません。問題は、unapply
どこかに複合型がある場合に発生します。上記の非常に単純化された例で得られるのと本質的に同じエラー メッセージが表示されます。
部分関数を変換する多くの代替方法を試したにもかかわらず、この問題を解決できないようです。
- ホワイトボックス マクロ コンテキストを使用する
- 上記の例のように、プレーンな準引用符を使用します
- ケースとパターン
cq"..."
には特別な準引用符を使用し、準引用符のドキュメントに示されているようにpq"..."
q"{case ..$cases}"
- guard: とのマッチング
q"{case $binder if $guard => $body }"
、またcq
およびpq
quasiquotesとのマッチング c.typecheck
orをさまざまな場所に追加するc.untypecheck
(これは以前は と呼ばれていましresetAllAttrs
たが、現在は廃止されています)- 準引用符は使用しませんが、生の構文ツリーですべてを行います:
Traverser
生のツリー マッチングと共に使用case UnApply(Apply(Select(t@Ident(TermName(_)), TermName("unapply")), List(Ident(TermName("<unapply-selector>")))), List(binder)) if t.tpe <:< typeOf[Blob]
します。 Ident
パターン マッチャーの をガード条件から取得したに置き換えてみてくださいIdent
。また、その逆も同様です (これにより、型チェックの失敗により、「アサーションに失敗しました」という奇妙なエラーが発生します)。- 特定の型の代わりに使用
Any
して、 を返しPartialFunction[Any,Any]
たり、合計関数Function1[Blob,Any]
などを使用したりします。 T
の代わりに型パラメータを使用しBlob
、マクロをパラメータ化して受け入れますPartialFunction[T,Any]
助けていただければ幸いです。私はScala 2.11.8をストレートマクロで使用しています(「マクロパラダイス」はありません)。
scala - scala meta と quasiquotes を使用した暗黙的エンコーダーの定義
Circe を使用して暗黙的なエンコーダーを作成しようとしています。ただし、このエンコーダーはアノテーションを使用して作成されるため、Scalameta を使用しています。これが私のコードです。ただし、コンパイラは、準引用符内にオーバーライド ステートメントがあると文句を言います。
ビルドファイルは次のとおりです。
結果として、私はまだ取得します: マクロ注釈を展開できませんでした(その最も一般的な理由は、マクロパラダイスプラグインを有効にする必要があるためです。別の可能性は、それを定義する同じコンパイル実行でマクロ注釈を使用しようとすることです)