使用val定义函数

时间:2018-02-17 11:49:21

标签: scala function

我知道使用def / val在scala中定义函数之间的基本区别:如果我使用val,我的函数定义一次,如

scala> val valRandom = Random.nextInt
valRandom: Int = 2032538454

scala> valRandom
res0: Int = 2032538454

但我的问题是为什么每次使用像:

这样的函数时都会计算Random.nextInt
scala> val valRandom2 = (_:Int) + Random.nextInt
valRandom2: Int => Int = $$Lambda$1100/1597979904@1a6dc5ea

scala> valRandom2(0)
res2: Int = 486047489

scala> valRandom2(0)
res3: Int = 1573520480

3 个答案:

答案 0 :(得分:2)

在你的第一种方法中,

scala> val valRandom = Random.nextInt
valRandom: Int = 2032538454

如果您发现valRandom的类型为int。基本上,您已使用Random.nextInt初始化valRandom。

但是,在第二种方法中,

scala> val valRandom2 = (_:Int) + Random.nextInt
valRandom2: Int => Int = $$Lambda$1100/1597979904@1a6dc5ea

您注意到valRandom2的类型是Int -> Int的映射 valRandom2是一个函数值,它只是一个匿名函数或一个lambda表达式。

因此,每当您调用它时,它始终会生成新值。

两种方法的不同之处在于第一种方法是创建变量并为其分配随机值。但是在第二种方法中,您正在调用匿名函数,因此每次都会进行评估

答案 1 :(得分:0)

在valRandom2中,随机偏移量在函数体内计算,因此每次调用函数时都会计算它。

您需要计算函数外部的随机偏移量,如下所示:

val valRandom3 = { val rand = Random.nextInt; (_:Int) + rand }

答案 2 :(得分:0)

我的回复:

scala>  val valRandom2 = (_:Int) + Random.nextInt
valRandom2: Int => Int = <function1>

所以valRandom2是一个东西,它接受一个I​​nt并返回一个Int,并且类型为function1。例如:

scala>  val valRandom3 = (_:Int) + (_:Int) + Random.nextInt
valRandom3: (Int, Int) => Int = <function2>

这是function2类型。

数字(1,2)表示传入了多少参数。函数总是返回一个值,所以这并不重要。即使没有返回,因为它是一个过程,可能需要副作用,它会隐式返回Unit()。如果它返回一个东西或一个元组的List,这只是一件事,你必须分开,以获得多个值中的一个。

功能与方法无关。函数可以传递并且执行被延迟,而方法是直接调用的,但是将方法作为函数传递很容易。

scala> def add (a: Int, b:Int) : Int = a + b
add: (a: Int, b: Int)Int

scala> def mul (a: Int, b:Int) : Int = a * b
mul: (a: Int, b: Int)Int

scala> def printIt (a: Int, b:Int, f:(Int, Int) => Int) = {
     |   val c = f (b, a) 
     |   println (s"b $b (X) a $a = c $c") 
     | }
printIt: (a: Int, b: Int, f: (Int, Int) => Int)Unit

scala> printIt (3, 4, add) 
b 4 (X) a 3 = c 7

scala> printIt (3, 4, mul) 
b 4 (X) a 3 = c 12

这个例子虽然简单易懂,但并没有解释为什么它有用,但有用的例子设置起来比较复杂。但想象一下可以对数值进行排序的List。如果你有一个Employees列表,你可以通过将一个函数交给List来对它们进行排序,从Employee中获取一个Numeric,可以是Employee.id,* .age,* .maxSalary(),. add.zipCode或者无论如何,这会给你最大的灵活性。

评论:

scala>  val valRandom2 = {println ("vR2 called"); (_:Int) + Random.nextInt}
vR2 called
valRandom2: Int => Int = <function1>

scala> val x = valRandom2 (0)
x: Int = -1231081

scala> val x = valRandom2 (0)
x: Int = 1421497830

为什么在声明时执行打印,但在使用时执行nextInt?

因为

scala>  val valRandom2 = {println ("vR2 called"); (_:Int) + Random.nextInt}
vR2 called
valRandom2: Int => Int = <function1>

scala>  val valRandom2 = {println ("vR2 called"); (_:Int) + Random.nextInt}
vR2 called
valRandom2: Int => Int = <function1>

scala> val x = valRandom2
x: Int => Int = <function1>

rhs的结果是函数,它被赋值给valRandom2或x,而print是声明的副作用。该块作为其最后一个表达式返回该函数。

在valRandom2上交换内部调用,你什么也得不到(单位)。

将参数Int添加到第二个调用:

scala>  val valRandom3 = {Random.nextInt; (_:Int) => println ("vR2 called") }
valRandom3: Int => Unit = <function1>

scala> valRandom3 (0)
vR2 called

scala> valRandom3 (0)
vR2 called