我想为一个接受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宏来实现此目标?还是可以通过其他方式实现?
答案 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]]
。