scala - Scala 中没有参数和名称参数 eta 扩展混淆
问题描述
我有以下代码
def call1 = 4
call1 _
并收到以下警告:
没有参数列表和按名称参数的方法不能再转换为函数 as ,而是
m _
写一个函数文字() => m
我不确定是否完全理解这里的原因和部分句子。显然,我在这里没有名称参数。
首先是警告可以分成两部分:
1)
没有参数列表的方法不能再转换为函数 as ,而是
m _
写一个函数文字() => m
按名称参数不能再转换为函数 as ,而是
m _
写一个函数文字() => m
我正在寻求 1) 和 2) 的解释。在第 2 点上,我很难想象为什么以及何时将别名参数转换为函数。
解决方案
两者都可以通过以下方式证明:
def needFunction(f: () => String) = {
println("calling function")
println(f())
}
def paramLess: String = {
println("calculating value")
"foo"
}
我想paramLess
传入needFunction
. 什么时候评估?
needFunction(() => paramLess) // (1)
// calling function
// calculating value
// foo
这很明显——paramLess
将在里面进行评估needFunction
。但是这个?
needFunction(paramLess _) // (2)
(2)
是一样的,(1)
但我需要花点时间思考一下它会如何表现并在 REPL 中运行它来确定。
这会经常发生,尤其是在使用别名参数时——您想让一些 API 易于用户使用,因此您将thunk: => A
其作为参数,但在内部您传递() => A
的是确切知道何时进行评估(将一个别名传递给另一个别名等等,希望两者之间没有任何评估会导致一些非常脆弱的代码)。
带参数的函数和方法没有可读性问题——如果你不把()
它放在不被评估的地方。您可以编写它、传递它、返回它 - 但如果没有传递参数,则没有评估。无参数方法在您每次使用它们的名称时都会进行评估,因此如果它们执行副作用或一些昂贵的计算,它们会很棘手 - 然而,这是避免和不鼓励的,因为建议您至少将()
参数列表添加到副作用方法。同时,它们有点假装是不需要争论的价值观。显然,这里的社区决定,如果他们想伪装成值,就应该将它们用作值,() => value
作为创建函数的方式——如果我们不将它们用于副作用,这是有道理的。
By-name 参数在可读性方面是一个类似的情况,但是 - 从我所见 - 它们有很多极端情况,当与 eta-expansion 结合使用时会导致错误,而且它们也经常(几乎总是?)出现在副作用的背景
def inSomeContext(context: Arguments)(thunk: => SideEffects) = ...
// Try.apply
// IO.apply
// option.fold(noneByName)(some => ...)
// ...
这使得它们比无参数方法(不鼓励副作用)更加危险,因此警告更加合理。
最重要的是,它主要是关于可读性、安全性和避免意外:
- 在可以用作
val
ues 时使用不带参数的方法(初始化顺序可能是原因之一)而没有副作用和意外(在无参数方法中有更多警告警告副作用), - 和名称参数作为在您的 API 中使用的好东西,但它会在内部立即手动转换为您可以安全传递的函数(甚至是
() => A
某种函数)或值 (val evaluated = thunk
)。
对这些其他用法的警告有助于保持代码的可读性并且没有意外。
推荐阅读
- javascript - 如何重定向到带有密码的页面,但无法通过 URL 访问该页面?
- sql - 从另一个表中插入值并使用返回值更新原始表
- python - 如何将 pd.DataFrame.rolling.corr() 与 Kendall 的 Tau 或 Spearman 一起使用
- flutter - 我是否总是必须等待“https://google.bintray.com”在停机维护后才能完全运行,然后才能构建我的颤振应用程序?
- node.js - AWS Fargate 服务中的“导致执行用户进程:执行格式错误”
- git - 为本地浅拷贝切换 git 标签/分支
- sapui5 - 如何控制 MasterDetail 应用程序的边距
- django - 无法重定向到最近创建的详细视图
- angular - Angular 沿应用程序保存 http 响应
- system-verilog - 如何从 1 到 52 System Verilog 生成可合成的伪随机发生器