while
表达式),表达式具有
Void
类型,这意味着它们不返回结果值
块表达式由一系列声明或表达式组成,它们括在花括号中并用分号进行分隔。块表达式的值是最后一个表达式 的值。如果块表达式中不包含表达式,则其类型为 Void
。请注意,var
和 def
是表达式。
下面的块表达式对几个数字进行相加并将结果存储在一个名为 total
的变量中:
var nums = [5, 7, 3, 9]; |
运行此脚本将生成以下输出:
Total is 24. |
第一行 (var nums = [5, 7, 3, 9];
) 声明一个整数序列。
第二行声明一个名为 total
的变量,该变量将用来存放这些整数的和。
随后的块表达式由左花括号和右花括号之间的所有内容构成:
{ |
在该块内部,第一行代码声明一个名为 sum
的变量,该变量将用来存放此序列中各个数字之和。第二行(一个 for
表达式)遍历该序列,将每个数字与 sum
相加。最后一行设置该块表达式的返回值(在本例中为 24)。
使用 if
表达式后,仅当特定条件为真时才执行某些代码块,从而对程序流 进行定向。
例如,以下脚本基于年龄来设置票价。12 岁到 65 岁的人支付正常价 10 美元。老人和儿童支付 5 美元;5 岁以下的儿童免费。
def age = 8; |
如果将 age
设置为 8,该脚本将生成以下输出:
Age: 8 Ticket Price: 5 dollars. |
该示例的程序流如下所示:
if (age < 5 ) { |
如果 age
小于 5,则票价将设置为 0。
程序随后将跳过其余条件测试并输出结果。
如果 age
不小于 5,程序将继续执行下一个条件测试(由后跟另一个 if
表达式的 else
关键字来指示):
if (age < 5 ) { |
如果人的年龄在 5 到 12 岁之间或者大于 65 岁,该程序会将票价设置为 5 美元。
如果人的年龄在 12 到 65 岁之间,程序会流至最后一个代码块(用 else
关键字进行标记):
if (age < 5 ) { |
只有当前面的所有条件均不满足时,才会执行此块。它会针对 12 到 65 岁之间的人将票价设置为 10 美元。
注:可以将上面的代码缩减成一个非常简洁的条件表达式:
ticketPrice = if (age < 5) 0 else if (age < 12 or age > 65) 5 else 10;
这是一个需要掌握的有用方法,在本教程的后 面部分中还会使用它。
“序列”一课讲授了一种用来声明形成等差数列的数字序列的简化表示法。
var num = [0..5]; |
从技术上讲,[0..5]
是一个范围表达式。默认情况下,相邻值之间的间 隔为 1,但是您可以使用 step
关键字来指定一个不同的间隔。例如,定义一个由 1 到 10 之间的奇数构成的序列:
var nums = [1..10 step 2]; |
此脚本的输出如下所示:
[ 1, 3, 5, 7, 9 ] |
要创建降序范围,请确保第二个值小于第一个值,并指定一个负的 step 值:
var nums = [10..1 step -1]; |
输出为:
[ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ] |
如果您在创建降序范围时没有提供负的 step 值,则会生成一个空序列。
以下代码:
var nums = [10..1 step 1]; |
将生成下面的编译时警告:
range.fx:1: warning: empty sequence range literal, probably not what you meant. |
如果您完全忽略 step 值,也会生成一个空序列。
另一个与序列有关的表达式是 for 表达式。for
表达式为遍历序列中的各个项提供了一种方便的机制。
以下代码提供了一个示例:
var days = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]; |
此脚本的输出如下所示:
Mon |
让我们将该示例分成几个部分。for
表达式以 "for" 关键字开头:
for (day in days) { |
days
变量是要由 for
表达式处理的输入序列的 名称:
for (day in days) { |
当 for
表达式遍历该序列时,day
变量用来存放当前项:
for (day in days) { |
请注意,不需要在脚本中的其他位置声明 day
变量即可将其用在 for
表达式中。此外,在完成整个循环之后,将无法访问 day
。程序员通常会赋予临时变量(如该变量)非常短的名称(或由一个 字母构成的名称)。
在上例中,未显示 for
返回值;但 for
也是一个返回序列的表达式。以下代码显示了两个使用 for
表达式从另一个序列创建序列的示例:
// Resulting sequence squares the values from the original sequence. |
请注意,toUpperCase
函数由 String
对象提供。您可以通过查阅 API 文档来查看完整的可用函数列表。
另一个循环结构是 while 表达式。与作用于序列中项的 for
表达式不同,while
表达式会一直循环,直到给定的表达式为 false
为止。尽管 while
在语法上是表达式,但是它的类型为 Void
,不返回值。
下面提供了一个示例:
var count = 0; |
此脚本的输出如下所示:
count == 0 |
第一行声明一个名为 count
的变量并将其初始化为 0:
var count = 0; |
第二行以 while
表达式开头。此表达式创建了一个循环(在左花括号和右花括号之间),该循环会一直进行,直到 count < 10
的值为 false
为止:
var count = 0; |
While 表达式的主体会输出 count
的当前值,然后将 count
的值加 1:
var count = 0; |
当 count
等于 10 时,循环退出。要创建一个无限循环,请将 true
关键字放在左小括号和右小括号之间,如 while(true){}
中所示。
break
和 continue
表达式与循环表达式有关。这两个表达式会影响循环迭代:break
完全放弃循环,而 continue
仅放弃当前迭代。
尽管 break
和 continue
在语法上是表达式,但它们的类型为 Void
,不返回值。
示例:
for (i in [0..10]) { |
输出:
1 |
如果没有 if
表达式,该程序将只是输出 0 到 10 之间的数字。
如果只有第一个 if
表达式,程序将在 i
的值大于 5 时中 断循环:
if (i > 5) { |
因此,程序将仅输出 1 到 5 之间的数字。
通过添加第二个 if
表达式,程序将仅放弃循环的当前迭代而继续执行下一 个迭代:
if (i mod 2 == 0) { |
在这种情况下,只有当 i
为偶数(即 i
能被 2 整除,没有余数)时才执行 continue
。出现这种情况时,将永远不会调用 println()
, 因此输出中将不包含该数字。
在实际的应用程序中,正常的脚本执行流有时会被某个事件中止。例如,如果脚本从某个文件中读取输入,但是找不到该文件,该 脚本将无法继续。我们将这种情况称为“异常”。
注意:异常是对象。它们的类型通常以它们所表示的情况命名(例如,FileNotFoundException
表示找不到文件的情况)。但是,定义一组特定于即将给出的示例的异常不在本节的讨论范围之内。因此,我们将使用一个通用的Exception
对象(从 Java 编程语言借用而来)来说明throw
、try
、catch
和finally
表达式。
以下脚本定义(和调用)一个会抛出异常的函数:
import java.lang.Exception; |
按原样运行此脚本(将 somethingWeird
设置为 false
) 将输出以下消息:
We made it through the function. |
但是,如果将该变量更改为 true
,则会抛出异常。在运行时,该脚本将崩溃并显示以下消息:
Exception in thread "main" java.lang.Exception: Something weird just happened! |
为了防止崩溃,我们将需要使用 try/catch 表达式来包装 foo()
调用。顾名思义,这些表达式尝试执行某些代码,但会在出现问题时捕捉异常:
try { |
现在,程序不会崩溃,而只是输出:
Something weird just happened! (but we caught it) |
还有一个 finally 块(它在技术上不是表达式),无论是否抛出了异常,该块始终在 try 表达式退出之后的某个时间执行。finally
块用来执行无论 try
主体是成功还是抛出异常都需要执行的清除操作。
try { |
程序输出现在为:
Something weird just happened! (but we caught it)
We are now in the finally expression...
The script is now executing as expected...