两种在Scala中定义函数的方法.有什么不同?

aio*_*obe 44 scala function currying

这是一个Scala会话,它定义并尝试了一些函数:

scala> def test1(str: String) = str + str;    
test1: (str: String)java.lang.String

scala> test1("ab")
res0: java.lang.String = abab
Run Code Online (Sandbox Code Playgroud)

很好地工作.

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
                   ^
Run Code Online (Sandbox Code Playgroud)

哎呀.

scala> val test2 = test1 _
test2: (String) => java.lang.String = <function1>

scala> test2("ab")
res1: java.lang.String = abab
Run Code Online (Sandbox Code Playgroud)

效果很好!

现在,我已经看到_折叠时的语法(_ + _等).据我所知,它_基本上意味着"争论".所以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>
Run Code Online (Sandbox Code Playgroud)

这里没有_!defed函数和valed函数之间有什么区别?

axe*_*l22 58

def声明周围物体/班/特质中的一个方法,类似于你定义的Java方法的方式.您只能def在其他对象/类/特征中使用s.在REPL中,您无法看到周围的对象,因为它是"隐藏的",但确实存在.

您不能将def值分配给值,因为def它不是值 - 它是对象中的方法.

(x: T) => x * x声明并实例化一个函数对象,它存在在运行时.函数对象是扩展FunctionN特征的匿名类的实例.FunctionN特征来自一种apply方法.名称apply很特殊,因为它可以省略.表达f(x)被贬低了f.apply(x).

底线是 - 由于函数对象是存在于堆上的运行时值,因此可以将它们分配给值,变量和参数,或者将它们作为返回值从方法返回.

为了解决为值分配方法的问题(可能很有用),Scala允许您使用占位符字符从方法创建函数对象.test1 _上面示例中的表达式实际上围绕方法创建了一个包装函数test1- 它等同于x => test1(x).

  • 简单而干净的答案,+ 1 (3认同)

Dan*_*ral 53

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>
Run Code Online (Sandbox Code Playgroud)

看到?所有这些都是功能,由X => Y它们具有的类型表示.

scala> def test5(str: String) = str + str
test5: (str: String)java.lang.String
Run Code Online (Sandbox Code Playgroud)

你看到一个X => Y类型?如果你这样做,去看眼科医生,因为没有.这里的类型(X)Y通常用于表示方法.

其实test1,test2,test3test4是所有方法中,它会返回功能.test5是一个返回a的方法java.lang.String.此外,test1通过test4不采取参数(只能test1,无论如何),同时test5.

所以,差异非常简单.在第一种情况下,您尝试将方法分配给val,但没有填写方法所采用的参数.所以它失败了,直到你添加了一个尾随下划线,这意味着将我的方法变成一个函数.

在第二个示例中,您有一个函数,因此您不需要执行任何其他操作.

方法不是函数,反之亦然.函数是其中一个FunctionN类的对象.方法是与对象关联的某些代码的句柄.

在Stack Overflow上查看有关方法与函数的各种问题.


Syn*_*sso 11

下划线在不同的上下文中意味着不同的东西.但它总是可以被认为是会在这里发生的事情,但不需要被命名.

当应用代替参数时,效果是将方法提升为函数.

scala> def test1(str: String) = str + str; 
test1: (str: String)java.lang.String

scala> val f1 = test1 _
f1: (String) => java.lang.String = <function1>
Run Code Online (Sandbox Code Playgroud)

注意,该方法已成为type(String)=> String的函数.

Scala中方法和函数之间的区别在于方法类似于传统的Java方法.你不能将它们作为值传递.但是,函数本身就是值,可以用作输入参数和返回值.

提升可以更进一步:

scala> val f2 = f1 _
f2: () => (String) => java.lang.String = <function0>
Run Code Online (Sandbox Code Playgroud)

提升此功能会产生另一个功能.这个时间类型()=>(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>
Run Code Online (Sandbox Code Playgroud)