Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala “与”的区别是什么;def";及;val";定义函数_Scala - Fatal编程技术网

Scala “与”的区别是什么;def";及;val";定义函数

Scala “与”的区别是什么;def";及;val";定义函数,scala,Scala,以下两者之间的区别是什么: def even: Int => Boolean = _ % 2 == 0 及 两者都可以称为偶数(10)考虑一下: scala> def even: (Int => Boolean) = { println("def"); (x => x % 2 == 0) } even: Int => Boolean scala> val even2: (Int =>

以下两者之间的区别是什么:

def even: Int => Boolean = _ % 2 == 0

两者都可以称为偶数(10)

考虑一下:

scala> def even: (Int => Boolean) = {
             println("def"); 
             (x => x % 2 == 0)
       }
even: Int => Boolean

scala> val even2: (Int => Boolean) = {
             println("val");
             (x => x % 2 == 0)
       }
val //gets printed while declaration. line-4
even2: Int => Boolean = <function1>

scala> even(1)
def
res9: Boolean = false

scala> even2(1)
res10: Boolean = false
初始化
x
时,
Random.nextInt
返回的值被设置为
x
的最终值。下次再次使用
x
时,它将始终返回相同的值

您还可以延迟初始化
x
。i、 e.第一次使用时,它是初始化的,而不是在声明时。例如:

scala> lazy val y = { Random.nextInt }
y: Int = <lazy>

scala> y
res4: Int = 323930673

scala> y
res5: Int = 323930673
scala>lazy val y={Random.nextInt}
y:Int=
scala>y
res4:Int=323930673
scala>y
res5:Int=323930673
考虑一下:

scala> def even: (Int => Boolean) = {
             println("def"); 
             (x => x % 2 == 0)
       }
even: Int => Boolean

scala> val even2: (Int => Boolean) = {
             println("val");
             (x => x % 2 == 0)
       }
val //gets printed while declaration. line-4
even2: Int => Boolean = <function1>

scala> even(1)
def
res9: Boolean = false

scala> even2(1)
res10: Boolean = false
初始化
x
时,
Random.nextInt
返回的值被设置为
x
的最终值。下次再次使用
x
时,它将始终返回相同的值

您还可以延迟初始化
x
。i、 e.第一次使用时,它是初始化的,而不是在声明时。例如:

scala> lazy val y = { Random.nextInt }
y: Int = <lazy>

scala> y
res4: Int = 323930673

scala> y
res5: Int = 323930673
scala>lazy val y={Random.nextInt}
y:Int=
scala>y
res4:Int=323930673
scala>y
res5:Int=323930673

方法
def-even
在调用时求值,并每次创建新函数(函数1的新实例)

使用
def
可以在每次调用时获得新函数:

val test: () => Int = {
  val r = util.Random.nextInt
  () => r
}

test()
// Int = -1049057402
test()
// Int = -1049057402 - same result

def test: () => Int = {
  val r = util.Random.nextInt
  () => r
}

test()
// Int = -240885810
test()
// Int = -1002157461 - new result
val
在定义时求值,
def
-调用时:

scala> val even: Int => Boolean = ???
scala.NotImplementedError: an implementation is missing

scala> def even: Int => Boolean = ???
even: Int => Boolean

scala> even
scala.NotImplementedError: an implementation is missing
请注意,还有第三个选项:
lazy val

它在第一次调用时求值:

scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>

scala> even
scala.NotImplementedError: an implementation is missing
性能

val
在定义时进行计算

def
在每次调用时进行评估,因此对于多个调用,性能可能比
val
差。您只需拨打一个电话即可获得相同的性能。如果没有调用,您将不会从
def
中获得任何开销,因此您可以定义它,即使您不会在某些分支中使用它

使用
lazy val
您将得到一个懒惰的计算:即使您不在某些分支中使用它,您也可以定义它,并且它会计算一次或从未计算过,但是对
lazy val
的每次访问进行双重检查锁定会带来一些开销

正如@SargeBorsch所指出的,您可以定义方法,这是最快的选项:

def even(i: Int): Boolean = i % 2 == 0

但如果您需要一个函数(而不是方法)用于函数合成或更高阶函数(如
filter(even)
),编译器将在您每次将其用作函数时从您的方法生成一个函数,因此,性能可能比使用
val

方法
def时稍差,甚至每次调用时都会求值并创建新函数(新的
Function1

使用
def
可以在每次调用时获得新函数:

val test: () => Int = {
  val r = util.Random.nextInt
  () => r
}

test()
// Int = -1049057402
test()
// Int = -1049057402 - same result

def test: () => Int = {
  val r = util.Random.nextInt
  () => r
}

test()
// Int = -240885810
test()
// Int = -1002157461 - new result
val
在定义时求值,
def
-调用时:

scala> val even: Int => Boolean = ???
scala.NotImplementedError: an implementation is missing

scala> def even: Int => Boolean = ???
even: Int => Boolean

scala> even
scala.NotImplementedError: an implementation is missing
请注意,还有第三个选项:
lazy val

它在第一次调用时求值:

scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>

scala> even
scala.NotImplementedError: an implementation is missing
性能

val
在定义时进行计算

def
在每次调用时进行评估,因此对于多个调用,性能可能比
val
差。您只需拨打一个电话即可获得相同的性能。如果没有调用,您将不会从
def
中获得任何开销,因此您可以定义它,即使您不会在某些分支中使用它

使用
lazy val
您将得到一个懒惰的计算:即使您不在某些分支中使用它,您也可以定义它,并且它会计算一次或从未计算过,但是对
lazy val
的每次访问进行双重检查锁定会带来一些开销

正如@SargeBorsch所指出的,您可以定义方法,这是最快的选项:

def even(i: Int): Boolean = i % 2 == 0
但是,如果您需要一个函数(而不是方法)用于函数合成或更高阶函数(如
过滤器(偶数)
),编译器将在您每次将其用作函数时从您的方法生成一个函数,因此性能可能比
val

稍差。请参见以下内容:

  var x = 2 // using var as I need to change it to 3 later
  val sq = x*x // evaluates right now
  x = 3 // no effect! sq is already evaluated
  println(sq)
令人惊讶的是,这将打印4而不是9!val(偶数var)立即计算并分配。
现在将val更改为def。。它将打印9!Def是一个函数调用。。它将在每次调用时进行评估。

请参见以下内容:

  var x = 2 // using var as I need to change it to 3 later
  val sq = x*x // evaluates right now
  x = 3 // no effect! sq is already evaluated
  println(sq)
令人惊讶的是,这将打印4而不是9!val(偶数var)立即计算并分配。

现在将val更改为def。。它将打印9!Def是一个函数调用。。它将在每次调用时进行求值。

此外,Val是按值求值。这意味着在定义过程中计算右侧表达式。其中Def是按名称计算的。在使用之前,它不会求值。

此外,Val是按值求值。这意味着在定义过程中计算右侧表达式。其中Def是按名称计算的。在使用之前,它不会进行计算。

val,即“sq”是由Scala定义的,是固定的。它是在声明时计算的,以后不能更改。在其他示例中,even2也是val,但它是用函数签名声明的,即“(Int=>Boolean)”,因此它不是Int类型。它是一个函数,其值由以下表达式设置

   {
         println("val");
         (x => x % 2 == 0)
   }
根据Scala val属性,您不能将另一个函数分配给even2,规则与sq相同

关于为什么调用eval2 val函数不反复打印“val”

原始代码:

val even2: (Int => Boolean) = {
             println("val");
             (x => x % 2 == 0)
       }
我们知道,在Scala中,上述类型表达式的最后一条语句(在{..}内)实际上是返回到左侧。因此,您最终将even2设置为“x=>x%2==0”函数,该函数与您为even2 val类型声明的类型相匹配,即(Int=>Boolean),因此编译器很高兴。现在even2只指向“(x=>x%2==0)”函数(而不是之前的任何其他语句,如println(“val”)等。使用不同参数调用event2实际上将调用“(x=>x%2==0)”代码,因为只有该代码与event2一起保存

scala> even2(2)
res7: Boolean = true

scala> even2(3)
res8: Boolean = false
为了进一步澄清这一点,下面是c语言的不同版本
scala> def even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean

scala> val even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean = $$Lambda$1157/1017502292@57a0aeb8