【问题标题】:How to get value out of anonymous function in scala?如何从scala中的匿名函数中获取价值?
【发布时间】:2016-01-03 03:06:03
【问题描述】:

我正在尝试学习 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,不知道这是否可能?

【问题讨论】:

    标签: scala functional-programming


    【解决方案1】:

    这是你对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
    

    在这种情况下,我们已经声明匿名函数接受 1 个 Int 类型的参数,因此当我们在方法调用中传递 4 时,它正确匹配方法签名。

    【讨论】:

      【解决方案2】:

      您并没有按照您的想法声明匿名函数。这一行:

      val func = { () => acc += 3 }
      

      这实际上声明了 2 个匿名函数。方括号是第一个匿名函数(不带参数),() =&gt; acc += 3 是第二个函数。 Scala 允许您仅通过使用方括号来声明 0 元匿名函数。如果你放弃这些,你就会得到你想要的:

      val func = () => acc += 3
      

      附带说明一下,您可以在类型签名中看到这一点。您当前对func 的签名是:

      () => Int = <function0>
      

      这是一个接受 0 个参数并返回一个整数的函数。那不是你想要的。当你把它改成我给你的,你会得到这个:

      Int => Int = <function1>
      

      现在func 接受一个参数和整数,并返回另一个整数,这就是您想要的。

      【讨论】:

      • 感谢您的解释!但是,当我尝试从功能中获取价值时,我仍然看到错误。 class c ( acc:Int) { val minc = ( acc + 1 ) val func = () => acc + 3 } val c1 = new C(5) c1.minc print 6 但是,c1.func 打印 res23: () => Int = 我期待这个对象的输出 8。我应该使用其他方法从 func 获取价值吗?
      猜你喜欢
      • 1970-01-01
      • 2018-03-06
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2019-07-03
      • 1970-01-01
      相关资源
      最近更新 更多