2010-07-20 59 views
3

当我想使用隐式方法将函数转换为其他东西时,我遇到了一些问题。在scala中使用我的函数 - 在函数上应用隐式转换

我正在Scala 2.8中实现一个小型DSL用于测试目的。它应该支持对实例进行各种检查(如果你喜欢的话)。整个DSL是一个有点复杂,但下面的简单示例说明我的问题:

object PimpMyFunction { 

    class A(val b: Int) 

    def b(a: A) = a.b 

    class ZeroCheck(f: A => Int) { 
    def isZeroIn(a: A) = f(a) == 0 
    } 

    implicit def fToCheck(f: A => Int): ZeroCheck = new ZeroCheck(f)  

    def main(args: Array[String]) { 
    val a0 = new A(0) 
    val a1 = new A(1) 

    println(fToCheck(b).isZeroIn(a0)) 
    println(fToCheck(b).isZeroIn(a1)) 

    println(b.isZeroIn(a0)) 
    } 
} 

前两位的println线(当我明确地调用转换方法)编制,做工精细,但最后一个(当我想依靠implicits)产生的错误:
Compile error: missing arguments for method b in object PimpMyFunction; follow this method with '_' if you want to treat it as a partially applied function
如果我想隐式地转换“正常”的实例(这不是函数)的方式,它也可以工作,所以我猜这个问题与范围/导入无关。

如果我按照错误消息的指示并使用println((b _).isZeroIn(a0))它也可以工作,但DSL是针对非技术人员的,因此我希望保持语法尽可能干净和简单。

我想我有另一种解决方法(b应该是一个扩展了一个断言特征的类,它已经包含了检查方法+ A => Int),它将支持更清晰的语法,但它会更冗长和更不灵活,所以我宁愿隐含的方式。

任何想法如何避免(b _)语法,仍然使用implicits?

回答

6

Scala要求您编写(b _)以确保您确实希望将方法b装箱为函数值。如果你不想写下划线,直接定义b可能是一个函数值,而不是一个方法:发生

val b = (a: A) => a.b 
+1

用于通过部分应用程序将方法转换为函数的术语是“提升”或“提升”。 – 2010-07-20 13:56:08

+0

就像丹尼尔的解决方案一样,工作就像一个魅力。我看不出两者之间有什么重大区别,你是第一个 - >这就是我所接受的,即使他们两个都完美地解决了我的问题。谢谢你的答案。 – 2010-07-21 07:08:11

4

的问题,因为b不是一个函数,而是一个方法。请查找关于该主题的相关问题。如果定义b像下面,但是,你应该不会有任何问题:

def b = (_: A).b 

这定义的b类型是一个函数。

+0

谢谢,请参阅接受答案的评论。 – 2010-07-21 07:08:35