3.3 元组与多重赋值

假定有个函数要返回多个值。比如,返回一个人的名、姓和email地址。如果使用Java的话,一种方式是返回一个PersonInfo类的实例,其中包括与那些数据对应的字段。另一种方式是返回一个包含这些值的String[]ArrayList,然后对结果进行循环,取出这些值。Scala提供了一种更简单的方式做这件事:元组和多重赋值。

元组是一个不变的对象序列,可以用逗号分隔的值进行创建。比如,下面表示一个有3个对象的元组:("Venkat", "Subramaniam", "venkats@agiledeveloper.com")

元组元素可以同时赋给多个varval,如下面这个例子所示:

ScalaForTheJavaEyes/MultipleAssignment.scala

  1. def getPersonInfo(primaryKey : Int) = {
  2. // 假设用primaryKey获取一个人的信息
  3. // 这里的返回值被硬编码了。
  4. ("Venkat", "Subramaniam", "venkats@agiledeveloper.com")
  5. }
  6. val (firstName, lastName, emailAddress) = getPersonInfo(1)
  7. println("First Name is " + firstName)
  8. println("Last Name is " + lastName)
  9. println("Email Address is " + emailAddress)

执行这段代码的输出如下:

  1. First Name is Venkat
  2. Last Name is Subramaniam
  3. Email Address is venkats@agiledeveloper.com

如果尝试将方法结果赋给数量不一致的变量会怎么样呢?Scala会密切地关注你,一旦这种情况发生,它就会报错。如果是编译代码,而不是作为脚本执行,Scala在编译时就会提示错误。比如,下面这个例子,将方法调用的结果赋值给数量少于元组个数的变量。

ScalaForTheJavaEyes/MultipleAssignment2.scala

  1. def getPersonInfo(primaryKey : Int) = {
  2. ("Venkat", "Subramaniam", "venkats@agiledeveloper.com")
  3. }
  4. val (firstName, lastName) = getPersonInfo(1)

Scala会报告这样的错误:

  1. (fragment of MultipleAssignment2.scala):5: error:
  2. constructor cannot be instantiated to expected type;
  3. found : (T1, T2)
  4. required: (java.lang.String, java.lang.String, java.lang.String)
  5. val (firstName, lastName) = getPersonInfo(1)
  6. ^
  7. ...

就算不赋值,也可以访问元组里的单个元素。比如,如果执行了val info = getPer-sonInfo(1),就可以用这样的语法info._1,访问第一个元素,第二个用info._2,以此类推。

元组不仅仅对多重赋值中有用。在并发编程里,使用元组可以把一组数据值作为消息在Actor之间传递(它们不变的属性刚好在这里派得上用场)。如此简洁的语法会让消息发送端的代码极为精炼。在接收端,使用模式匹配会让接收和处理消息变得简单,在9.3节“匹配元组和list”中会详细介绍。