• 如何在Scala中使用条件表达式 .


    条件表达式

    Scala的if/else语法结构和Java或C++一样。不过,在Scala中if/else表达式有值,这个值就是跟在if或else之后的表达式的值。例如:

    if (x > 0) 1 else -1

    上述表达式的值是1或−1,具体是哪一个取决于x的值。你可以将if/else表达式的值赋值给变量:

    val s = if (x > 0) 1 else -1

    这与如下语句的效果一样:

    if (x > 0) s = 1 else s = -1

    不过,第一种写法更好,因为它可以用来初始化一个val。而在第二种写法当中,s必须是var。

    (之前已经提过,Scala中的分号绝大多数情况下不是必需的。)

    Java和C++有一个?:操作符用于同样目的。如下表达式

    x > 0 ? 1 : -1 // Java或C++

    等同于Scala表达式 if (x > 0) 1 else −1。不过,你不能在?:表达式中插入语句。Scala的if/else将在Java和C++中分开的两个语法结构if/else和?:结合在了一起。

    在Scala中,每个表达式都有一个类型。举例来说,表达式 if (x > 0) 1 else −1的类型是Int,因为两个分支的类型都是Int。混合类型表达式,比如:

    if (x > 0) "positive" else -1

    上述表达式的类型是两个分支类型的公共超类型。在本例中,其中一个分支是java.lang.String,而另一个分支是Int。它们的公共超类型叫做Any。(详细内容参见8.11节。)

    如果else部分缺失了,比如:

    if (x > 0) 1

    那么有可能if语句没有输出值。但是在Scala中,每个表达式都应该有某种值。这个问题的解决方案是引入一个Unit类,写做()。不带else的这个if语句等同于

    if (x > 0) 1 else ()

    你可以把()当做是表示“无有用值”的占位符,将Unit当做Java或C++中的void。(从技术上讲,void没有值但是Unit有一个表示“无值”的值。如果你一定要深究的话,这就好比空的钱包和里面有一张写着“没钱”的无面值钞票的钱包之间的区别。)

    说明:Scala没有switch语句,不过它有一个强大得多的模式匹配机制,我们将在第14章中看到。在现阶段,用一系列的if语句就好。

    注意:REPL比起编译器来更加“近视”——它在同一时间只能看到一行代码。

    举例来说,当你键入如下代码时:

    if (x > 0) 1

    else if (x == 0) 0 else -1

    REPL会执行 if (x > 0) 1,然后显示结果。之后它看到接下来的else关键字就会不知所措。

    如果你想在else前换行的话,用花括号:

    if (x > 0) { 1

    } else if (x == 0) 0 else -1

    只有在REPL中才会有这个顾虑。在被编译的程序中,解析器会找到下一行的else。

    提示:如果你想在REPL中粘贴成块的代码,而又不想担心REPL的近视问题,可以使用粘贴模式。键入:

    :paste

    把代码块粘贴进去,然后按下Ctrl+D。这样REPL就会把代码块当做一个整体来分析。

    语句终止

    在Java和C++中,每个语句都以分号结束。而在Scala中——与JavaScript和其他脚本语言类似——行尾的位置不需要分号。同样,在}、else以及类似的位置也不必写分号,只要能够从上下文明确地判断出这里是语句的终止即可。

    不过,如果你想在单行中写下多个语句,就需要将它们以分号隔开。例如:

    if (n > 0) { r = r * n; n -= 1 }

    我们需要用分号将 r = r * n 和 n -= 1 隔开。由于有},在第二个语句之后并不需要写分号。

    如果你在写较长的语句,需要分两行来写的话,就要确保第一行以一个不能用做语句结尾的符号结尾。通常来说一个比较好的选择是操作符:

    s = s0 + (v - v0) * t + // +告诉解析器这里不是语句的末尾

    0.5 * (a - a0) * t * t

    在实际编码时,长表达式通常涉及函数或方法调用,如此一来你并不需要过分担心——在左括号(之后,编译器直到看到匹配的)才会去推断某处是否为语句结尾。

    正因如此,Scala程序员们更倾向于使用Kernighan & Ritchie风格的花括号:

    if (n > 0) {

    r = r * n

    n -= 1

    }

    以{结束的行很清楚地表示了后面还有更多内容。

    许多来自Java或C++的程序员一开始并不适应省去分号的做法。如果你倾向于使用分号,用就是了——它们没啥坏处。

    块表达式和赋值

    在Java或C++中,块语句是一个包含于{ }中的语句序列。每当你需要在逻辑分支或循环中放置多个动作时,你都可以使用块语句。

    在Scala中,{ }块包含一系列表达式,其结果也是一个表达式。块中最后一个表达式的值就是块的值。

    这个特性对于那种对某个val的初始化需要分多步完成的情况很有用。例如,

    val distance = { val dx = x - x0; val dy = y - y0; sqrt(dx * dx + dy * dy) }

    { }块的值取其最后一个表达式,在此处以粗体标出。变量dx和dy仅作为计算所需要的中间值,很干净地对程序其他部分而言不可见了。

    在Scala中,赋值动作本身是没有值的——或者,更严格地说,它们的值是Unit类型的。你应该还记得,Unit类型等同于Java和C++中的void,而这个类型只有一个值,写做()。

    一个以赋值语句结束的块,比如

    { r = r * n; n -= 1}

    的值是Unit类型的。这没有问题,只是当我们定义函数时需要意识到这一点。

    由于赋值语句的值是Unit类型的,别把它们串接在一起。

    x = y = 1 // 别这样做

    y = 1的值是(),你几乎不太可能想把一个Unit类型的值赋值给x。(与此相对应,在Java和C++中,赋值语句的值是被赋的那个值。在这些语言中,将赋值语句串接在一起是有意义的。)

    输入和输出

    如果要打印一个值,我们用print或println函数。后者在打印完内容后会追加一个换行符。举例来说,

    print("Answer: ")

    println(42)

    与下面的代码输出的内容相同:

    println("Answer: " + 42)

    另外,还有一个带有C风格格式化字符串的printf函数:

    printf("Hello, %s! You are %d years old.\n", "Fred", 42)

    你可以用readLine函数从控制台读取一行输入。如果要读取数字、Boolean或者是字符,可以用readInt、readDouble、readByte、readShort、readLong、readFloat、readBoolean或者readChar。与其他方法不同,readLine带一个参数作为提示字符串:

    val name = readLine("Your name: ")

    print("Your age: ")

    val age = readInt()

    printf("Hello, %s! Next year, your will be %d.\n", name, age + 1)

     

    本文节选自《快学Scala

    电子工业出版社出版

    (美)霍斯曼(Horstmann,C.S.)著

    高宇翔译

  • 相关阅读:
    LeetCode 21. 合并两个有序链表
    LeetCode 20. 有效的括号
    LeetCode 19. 删除链表的倒数第N个节点
    AI
    http
    IP地址
    wiodows /linux CMD
    git
    AI
    JS常用的获取值和设值的方法
  • 原文地址:https://www.cnblogs.com/broadview/p/2756330.html
Copyright © 2020-2023  润新知