【问题标题】:What is the difference between () => Int and Unit => Int? What on earth is the type of "()" in Scala?() => Int 和 Unit => Int 有什么区别? Scala 中的“()”到底是什么类型?
【发布时间】:2012-06-03 06:11:49
【问题描述】:

我想我还没有完全理解函数定义过程中type()代表什么。所以我无法提出每种情况的具体例子: () => Int;单位=> 整数。

谁能给我一个简单的函数文字示例,分别是 () => Int 和 Unit=>Int 类型?在那之后,我想我可以了解 () 到底是什么。

谢谢

*编辑:* destin 说它们是一样的。但以下测试似乎表明并非如此: () 不能用于期望 Unit.

scala> def inCase[A] ( b :Boolean, ifTrue : Unit => A, ifFalse : Unit => A ) : A  = 
 |     b match {
 |         case True => ifTrue()
 |         case _ => ifFalse()
 |     }

 inCase: [A](b: Boolean, ifTrue: Unit => A, ifFalse: Unit => A)A


scala> inCase( True,  () => 1,  () => -1 )
 <console>:11: error: type mismatch;
 found   : () => Int
  required: Unit => ?
          inCase( True,  () => 1,  () => -1 )

【问题讨论】:

  • 您在寻找 int 或 Unit 的返回类型吗?听起来很像,但我想确定。
  • 我正在寻找 Int 的返回类型。

标签: scala


【解决方案1】:

函数类型中的() 根本不是类型,也不是值。 () =&gt; 是一个简单的语法,表示一个接受零参数的函数。请参阅the Scala specification. 的第 3.2.9 节中的 BNF 表示法

当您看到(Type1, Type2, Type3) =&gt; Type4 时,() 包围了该函数采用的所有参数类型。 (Type1, Type2, Type3) 在这里不是元组类型——括号只是语法。所以当你看到() =&gt; Type4 时,你有一个参数列表,它接受零个参数。单参数函数很特殊,因为您可以省略括号。

没有参数的函数,没有() 指定,只是=&gt; Type4 是按名称参数(看起来像值,但实现为函数,当您尝试评估它们的值时会被隐式调用。)它们'在规范的第 4.6.1 节中重新定义。

括号在其他情况下可能意味着一堆其他东西。

  • 函数类型声明中除=&gt; 之前的任何位置的括号表示元组类型,并且不能为空。 (第 3.2.5 节)
  • 空括号() 是返回类型为Unit 的函数的返回值。 (第 12.2.3 节)这实际上在某些情况下会变成一个实际值,例如 println(println("foo")) 将打印

    foo                 <--- the argument to the inner println
    ()                  <--- the argument to the outer println
    
  • 当您进行函数调用时,括号也是函数参数的语法,您可能已经知道这一点。这些可以是空的。它们在规范的第 6.6 节中定义。

  • 当您使用def 定义方法时,括号也是函数参数的语法。这些在规范的第 4.6 节中进行了描述。
  • 括号也是创建元组值的语法(第 6.9 节)。如果它们不为空,您会得到一个TupleN,其中N 是括号内的值的数量。如果它们为空,则此表达式的类型为Unit。 (第 6.9、12.2.3 节)

【讨论】:

  • {val f : Unit =&gt; Int = ((x:Unit)=&gt;42) ; f(()) } 计算为 42。{val g : () =&gt; Int = (()=&gt;42) ; g() } 计算为 42。但奇怪的是 {val h : Unit =&gt; Int = ((x:Unit)=&gt;42) ; h() } 也编译并计算为 42。我会认为,因为我传递了 h 零参数而不是 1 ,这将是一个编译时错误。
  • 而且,有趣的是,{val k : Int =&gt; Int = ((a:Int) =&gt; 42) ; k()} 给出了“方法应用的参数不足”而不是类型错误。所以似乎有一种特殊情况,将 0 参数传递给域为 Unit 的 1 参数函数。
【解决方案2】:

我更改了您的示例,使其具有两种表示法(并使用更流行的布尔值):

def inCase[A] (b:Boolean, ifTrue: ()=> A, ifFalse: Unit => A): A = b match {
  case true => ifTrue ()
  case _    => ifFalse ()
}

inCase (true, () => 1,  (Unit) => -1)

然后我必须在调用站点上使用相同的符号。

【讨论】:

    【解决方案3】:

    ()Unit 类型的唯一实例。
    所以() =&gt; Int 作为部分函数的签名意味着:接受 the Unit 对象,做某事并给出一个 Int。
    Unit =&gt; Int 表示:接受任何 Unit 对象,做某事并给出一个 Int。

    编辑

    "Scala 的 Unit 类型大致对应于 Java 中的 void;当函数没有返回有趣的结果时使用它。事实上,因为 Scala 是面向表达式的语言,所以每个函数都会返回一些结果。如果没有显式返回给定表达式时,假定读作“unit”的值 ()。这个值是 单位类型。单元返回函数也称为过程。这里有更多 第一次实现中交换函数的“面向表达式”公式化 的快速排序,这使得这一点明确:

    def swap(i: Int, j: Int): Unit = {
      val t = xs(i); xs(i) = xs(j); xs(j) = t
      ()
    }
    

    这个函数的结果值只是它的最后一个表达式——返回关键字是 不必要。请注意,返回显式值的函数总是需要一个“=” 在他们的身体或定义表达之前。”

    来源:Scala 编程 - Martin Odersky(第 14 页)

    【讨论】:

    • 没有。 ()=&gt;Int 表示不带参数并返回 Int 的函数。
    • 您的报价是正确的,但偏离主题。在函数的类型签名中,() 表示没有映射到 Function0 的参数。如果你定义val f:()=&gt;Int = () =&gt; 12,然后你用一个单位参数调用它,它不会起作用:试试f()f(())
    猜你喜欢
    • 1970-01-01
    • 2010-11-19
    • 2017-02-23
    • 2020-05-05
    • 2015-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多