3
votes

I have some problems when I want to use implicit methods to convert a function to something else.

I'm implementing a small DSL in Scala 2.8 for testing purposes. It should support various checks (assertions if you like) on instances. The whole DSL is a bit complex, but the following simplified example shows my problem:

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)) 
  }
}

First two println lines (when I explicitly call the conversion method) compile and work fine, but the last one (when I want to rely on implicits) produces the error:
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
If I want to implicitly convert "normal" instances (which are not functions) the same way it also works, so I guess the problem is not related to scoping/importing.

If I follow the instructions of the error message and use println((b _).isZeroIn(a0)) it also works, but the DSL is targeted at non technical people, so I would like to keep the syntax as clean and simple as possible.

I think I have another workaround (b should be a class extending an Assertions trait which already contain the check methods + A => Int) that would support the cleaner syntax, but it would be more verbose and less flexible, so I would prefer the implicit way.

Any ideas how to avoid the (b _) syntax and still use implicits?

2

2 Answers

6
votes

Scala requires you to write (b _) to ensure that you really want the method b to be boxed to a function value. If you don't want to write the underscore, directly define b to be a function value instead of a method:

val b = (a: A) => a.b
4
votes

The problem happens because b is not a function, but a method. Please look up related questions on that topic. If you define b like below, though, you shouldn't have any problems:

def b = (_: A).b

This defines the type of b to be a function.