我已经定义了以下类:
class TransparentFunction1[-T1, +R1](val func : T1 => R1, val text : String) {
@inline
def apply(t : T1) = func(t)
override def toString = text
}
基本上,TransparentFunction1
只是Function1
的包装器,它提供了一个描述函数内容的人类可读文本字段。
我想定义一个隐式转换,可以将任何Function1转换为TransparentFunction1
,并将函数的代码传递给text参数。
我已经使用宏定义了这种隐式转换:
implicit def transparentFunction1[T1, R1](expression : T1 => R1) : TransparentFunction1[T1, R1] = macro Macros.transparentImpl[T1, R1, TransparentFunction1[T1, R1]]
object Macros {
def transparentImpl[T : context.WeakTypeTag, U : context.WeakTypeTag, V : context.WeakTypeTag](context : scala.reflect.macros.whitebox.Context) (expression : context.Expr[T => U]) : context.Expr[V] = {
import context.universe._
context.Expr[V](
Apply(
Select(
New(
TypeTree(
appliedType(weakTypeOf[V].typeConstructor, weakTypeOf[T] :: weakTypeOf[U] :: Nil)
)
),
termNames.CONSTRUCTOR
),
List(expression.tree, Literal(Constant(expression.tree.toString)))
)
)
}
}
这很有效。但是,它会导致类型推断出现问题。
例如,如果我尝试调用一个名为&#34的方法; map"它采用类型为TransparentFunction1[Int, Int]
的参数:
map(_ + 2)
我收到错误"缺少扩展函数"的参数类型,而如果map的参数类型只是Int => Int
,则类型推断可以正常工作。
有没有办法修复宏,以便类型推断继续有效?
答案 0 :(得分:2)
要解决此问题,您只需要TransparentFunction1
延长Function1
(这似乎很自然,因为TransparentFunction1
在概念上非常Function1
,它只是添加了一个自定义toString
,但应该作为一个普通的功能):
class TransparentFunction1[-T1, +R1](val func : T1 => R1, val text : String) extends (T1 => R1){
@inline
def apply(t : T1) = func(t)
override def toString = text
}
我只能看到一小部分理由来定义类似函数的类不扩展Function1
。在我的脑海中,主要原因是当你的类被设计为用作隐式值(例如类型类)时,你不希望编译器自动将这些隐式值用作隐式转换(它将会如果它延伸Function1
)。这似乎并非如此,因此TransparentFunction1
扩展Function1
似乎是正确的做法。