マクロでプライベート コンストラクターを使用したい。この例は正の整数ですが、基本パターンは偶数などの他の数値型だけでなく、電子メール アドレスやディレクトリ名などの文字列から派生した型にも使用できます。コンストラクターを非公開にすることにより、ユーザーは不正な型を作成する機会を拒否されます。次のコードがあります。
object PosInt
{
import language.experimental.macros
import reflect.runtime.universe._
import reflect.macros.Context
def op(inp: Int): Option[PosInt] = if (inp > 0) Some(new PosInt(inp)) else None
def apply(param: Int): PosInt = macro apply_impl
def apply_impl(c: Context)(param: c.Expr[Int]): c.Expr[PosInt] =
{
import c.universe._
param match {
case Expr(Literal(i)) if (i.value.asInstanceOf[Int] > 0) =>
case Expr(Literal(i)) if (i.value.asInstanceOf[Int] == 0) => c.abort(c.enclosingPosition, "0 is not a positive integer")
case Expr(Literal(i)) => c.abort(c.enclosingPosition, "is not a positive integer")
case _ => c.abort(c.enclosingPosition, "Not a Literal")
}
reify{new PosInt(param.splice)}
}
}
class PosInt (val value: Int) extends AnyVal
ただし、PosInt コンストラクターをプライベートにすると、マクロは期待どおりにコンパイルされますが、マクロを使用しようとするとエラーが発生します。式ツリーを手動で構築する方法を見つけることはできませんが、とにかくそれが役立つかどうかはわかりません. とにかく私はこれを行うことができますか?
PosInt が値クラスでない場合でも、プライベート コンストラクターを使用することはできません。値クラスを使用しない回答を受け入れます。値クラスの欠点は、型が消去されることです。さらに、2次元座標のサブセットのように私が興味を持っているクラスは、とにかく値クラスとして実装できません。私は実際には正の整数には興味がありません。単純なテストベッドとして使用しているだけです。Scala 2.11M5 を使用しています。Scala 2.11 には quasiquotes 機能が追加されます。quasiquotes の使用方法についてはまだ考えていません。現時点でのすべての資料は、私が持っていない Macro Paradise に精通していることを前提としているようです。