根据类型参数生成函数

时间:2019-07-06 17:52:11

标签: scala macros metaprogramming implicit dotty

我想为一个接受1个类型参数的类生成函数,该类型参数按名称值包装。

class C[T](_t: => T) {
    def t: T = _t
}

我想生成的函数是由T上可用的函数派生的。

我确切想要的是获得T可用的所有功能,以编程方式更改其合约实施,并使它们可用于C

  • 通过更改合同,我的意思是更改其签名,以便他们返回C[R],其中R代表原始函数的返回类型。

  • 通过更改其实现,我的意思是在返回结果之前将结果包装在C中。

例如

def +(that: Int): Int =
    this + that

将在C[Int]上以

的形式提供
def +(that: Int): C[Int] =
    C(this.t + that)

这样做是为了消除必须在C内包装计算以使其不被评估的样板。

例如

val c1 = new C(1)

val c2: C[Int] = C(c1.t + 1)
c2.t == 2

也可以表示为

val c2: C[Int] = c1 + 1
c2.t == 2

如何通过使用Scala 2或dotty宏来实现此目标?还是可以通过其他方式实现?

1 个答案:

答案 0 :(得分:3)

根据@KrzysztofAtłasik在您之前的question中的建议,尝试另外添加一个隐式转换。

implicit def conversion[T](c: C[T]): T = c.t
implicit def conversion1[T](t: => T): C[T] = new C(t)

或使类隐式

implicit class C[T](_t: => T) {
  def t: T = _t
}

关于宏,由于要添加定义,因此需要macro annotations而不是def macros。 Dotty没有宏注释,只有inline macros像Scala 2 def宏。

宏注释也无济于事。当您定义类C[T]时,不知道T是什么(只有在呼叫站点才知道),因此不知道要添加什么方法。

Dotty也有隐式转换

given [T] as Conversion[T, C[T]] = new C(_)
given [T] as Conversion[C[T], T] = _.t

(当前是given,以前是implicit,然后是implied,然后是delegate,目前为0.17 given,可以再次更改)。

似乎不允许使用Conversion[(=> T), C[T]]