这是一个定义和尝试一些函数的Scala会话:
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
效果很好!
现在,我在折叠时看到了 _
语法( _ + _
等) . 据我了解 _
基本上意味着"an argument" . 所以 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函数之间的区别是什么?
3 回答
def'ed函数和val'ed函数之间没有区别:
看到?所有这些都是函数,它们由
X => Y
类型表示 .你看到
X => Y
类型了吗?如果你这样做,去看眼科医生,因为没有 . 这里的类型是(X)Y
,通常用于表示方法 .实际上,
test1
,_ 283833,test3
和test4
都是返回函数的方法 .test5
是一个返回java.lang.String
的方法 . 此外,test1
到test4
不接受参数(无论如何只能test1
),而test5
.所以,差异非常简单 . 在第一种情况下,您尝试将方法分配给val,但没有填写方法所采用的参数 . 所以它失败了,直到你添加了一个尾随下划线,这意味着将我的方法变成一个函数 .
在第二个示例中,您有一个函数,因此您不需要执行任何其他操作 .
方法不是函数,反之亦然 . 函数是
FunctionN
类之一的对象 . 方法是与对象关联的某些代码的句柄 .在Stack Overflow上查看有关方法与函数的各种问题 .
def
在周围的对象/类/特征中声明一个方法,类似于在Java中定义方法的方式 . 您只能在其他对象/类/特征中使用def
. 在REPL中,您无法看到周围的对象,因为它是"hidden",但它确实存在 .您不能将
def
分配给某个值,因为def
不是值 - 它是对象中的方法 .(x: T) => x * x
声明并实例化 function object ,它在运行时存在 . 函数对象是扩展FunctionN
特征的匿名类的实例 .FunctionN
特征带有apply
方法 . 名称apply
是特殊的,因为它可以省略 . 表达式f(x)
被贬低为f.apply(x)
.底线是 - 由于函数对象是存在于堆上的运行时值,因此可以将它们分配给值,变量和参数,或者将它们作为返回值从方法返回 .
为了解决为值分配方法的问题(这可能很有用),Scala允许您使用占位符字符从方法创建函数对象 . 上面示例中的表达式
test1 _
实际上围绕方法test1
创建了一个包装函数 - 它相当于x => test1(x)
.下划线在不同的上下文中意味着不同的东西 . 但它总是可以被认为是会在这里发生的事情,但不需要被命名 .
当应用代替参数时,效果是将方法提升为函数 .
注意,该方法已成为type(String)=> String的函数 .
Scala中方法和函数之间的区别在于方法类似于传统的Java方法 . 你不能将它们作为值传递 . 但是,函数本身就是值,可以用作输入参数和返回值 .
提升可以更进一步:
提升此功能会产生另一个功能 . 这个时间类型()=>(String)=>(String)
据我所知,这种语法相当于用显式下划线替换所有参数 . 例如: