有没有人知道scala中=> Unit的类型?我不知道=> Unit的含义以及如何使用它.我定义了如下函数:
def test(code: => Unit){
print("start ...")
code
print("end ....")
}
test(print(1))
Run Code Online (Sandbox Code Playgroud)
它是否意味着具有返回Unit的任何参数的函数?
谢谢
Mac*_*ndy 23
这种参数称为by-name参数
=> B
表示返回B
值的代码块a ,其目的是仅在调用参数时对它们进行求值.
def foo(code: => Int) {
println("Not yet evaluated")
val result = code
println("parameter evaluated %s, is it an int ? %s " format (
result, result.isInstanceOf[Int]) )
}
Run Code Online (Sandbox Code Playgroud)
您可以foo
通过以下方式致电:
foo(1)
Run Code Online (Sandbox Code Playgroud)
要么
val a = 3
val b = 5
foo {
val c = a * a
c * b
}
Run Code Online (Sandbox Code Playgroud)
另一种传递参数样式是按值:参数在发送到方法之前进行评估
def foo(code : Int) {
println("Parameter already evaluated")
val result = code
println("parameter evaluated : " + result)
}
Run Code Online (Sandbox Code Playgroud)
从Scala中的Book Functionnal Programming中提取
说明了by-name参数和by-value参数之间的更多差异
这称为名称参数,与名称参数评估策略相关.有关传递参数的相似但不相同的方法,请参阅链接的维基百科文章.
为了更好地解释它,让我们首先考虑两个最常见的参数评估策略:按值调用和按引用调用.
按价值呼叫是迄今为止最常见的评估策略.例如,它是Java中的唯一策略,也是C中的默认策略.例如,考虑这个简单的Java程序:
public class ByValue {
static public void inc(int y) {
y++;
}
static public void main(String... args) {
int x = 0;
inc(x);
System.out.println(x);
}
}
Run Code Online (Sandbox Code Playgroud)
它会打印0
,因为它x
的值被复制到y
,所以当y
递增时它不会改变原始值x
.将此与此C++程序进行对比,并使用call-by-reference:
#include <stdio.h>
void inc(int &y) {
y++;
}
int main() {
int x = 0;
inc(x);
printf("%d\n", x);
}
Run Code Online (Sandbox Code Playgroud)
这将打印1
,因为x的引用被传递给inc
,而不是x
值.
请注意,Java按值传递对象引用,这导致一些人声称它通过引用调用.事实并非如此,如果您要将新对象分配给函数的参数,它将不会反映在函数的调用者中.
那么,名字的呼叫是什么样的呢?在按名称调用时,既不传递值也不传递引用.相反,传递整个代码,并且在使用参数的任何地方,执行代码并使用其结果.例如:
object ByName {
def incIfZero(y: => Int): Int = if (y == 0) y + 1 else y
def main(args: Array[String]) {
var x = 0
x = incIfZero( { val tmp = x; x += 1; tmp } )
println(x)
}
}
Run Code Online (Sandbox Code Playgroud)
此示例打印2
而不是1
,因为作为参数传递的代码块被评估两次.执行时,就好像第二行main
一样写成:
x = if ({ val tmp = x; x += 1; tmp }) { val tmp = x; x += 1; tmp } + 1 else { val tmp = x; x += 1; tmp }
Run Code Online (Sandbox Code Playgroud)
现在,通过名称参数至少有三个有趣的用途:
我认为,第一个和最后一个案例非常明显.以下是第二种情况的示例:
implicit def fromBoolean(b: Boolean) = new {
def and(that: => Boolean): Boolean = if (b) that else b }
val x = 0
(x > 0) and (10 / x > 0)
Run Code Online (Sandbox Code Playgroud)
如果that
不是by name参数,则会在最后一行抛出异常.事实上,它将会回归false
.