在Scala中定义函数的两种方法。 有什么不同?
这是一个小小的Scala会话,定义并尝试一些function:
scala> def test1(str: String) = str + str; test1: (str: String)java.lang.String scala> test1("ab") res0: java.lang.String = abab
很好地工作。
scala> val test2 = test1 <console>:6: error: missing arguments for method test1 in object $iw; follow this method with `_' if you want to treat it as a partially applied function val test2 = test1 ^
哎呀。
scala> val test2 = test1 _ test2: (String) => java.lang.String = <function1> scala> test2("ab") res1: java.lang.String = abab
效果很好!
现在,我在折叠( _ + _
等)时看到了_
语法。 据我所知,这基本上意味着“一个论点”。 所以test1 _
基本上是指一个带有参数的函数,它是给test1
“,但是为什么不和 test1
完全一样呢?为什么添加一个_
有什么区别呢?
所以我一直在探索…
scala> val test3 = (str: String) => str + str test3: (String) => java.lang.String = <function1> scala> test3("ab") res2: java.lang.String = abab scala> val test4 = test3 test4: (String) => java.lang.String = <function1>
这里它没有工作! def
ed函数和val
ed函数有什么区别?
def'ed函数和val'ed函数没有区别:
scala> def test1 = (str: String) => str + str test1: (String) => java.lang.String scala> val test2 = test1 test2: (String) => java.lang.String = <function1> scala> val test3 = (str: String) => str + str test3: (String) => java.lang.String = <function1> scala> val test4 = test2 test4: (String) => java.lang.String = <function1>
看到? 所有这些都是函数,它们是由X => Y
types表示的。
scala> def test5(str: String) = str + str test5: (str: String)java.lang.String
你看到X => Y
型吗? 如果你这样做,去看眼科医生,因为没有。 这里的types是(X)Y
,通常用来表示方法 。
实际上, test1
, test2
, test3
和test4
都是返回函数的方法。 test5
是一个返回java.lang.String
的方法。 另外, test1
到test4
不带参数(只有test1
可以),而test5
可以。
所以,区别很简单。 在第一种情况下,您尝试将方法分配给val,但未填写方法所用的参数。 所以它失败了,直到你添加了一个尾随的下划线,这意味着把我的方法变成一个函数 。
在第二个例子中,你有一个函数,所以你不需要做任何事情。
方法不是一个函数,反之亦然。 函数是FunctionN
类之一的一个对象。 方法是与某个对象关联的某段代码的句柄。
在Stack Overflow上看到有关方法和函数的各种问题。
def
在周围的对象/类/特征中声明一个方法,类似于你在Java中定义方法的方式。 你只能在其他对象/类/特性中使用def
。 在REPL中,你看不到周围的物体,因为它是“隐藏的”,但它确实存在。
你不能把def
赋值给一个值,因为def
不是一个值 – 它是对象中的一个方法。
(x: T) => x * x
声明并实例化一个在运行时存在的函数对象 。 函数对象是扩展FunctionN
特征的匿名类的实例。 FunctionN
特征带有apply
方法。 名称apply
是特殊的,因为它可以省略。 expression式f(x)
被parsing成f.apply(x)
。
底线是 – 因为函数对象是堆中存在的运行时值,所以可以将它们分配给值,variables和参数,或者将它们作为返回值从方法返回。
为了解决赋值的问题(可能有用),Scala允许你使用占位符来创build一个方法的函数对象。 在上面的例子中,expression式test1 _
实际上创build了围绕方法test1
的包装函数 – 它相当于x => test1(x)
。
下划线在不同的情况下意味着不同的事物。 但总是可以把它想象成这里将会发生的事情,但不需要命名 。
当应用代替参数时,效果是将该方法提升到一个函数。
scala> def test1(str: String) = str + str; test1: (str: String)java.lang.String scala> val f1 = test1 _ f1: (String) => java.lang.String = <function1>
请注意,该方法已成为types(String)=> String的函数。
Scala中的一个方法和一个函数的区别在于方法类似于传统的Java方法。 你不能将它们作为值传递。 然而,函数本身是值,可以用作input参数和返回值。
提升可以进一步:
scala> val f2 = f1 _ f2: () => (String) => java.lang.String = <function0>
解除这个function将导致另一个function。 这个时候的type()=>(String)=>(String)
从我所知道的,这个语法等价于用明确的下划线代替所有的参数。 例如:
scala> def add(i: Int, j: Int) = i + j add: (i: Int,j: Int)Int scala> val addF = add(_, _) addF: (Int, Int) => Int = <function2> scala> val addF2 = add _ addF2: (Int, Int) => Int = <function2>