我可以从模板生成Scala代码吗?

mnowg1ta  于 2022-12-13  发布在  Scala
关注(0)|答案(3)|浏览(122)

我可以从模板生成Scala代码吗?
我知道如何在Racket/Scheme/Lisp中做到这一点,但在Scala中却不知道。这是Scala宏可以做到的吗?
我想要一个X变化的代码模板。如果我有这个代码模板:

def funcX(a: ArgsX): Try[Seq[RowX]] =
  w.getThing() match {
    case Some(t: Thing) => w.wrap(t){Detail.funcX(t, a)}
    case _ => Failure(new MissingThingException)
  }

和标记AppleOrange,宏将采用my模板,替换X,并生成:

def funcApple(a: ArgsApple): Try[Seq[RowApple]] =
  w.getThing() match {
    case Some(t: Thing) => w.wrap(t){Detail.funcApple(t, a)}
    case _ => Failure(new MissingThingException)
  }

def funcOrange(a: ArgsOrange): Try[Seq[RowOrange]] =
  w.getThing() match {
    case Some(t: Thing) => w.wrap(t){Detail.funcOrange(t, a)}
    case _ => Failure(new MissingThingException)
  }
toe95027

toe950271#

使用树转换器尝试macro annotation
第一个
你也可以尝试用类型类的方法

def func[A <: Args](a: A)(implicit ar: ArgsRows[A]): Try[Seq[ar.R]] =
  w.getThing() match {
    case Some(t: Thing) => w.wrap(t){Detail.func(t, a)}
    case _ => Failure(new MissingThingException)
  }

trait ArgsRows[A <: Args] {
  type R <: Row
}
object ArgsRows {
  type Aux[A <: Args, R0 <: Row] = ArgsRows[A] { type R = R0 }

  implicit val apple: Aux[ArgsApple, RowApple] = null
  implicit val orange: Aux[ArgsOrange, RowOrange] = null
}

sealed trait Args
trait ArgsApple extends Args
trait ArgsOrange extends Args

trait Thing

sealed trait Row
trait RowApple extends Row
trait RowOrange extends Row

object Detail {
  def func[A <: Args](t: Thing, a: A)(implicit ar: ArgsRows[A]): ar.R = ???
}

class MissingThingException extends Throwable

trait W {
  def wrap[R <: Row](t: Thing)(r: R): Try[Seq[R]] = ???
  def getThing(): Option[Thing] = ???
}

val w: W = ???
lf3rwulv

lf3rwulv2#

在我看来,您可以将funcX函数作为高阶函数传递,也可以将它与currying结合起来,创建一个 “函数工厂”

def funcX[A](f: (Thing, A) => RowX)(a: A): Try[Seq[RowX]] =
  w.getThing() match {
    case Some(t: Thing) => w.wrap(t){f(t,a)}
    case _ => Failure(new MissingThingException)
 }

然后,您可以使用它来创建funcApplefuncOrange的示例:

val funcApple: ArgsApple => Try[Seq[RowX]] = funcX(Detail.funcApple)

val funcOrange: ArgsOrange => Try[Seq[RowX]] = funcX(Detail.funcOrange)

funcApple(argsApple)

funcOrange(argsOrange)

我假设Detail.funcAppleDetail.funcOrange的签名与(Thing, X) => RowX相似,但当然您可以使用不同的签名。

ax6ht2ek

ax6ht2ek3#

您可能实际上不需要宏来实现这一点,您可以使用一个模式匹配一个泛型类型,如下所示:

import scala.util.Try

def funcX[A](input :A) :Try[Seq[String]] = input match {
  case x :String => Success(List(s"Input is a string: $input, call Detail.funcApple"))
  case x :Int => Success(List(s"Input is an int, call Detail.funcOrange"))
}

scala> funcX("apple")
res3: scala.util.Try[Seq[String]] = Success(List(Input is a string: apple, call Detail.funcApple))

scala> funcX(11)
res4: scala.util.Try[Seq[String]] = Success(List(Input is an int, call Detail.funcOrange))

相关问题