Scala通过名称混淆呼叫
我正在使用REPL通过名称示例进行一些调用,并在
Eclipse中运行相同的示例.
以下是Eclipse中的内容: val funct = {println("Calling funct")} takesFunct(funct) def takesFunct(f: => Unit) { val b = f } 输出是:调用函数 场景2: takesFunct({println("Calling funct")} 输出是: Scala REPL scala> def takesFunct(f: => Unit) { val b = f } takesFunct: (f: => Unit)Unit scala> val funct = {println("Calling funct")} Calling funct funct: Unit = () scala> takesFunct(funct) // No Output 情景2 scala> takesFunct({println("Calling funct")} Calling funct 两个问题 val funct = {...} takesFunct(funct) 而不是 takesFunct({...}) 解决方法
在@ IttayD回答后更新:
Eclipse上的场景1是正确的,你会在下面看到原因.场景2显然是一个Eclipse错误. Eclipse上的ScalaIDE因其破碎而闻名.我不相信(或使用它).如果必须,请使用Intellij IDEA的Scala插件. 你的两个问题的答案是,{}是一个块,它返回它的最后一个语句的返回类型.它与Scheme的(开始)或Common Lisp(预测)完全相同.当你有: scala> def takesFunct(f: => Unit) { val b = f } takesFunct: (f: => Unit)Unit scala> val funct = {println("Calling funct")} Calling funct funct: Unit = () scala> takesFunct(funct) // No Output funct的RHS已经过热切评估,并返回了一个类型为Unit的值().将已计算的值应用于按名称调用的函数并在正文中使用它不会导致重新评估,因为该值已经是叶子. 进一步更新: def takesFunct(f: => Unit) 具有与…基本相同的语义 def takesFunct(f: () => Unit) 在某些圈子中称为流式传输或延迟评估.但是有一个主要的区别,就是你调用提供的参数的方式.在后一种情况下,为了从f中获取一个值,你必须这样调用它 – 即f().在前一种情况下,f是一个惰性表达式,它在第一次被引用时计算为一个值,因此按名称调用.你可以想到语法f:=>单位作为一种自动包装您在容器{}中提供的任何表达式的方法.使用时检索其内容如下: scala> val a = { 1 } // 1 wrapped in {},and retrieved when assigned to a a: Int = 1 那么这个怎么样? scala> takesFunct({println("Calling funct")}) Calling funct 这是因为现在您正在创建一个绑定到函数参数f的就地块,并且仅在val b = f中使用它时才会计算它.我们再做一个实验: scala> takesFunct(println("Calling funct")) Calling funct 你怎么问?因为println(…)被包裹在绑定到f的{}中.引用f检索容器内的值,即println(…)的值,即():Unit.在前面的示例中,f绑定到{{println(…)}},这与{println(…)}相同,因此您得到相同的结果.事实上,你可以无限期地嵌套{},但仍然会得到同样的东西.唯一的区别是,手动提供{}允许您将多个语句放入其中: scala> takesFunct({ println("hello"); println("world") }) hello world 希望这可以帮助. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |