2012-06-28 18 views
5

私はケーキパターンを使用しているプロジェクトにいくつかのマクロを統合する必要があります。そのパターンは、他の利点の中でも、我々が輸入の盛り上がりを避けることを可能にしたので、我々はそれを保つつもりです。さて、私たちはトランクの外でテストしていたいくつかの実験マクロで問題に直面しています。まずは、ケーキという名前のダミーシステムを示してみましょう:ケーキパターンとマクロを統合することは可能ですか?

trait APiece { 
    class A 
} 

trait BPiece { this: APiece => 
    def aMacro(a: A): Unit =() /* macro ??? */ 
} 

trait CPiece { this: APiece with BPiece => 
    def aMacroInvoker = aMacro(new A) 
} 

class Cake { this: APiece with BPiece with CPiece => } 

個々にするクラスを定義し、BPieceは個々に定義されたクラスを使用し、最終的には、CPieceは、マクロを呼び出すマクロことになっています。私はBPieceを実装するためのコードを書くことができなかったので、BPieceはマクロであると言いました。私はいくつかの方法を試してみましたが、私はいつも次のエラーでクラッシュ:

"macro implementation must be in statically accessible object" 

macros code 1は、静的モジュールにマクロを囲むneccesaryであることを推測することができます読み取ります。システム構造を使用するマクロを展開する方法はありますか?

答えて

4

あなたの問題を簡単に解決する方法があります。

しかし、まず、いくつかの回顧をおこなってみましょう。最初のプロトタイプでは、マクロは次のように定義されました:def macro aMacro(a: A): Unit = ...。 SIPを準備する際の大きな進歩の1つは、マクロ定義(マクロの公開面)とマクロ実装(マクロロジックをホストするツリートランス)を分離することです。これはどれくらいクールなのか気づいていましたが、今はマクロの宣言を書くたびに喜びを感じています。

あなたの質問に戻る。確かに、マクロ実装は静的にアクセス可能でなければなりません(そうしないと、コンパイラーはコンパイル時にそれらをロードして呼び出すことができません)。あなたがそのような定義を書くことができますので、しかし、マクロ定義は、この制限はありません。定義から参照される

trait BPiece { this: APiece => 
    def aMacro(a: A): Unit = macro Macros.aMacro 
} 

マクロ実装が異なっても、コンパイル単位に、あなたが望むものは何でも対象に入れることができます。

パズルの欠けている部分は、Aがケーキの中で定義されているため、実装からAをどのように参照するかです。最も簡単な方法はaMacroを汎用とし、タイプ推論に依存することです:

(更新:この例を2.10.0-M7で動作させるには、この例を作るためにc.TypeTagをc.AbsTypeTagに置き換える必要があります。マクロ実装のためAはせずに、単にtypeパラメータであるため、2.10.0-RC1での仕事、c.AbsTypeTagはc.WeakTypeTagに交換する必要がある)

trait BPiece { this: APiece => 
    def aMacro[A](a: A): Unit = macro Macros.aMacro[A] 
} 

object Macros { 
    def aMacro[A: c.TypeTag](c: Context)(a: c.Expr[A]): c.Expr[Unit] = c.literalUnit 
} 

これは、しかし、あなたはreifyを使用させません任意のメンバー。マクロからケーキ固有のものを返そうとするなら、問題が生じるでしょうが、発生したときにそれらを処理しましょう。必要に応じてフォローアップの質問を提出してください。

+2

私は彼の問題を解決するとは思わないし、私は何も考えないと思う。あなたが知っておくべきであるように、ケーキパターンの本質! :-) - "クライアント"コードで必要なレイヤーを選択できるようになりました。 'マクロス(Macros) 'が静的であれば、自由にそれを切り替えることはできません。ソースファイルやクラスファイルを切り替えることはできますが、「ここからマクロを使用し、そこからマクロを使用します」というコードを記述することはできません。 –

+0

偉大な、私は新しい問題が発生すると思うが、私は今この解決策を続けることができます。どうもありがとうございました!ダニエル、私たちのシステムは本当に(ケーキパターン)マクロで純粋になるわけではありません。私たちは、クライアントが使用したいかどうかをクライアントが決定できるようにします。だから、私はこれが十分に良いことを願っています。 – jeslg

+0

@ DanielC.Sobralアイデアはケーキの中にマクロを宣言することでした。異なるマクロ実装を参照するマクロを定義するレイヤーが異なる場合は、必要に応じてそれらを切り替えて、異なる動作を得ることができます。 –

関連する問題