首页 > 代码库 > 探索Scala(6)-- Tuples
探索Scala(6)-- Tuples
本文讨论一下Tuple的用法和实现方式
Unit
Scala语言没有void关键字,取而代之的,是Unit概念(和对象)。Scala比Java更加OO,这也算是其中一个方面。从Scala语言的角度来讲,Unit和Tuple并没有太大的联系,但是基于两点原因,我打算先讨论一下Unit:
- 概念相似:Tuple表示包含n(n > 0)个元素的对象,Unit表示没有对象,或不需要对象。所以Unit可以认为是Tuple的一种特殊情况,即包含0个元素的Tuple。
- 语法相似:可以用圆括号来创建Tuple实例,比如,val t = (1, "2", false)创建了一个三元组。一对儿空圆括号则创建Unit实例,比如val u = ()
大部分时候,Unit都只是个概念,它等价于Java的void关键字。比如下面这段Scala代码:
def unitIsVoid(x: Int, y: Int): Unit = { val z = x + y }反编译之后,实际上得到下面的Java代码:
public void unitIsVoid(int x, int y) { int z = x + y; }但如果你非要使用Unit实例的话,也是行得通的:
def unitIsNotVoid(nothing: Unit) = { val unit = () if (unit == nothing) { println("unit == nothing") } }上面的Scala代码可以通过编译,但是编译器会给出一条警告:
warning: comparing values of types Unit and Unit using `==‘ will always yield true
下面是反编译之后的Java代码:
public void unitIsNotVoid(scala.runtime.BoxedUnit nothing) { scala.runtime.BoxedUnit unit = BoxedUnit.UNIT; if (unit.equals(nothing)) { ... } }可以看到,Unit概念的化身,就是BoxedUnit.UNIT单例对象。
Tuple1
Tuple1就是只包含一个元素的Tuple,也就是一元组。需要注意的是,Tuple1是无法用圆括号字面量来实例化的,必须用Tuple1("x")这样的方式来实例化,如下面代码所示:
def tuple1() = { val x = ("a") val y = Tuple1("b") }下面是反编译之后的Java代码:
String x = "a"; Tuple1 y = new Tuple1("b");
TupleN
那么可以任意表达包含n个元素的Tuple吗?答案是否定的。Scala只定义了Tuple1~Tuple22共22个Tuple(在scala包里),圆括号字面量也只支持Tuple1~Tuple22,再多就不支持了。例如下面这段代码是无法通过编译的:
def tuple23() = { val t23 = (1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,"21","22","23") }Scala编译器报了下面这个错误:
error: object <none> is not a member of package scala
函数返回多个值
Tuple有很多用途。当方法想返回多个值,但又不太值得单独定义一个类的时候,就比较适合用Tuple。下面是一个例子:
def nameAndAge() = { ("zxh", 32) }
把Tuple赋值给多个变量
也可以把Tuple赋值给n个变量,这相当于把Tuple给拆了,代码如下所示:
def assignToVars() = { val (name, age) = nameAndAge() println(name + " is " + age + " old") }
实例化Map
下面这段代码实例化了一个Map:
val m = Map("a" -> 1, "b" -> 2)看起来Scala好像支持Map字面量,但实际上并不是。下面是反编译之后的Java代码:
Tuple2[] ts = new Tuple2[2]; ts[0] = scala.Predef$ArrowAssoc$.MODULE$.$minus$greater$extension("a", 1); // -> ts[0] = scala.Predef$ArrowAssoc$.MODULE$.$minus$greater$extension("b", 2); scala.collection.immutable.Map$.apply(ts);->实际上只是个隐式转换方法,下面是它的定义:
object Predef { implicit final class ArrowAssoc[A](private val self: A) extends AnyVal { @inline def -> [B](y: B): Tuple2[A, B] = Tuple2(self, y) } }也就是说,->把key和value转换成了Tuple2,然后Tuple2数组传递给了Map单例对象的apply方法。
探索Scala(6)-- Tuples
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。