首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Scala中defs/lambdas的隐式转换?

Scala中defs/lambdas的隐式转换?
EN

Stack Overflow用户
提问于 2015-02-11 17:07:36
回答 1查看 794关注 0票数 8

我刚刚在函数和对象之间遇到了奇怪的差异(scala 2.10):

代码语言:javascript
运行
复制
implicit def conv(c: Int => String) : (PrintStream => Int => Unit) = p => v => p.println(c(v))
def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1)

def a(x: Int) = x.toString
val b = (x: Int) => x.toString

//    def main(args: Array[String]) = f(a) // fail
//    def main(args: Array[String]) = f((x: Int) => x.toString) // fail
def main(args: Array[String]) = f(b) // ok

为什么defs/lambda字面量和lambda函数有区别?

更新:显然,二进制函数不会出现这个问题:Implicit conversion of a function to a second-order-function only works if the function to convert has at least two parameters

我对此进行了检查,实际上,以下代码可以正常工作:

代码语言:javascript
运行
复制
implicit def conv(c: (Int,Unit) => String) : (PrintStream => Int => Unit) = p => v => p.println(c(v,()))
def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1)

def a(x: Int, y : Unit) = x.toString
val b = (x: Int, y : Unit) => x.toString

def main(args: Array[String]) = f(a) // ok
def main(args: Array[String]) = f((x: Int, y: Unit) => x.toString) // ok
def main(args: Array[String]) = f(b) // ok

同样,Nullary函数也不会带来问题:

代码语言:javascript
运行
复制
implicit def conv(c: () => String) : (PrintStream => Int => Unit) = p => v => p.println(c())
def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1)

def a() = "1"
val b = () => "1"

def main(args: Array[String]) = f(a) // ok
def main(args: Array[String]) = f(() => "1") // ok
def main(args: Array[String]) = f(b) // ok

因此,换句话说:为什么这不适用于UNARY方法和函数?

更新:这个问题似乎也与目标类型(f的参数h的类型)有关。下面的方法也是有效的(这一次,支持"eta-expansion counts as hop",因为我们需要从using _创建一个方法值)

代码语言:javascript
运行
复制
implicit def conv(c: Int => String) : Unit = ()
def f(h: Unit) : Unit = System.out.print("?")

def a(x: Int) = x.toString
val b = (x: Int) => x.toString

def main(args: Array[String]) = f(a _) // ok
def main(args: Array[String]) = f((x: Int) => x.toString) // ok
def main(args: Array[String]) = f(b) // ok
EN

回答 1

Stack Overflow用户

发布于 2015-02-11 21:21:39

在scala中,defsmethods,不同于functions

代码语言:javascript
运行
复制
scala> def a( x: Int, y: Int ): Int = x + y
a: (x: Int, y:Int)Int

scala> (x: Int, y: Int) => x + y
res0: (Int, Int) => Int = <function2>

您可以通过部分应用method来将其转换为function

代码语言:javascript
运行
复制
scala> b _
res1: (Int, Int) => Int = <function2>

所以..。你能做到的,

代码语言:javascript
运行
复制
implicit def conv(c: Int => String) : (PrintStream => Int => Unit) = p => v => p.println(c(v))
def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1)

def a(x: Int) = x.toString
val af = a _

def main( args: Array[ String ] ) = f( af )

此外,正如@srgfed01在他的评论中提到的那样...对于第二种情况,问题是...它们的类型不是显式指定的,如果您正确指定了类型...第二种情况是可行的。

代码语言:javascript
运行
复制
scala> f( ( a => a.toString ): (Int => String) )
1

代码语言:javascript
运行
复制
scala> f( ( _.toString ): (Int => String) )
1

现在,关于methodsfunctions之间的区别...

您可以调用不带括号的不带参数的method ()...但是你不能在没有()的情况下调用函数。

代码语言:javascript
运行
复制
scala> def g() = 5
g: ()Int

scala> g
res15: Int = 5

scala> () => 5
res13: () => Int = <function0>

scala> res13
res14: () => Int = <function0>

scala> res13()
res15: 5

methodsfunctions不同的一个最重要的原因是,Scala的创建者希望与Java实现无缝的互操作性,而不是受困于Java的局限性。

因此,methods (def)非常类似于Java,保持methodsmethods的不同使他们能够以自己想要的方式无限自由地创建functions

还有..。另一个主要区别是methods可以接受Type-classes,而as functions不能。基本上,你可以使用泛型methods,比如

代码语言:javascript
运行
复制
scala> :paste

trait Behave {
    def behave
}

class A( elem: String ) extends Behave {
  def behave() {
    println( elem )
  }
}

// Exiting paste mode, now interpreting.

defined trait Behave
defined class A

现在您可以定义一个泛型方法,

代码语言:javascript
运行
复制
scala> def check[ T <: Behave ]( t: T ): Unit = t.behave()
check: [T <: Behave](t: T)Unit

但是你不能定义这样的函数,

代码语言:javascript
运行
复制
scala> ( t: T ) => t.behave()
<console>:8: error: not found: type T
          ( t: T ) => t.behave()

或者像这样

代码语言:javascript
运行
复制
scala> ( t: (T <: Behave) ) => t.behave()
<console>:1: error: ')' expected but '<:' found.
   ( t: (T <: A) ) => t.behave()
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28450337

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档