我正在尝试学习scala并理解函数和方法之间的区别。
这是我写的非常简单的代码 -
scala> class C ( acc:Int) {
| val minc = ( acc + 1 )
| val func = { () => acc += 3 }
| }
scala> val c1 = new C(3)
c1: C = C@55e610e3
scala> c1.minc
res2: Int = 4
scala> c1.func
res3: () => Int = <function0>
我知道在实例化对象c1上调用函数func的结果存储为另一个表达式res3。
但是我想从C类内部的匿名函数()= acc +3中获取价值。
如果我尝试将参数传递给res3表达式,则scala会抛出错误
scala> res3(4)
<console>:11: error: too many arguments for method apply: ()Int in trait Function0
res3(4)
^
如何从中获取价值?
PS - 我刚开始使用scala并且不知道这是否完全可能?
答案 0 :(得分:5)
这是您对func
:
val func = { () => acc += 3 }
让我们看一下REPL中func
的类型。
scala> val c1 = new C(3)
val c1 = new C(3)
c1: C = C@58db88e9
scala> c1.func
c1.func
res29: () => Unit = <function0>
简单来说,这意味着“func指的是一个不接受任何参数并且不返回值的函数。” Unit
表示该方法不返回任何内容。如果你来自Java,那么它类似于void
作为返回类型。 function0
表示它接受0个参数。
接下来,让我们看一下您示例中的失败呼叫。
scala> c1.func(4)
c1.func(4)
<console>:10: error: too many arguments for method apply: ()Unit in trait Function0
c1.func(4)
^
现在我们知道了func
的方法签名,这个错误信息应该更有意义。我们知道func
指的是一个不接受任何参数的函数,但是在这个调用中,你试图用一个整数参数来调用它。由于方法调用的参数太多,因此Scala会将此错误地报告为错误。
通过传递4
作为参数,我并不完全确定你要做什么。我最好的猜测是你试图通过将3
添加到acc
然后将其返回给调用者来应用函数来计算结果。如果我是对的,那么我们可以重新定义C
:
class C(var acc:Int) {
val minc = ( acc + 1 )
val func = () => {
acc += 3
acc
}
scala> val c1 = new C(3)
val c1 = new C(3)
c1: C = C@58db88e9
scala> c1.func()
c1.func()
res44: Int = 6
当我们调用c1.func()
时,没有传递任何参数,因此它正确匹配定义的方法签名。
另一种可能性是您尝试参数化增量并在调用中将4
传递给它。如果是这样,那么你可以这样做:
class C(var acc:Int) {
val minc = ( acc + 1 )
val func = (delta: Int) => {
acc += delta
acc
}
}
scala> c1.func(4)
c1.func(4)
res45: Int = 7
在这种情况下,我们声明匿名函数接受类型Int
的1个参数,因此当我们在方法调用中传递4
时,它正确匹配方法签名。
答案 1 :(得分:0)
您并未按照您的想法声明匿名功能。这一行:
val func = { () => acc += 3 }
实际上声明了 2 匿名函数。括号是第一个匿名函数(不带参数),() => acc += 3
是第二个函数。 Scala允许您通过使用括号来声明0-arity匿名函数。如果放弃它们,你就会得到你想要的东西:
val func = () => acc += 3
作为旁注,您可以在类型签名中看到这一点。您func
的当前签名是:
() => Int = <function0>
这是一个带0个参数并返回整数的函数。这不是你想要的。当你把它改成我给你的东西时,你会得到这个:
Int => Int = <function1>
现在func
只接受一个参数和Integer,并返回另一个Integer,这就是你想要的。