【问题标题】:Generate functions based on type parameter根据类型参数生成函数
【发布时间】:2019-11-16 21:01:54
【问题描述】:

我想为一个接受 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 宏来实现这一点?或者,这可以通过其他方式实现吗?

【问题讨论】:

    标签: scala macros metaprogramming implicit dotty


    【解决方案1】:

    尝试在您之前的@​​987654321@@KrzysztofAtłasik 建议的基础上再添加一个隐式转换。

    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]]是不允许的。

    【讨论】:

    • 通过在conversion1的参数中添加名字,实际上实现了惰性,所以conversion1会变成隐式 def conversion1[T](t: => T): C[T] = new C(t )
    • 虽然,通过使用这种方法,为了保持惰性,计算的类型需要显式设置为 C[T],否则会选择 T 并评估 t
    猜你喜欢
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多