我在Scala中编写了一个简单的代码,将Function1隐式转换为某个case类。
object MyApp extends App{
case class FunctionContainer(val function:AnyRef)
implicit def cast(function1: Int => String):FunctionContainer = new FunctionContainer(function1)
def someFunction(i:Int):String = "someString"
def abc(f : FunctionContainer):String = "abc"
println(abc(someFunction))
}
但它不起作用。编译器并不想将someFunction作为参数传递给abc。我可以猜出它的原因,但不知道它为什么不起作用。
答案 0 :(得分:3)
您的someFunction
在此处显示为方法。
你可以试试
object MyApp extends App{
case class FunctionContainer(val function:AnyRef)
implicit def cast(function1: Int => String):FunctionContainer = new FunctionContainer(function1)
val someFunction = (i:Int) => "someString"
def abc(f : FunctionContainer):String = "abc"
println(abc(someFunction))
}
或
object MyApp extends App{
case class FunctionContainer(val function:AnyRef)
implicit def cast(function1: Int => String):FunctionContainer = new FunctionContainer(function1)
def someFunction(i:Int): String = "someString"
def abc(f : FunctionContainer):String = "abc"
println(abc(someFunction(_: Int)))
}
顺便说一下:隐含地将这些常用函数强制转换为其他东西会很快导致问题。你绝对确定你需要这个吗?重载abc
会不会更容易?
答案 1 :(得分:3)
当您使用方法名称时,编译器必须选择如何将方法类型转换为值。如果期望的类型是一个函数,那么它会扩展;否则它提供空的parens来调用该方法。这被描述为here in the spec。
但并非总是如此。十年前,只需使用方法名称即可得到函数值。
新的在线规范省略了“更改日志”附录,因此,对于记录,这是有人对parens感到沮丧并介绍当前规则的时刻。 (参见Scala参考2.9,第181页。)
这并没有消除所有irksome anomalies。
用于隐式转换方法到函数(第6.26节)的规则已经收紧。以前,用作值的参数化方法始终隐式转换为函数。当忘记方法参数时,这可能会导致意外结果。例如,考虑下面的陈述:
show(x.toString)
其中show定义如下:
def show(x: String) = Console.println(x)
最有可能的是,程序员忘了向toString提供一个空参数列表()。以前的Scala版本会将此代码视为部分应用的方法,并将其扩展为:
show(() => x.toString())
结果,将打印闭包的地址而不是s的值。仅当表达式的预期类型确实是函数类型时,Scala版本2.0才会将部分应用的方法转换为函数值。例如,转换不会应用于上面的代码中,因为show的参数的预期类型是String,而不是函数类型。新公约不允许一些以前合法的代码。例如:
def sum(f: int => double)(a: int, b: int): double =
if (a > b) 0 else f(a) + sum(f)(a + 1, b)
val sumInts = sum(x => x) // error: missing arguments
上面代码的最后一行中sum的部分应用不会转换为函数类型。相反,编译器将生成一条错误消息,指出缺少方法sum的参数。可以通过为部分应用程序提供预期类型来解决该问题,例如通过使用其类型注释sumInts的定义:
val sumInts: (int, int) => double = sum(x => x) // OK
另一方面,Scala 2.0版现在会在必要时自动将具有空参数列表的方法应用于()参数列表。例如,上面的show表达式现在将扩展为
show(x.toString())
答案 2 :(得分:2)
你应该使用eta-expansion
println(abc(someFunction _))