与下划线一起使用时,部分函数应用程序过早运行代码块 [英] Partial function application prematurely runs codeblock when used with underscore

查看:43
本文介绍了与下划线一起使用时,部分函数应用程序过早运行代码块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定:

def save(f: => Any)(run:Boolean) { if (run) { println("running f"); f } else println("not running f") } 

我可以用:

save("test")(true) -> running f
save("test")(false) -> not running f
save(throw new RuntimeException("boom!"))(false) -> not running f
save(throw new RuntimeException("boom!"))(true) -> running f and then exception thrown

这是部分应用的奇怪行为:

Here's the curious behaviour with partial application:

save(throw new RuntimeException("boom!"))(_) -> (Boolean) => Unit = <function1> //as expected
save(throw new RuntimeException("boom!")) _ -> exception thrown

代码块被立即评估,而不是作为函数传入.以上2个说法有什么区别?

The codeblock is evaluated immediately without being passed in as a function. What is the difference between the above 2 statements?

推荐答案

第一种情况,

save(throw new RuntimeException("boom!")) _ 

根据 Scala 参考"(第 6.7 节),尾随使用下划线代替参数列表,并将表达式转换为

According to "Scala Reference" (§6.7), trailing underscore is used in place of the argument list, and expression is converted to

val f: (Boolean) => Unit = save(throw new RuntimeException("boom!"))

def save 的第一个参数立即被求值.

where the first argument of def save is immediately evaluated.

表达式 e _ 是合式的,如果 e是方法类型或者如果 e 是一个按名称调用参数.如果 e 是带参数的方法,e_代表e 被 eta 转换为函数类型扩展(第 6.26.5 节).如果 e 是无参数方法或按名称调用类型 =>T 的参数,e _ 表示类型 () => T 的函数,其中将 e 应用于空参数列表().

The expression e _ is well-formed if e is of method type or if e is a call-by-name parameter. If e is a method with parameters, e _ represents e converted to a function type by eta expansion (§6.26.5). If e is a parameterless method or call-by-name parameter of type =>T , e _ represents the function of type () => T , which evaluates e when it is applied to the empty parameterlist ().

为了使事情如您所愿,需要进行一些修改:

To make the things work as you expect, some modifications are required:

scala> def save(f:() => Any)(run:Boolean) { if (run) { println("running f"); f() } else println("not running f") }
save: (f: () => Any)(run: Boolean)Unit

scala> val f = save(() => throw new RuntimeException("boom!")) _
f: (Boolean) => Unit = <function1>

scala> f(true)
running f
java.lang.RuntimeException: boom!
        at $anonfun$1.apply(<console>:6)

第二种情况,

save(throw new RuntimeException("boom!"))(_)

根据 Scala 参考"(第 6.23 节),当占位符用作参数的替代,表达式被转换为

According to "Scala Reference" (§6.23), when placeholder is used as a replacement for an argument, the expression is converted to

val f: (Boolean) => Unit = save(throw new RuntimeException("boom!"))(_)

这篇关于与下划线一起使用时,部分函数应用程序过早运行代码块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆