控制流语句
第一个greeting.nim程序包含3个语句,它们顺序执行。只有最原始的程序可以逃脱:分支和循环同样需要
if语句
if语句是控制流的一个分支:
let name = readLine(stdin)
if name == "":
echo("Poor soul, you lost your name?")
elif name == "name":
echo("Very funny, your name is name.")
else:
echo("Hi, ", name, "!")
这可以有0个或多个elif部分,else部分也是可以选择的。elif关键字比else if短和有效避免过多的缩进
case语句
case语句提供另一种分支方式,一个case语句是一个多分支
let name = readLine(stdin)
case name
of "":
echo("Poor soul, you lost your name?")
of "name":
echo("Very funny, your name is name.")
of "Dave", "Frank":
echo("Cool name!")
else:
echo("Hi, ", name, "!")
正如上面所见,对于一个分支以逗号分割的值列表是允许的
case语句可以处理整数,字符串和其他序列类型。(什么是一个序数类型将稍后解释)对于整数或者其他序数类型值的范围也是可能的:
# this statement will be explained later:
from strutils import parseInt
echo("A number please: ")
let n = parseInt(readLine(stdin))
case n
of 0..2, 4..7: echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}")
of 3, 8: echo("The number is 3 or 8")
然而,上面的代码不能编译:原因是你必须覆盖n可能包含的每一个值,但是这个代码仅处理了值0...8。因为它列出所有可能的值是很不实际的(尽管这个可能的由于范围符号),我们解决这个通过告诉编译器对于其他的每个值什么都不应该做:
...
case n
of 0..2, 4..7: echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}")
of 3, 8: echo("The number is 3 or 8")
else: discard
这个空废弃语句是什么也不做的声明。编译器知道一个case语句带有一个else部分不会失败,因此错误消失了。注意,要涵盖所有可能的字符串值是不可能的,这就是为什么字符串case总是需要一个else分支
在一般情况下case语句用于子界类型或枚举是非常有用的,编译器将检查所有可能的值。
while语句
while语句是一个简单的循环构造:
echo("What's your name? ")
var name = readLine(stdin)
while name == "":
echo("Please tell me your name: ")
name = readLine(stdin)
# no ``var``, because we do not declare a new variable here
这个例子用一个while循环一直询问用户的姓名,只要他什么都没有输入(只按RETURN)
for语句
for语句是一个结构去遍历一个构造器提供的所有值。该示例使用内置countup迭代器:
echo("Counting to ten: ")
for i in countup(1, 10):
echo($i)
# --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
内置的$操作符将一个整形(int)和许多其他的类型转化为一个字符串类型。变量i通过循环隐式的声明为int,因为那是迭代器countup返回的结果。i的值是1-10,每个值都被echo-ed上面的代码也可以这样写:
echo("Counting to 10: ")
var i = 1
while i <= 10:
echo($i)
inc(i) # increment i by 1
# --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
countdown可以很容易的被实现(但是它很少使用)
echo("Counting down from 10 to 1: ")
for i in countdown(10, 1):
echo($i)
# --> Outputs 10 9 8 7 6 5 4 3 2 1 on different lines
由于countup在程序中经常出现。nim也有一个迭代器功能相同:
for i in 1..10:
...
作用域和块语句
控制流语句有一个特性没有包括:他们打开一个新的范围。这意味着,在下面的例子中,x在循环外是不可访问的:
while false:
var x = "hi"
echo(x) # does not work
一个while或者for语句声明了一个隐含的块。标识符只在声明它的块中可以访问。一个块语句可以用来打开一个新的块语句。
block myblock:
var x = "hi"
echo(x) # does not work either
块标签(例子中的myblock)是可选择的。
break语句
break语句可以提前跳出一个块。break可以跳出while,for循环以及块语句。break是跳出最深处的结构,除非给出了一个块的标签。
block myblock:
echo("entering block")
while true:
echo("looping")
break # leaves the loop, but not the block 跳出循环,但不跳出块
echo("still in block")
block myblock2:
echo("entering block")
while true:
echo("looping")
break myblock2 # leaves the block (and the loop) 跳出块(和循环)
echo("still in block")
continue语句
就像在其他很多编程语言中,continue语句直接进入下一次迭代:
while true:
let x = readLine(stdin)
if x == "": continue
echo(x)
when语句
例如:
when system.hostOS == "windows":
echo("running on Windows!")
elif system.hostOS == "linux":
echo("running on Linux!")
elif system.hostOS == "macosx":
echo("running on Mac OS X!")
else:
echo("unknown operating system")
when语句与if语句是大致相同的,以下是一些不同的地方:
- 每一个条件都必须是一个常量表达式,因为它要通过编译器评估
- 在一个分支语句中不打开一个新的范围
- 只有第一条件评估为true时编译器才会检查语句的语义和生成代码。
- when语句对于写特定平台的代码很有用,类似于c编程语言中的#ifdef构造。
注意:要注释一大块代码,通常使用when false:statement比用真正的注释要好。这种方式的嵌套是可能的。