一个 C++ 程序员眼中的 Swift(三)
On 2014-12-03 23:22:15 By Soli一个 C++ 程序员眼中的 Swift(三)
接下来的内容就更有趣了,方便的for-in、强大的switch、 穿越的break等等。每一个都戳到了 C++ 程序员的痛处或痒处。
for-in现在大多数语言都已支持
for-in语句了。C/C++ 还在固守成规。Swift 的
for-in语句与它的区间运算符简直是绝配,写个循环如此简单:var sum = 0 for i in 0..<10 { sum += i }迭代数组也极其方便:
let names = ["xiaoming", "xiaolan", "xiaohong"] for i in 0..<names.count { println("\(names[i])") }迭代数组何必需要下标?
let names = ["xiaoming", "xiaolan", "xiaohong"] for name in names { println("\(name") }往下看前先默念一遍 C++ 中如何迭代
std::map的。然后再看 Swift 是怎么做的:let scores = ["xiaoming":98, "xiaolan":89, "xiaohong":99] for (name, score) in scores { println("\(names) got \(score)") }增强的
switch不再有漏写
break的烦恼。Swift 的switch中每个case都是默认break的,无需在最后写break。但在 C/C++ 中,有时我们是故意不写
break的。Swift 为了支持这一特性,增加了fallthrough语句。虽然增加了新的语句,但这更符合实际情况。在大多数情况下我们想要的是
break,而极少数情况下才需要fallthrough。而默认值应该是照顾大多数情况的。所以,Swift 中是默认break而需要显式写fallthrougn,而 C/C++ 中却是默认fallthrough而需要显式写break。下面是个例子:
let skills = 2 var description = "You are a " switch skills { case 2: description += "senior " fallthrough case 1: description += "expert" default: description += "good guy" } println(description)Swift 要求
switch中的case必须是完备的,即列举所有的情况。当然,可以使用default来覆盖那些我们不关心的情况。Swift 还要求每个
case下必须含有有效的语句(注释不算)。所以,如果你想忽略某个(些)case,你需要显式的写个break。每个
case可以写多个条件:switch result { case "true", "True": println("correct") case "false", "False": println("wrong") default: println("invalid") }case里的条件不只是一个或多个的值,还可以是区间:switch temperature { case -40 ... -10: println("frigid") case -10 ... 5: println("cold") case 5 ... 20: println("cool") case 20 ... 28: println("warm") case 28 ... 40: println("hot") default: println("not for human beings") }还可以是元组:
switch (strength, magic) { case (0, 0): println("die") case (0, _): // 下划线表示该项可为任意值。 println("revive") case (80...100, 80...100) println("attack") case (0...30, _): println("escape") default: println("defense") }可以看到,各个条件是可以重叠甚至相同的。Swift 只执行第一个匹配到的条件下的语句。
值绑定
有时你需要在
case里的代码段里使用case所匹配到的值。这时可能就会用到值绑定。比如:let point = (0, 3) switch point { case (let row, 0): println("rown number of \(row)") case (0, let col): println("headline of \(col)") case let (row, col): println("data of (\(row), \(col))") }当然,也可以用
var声明变量来进行值绑定。这个特性除了方便之外,似乎没有什么用。因为我们可以通过
point这个常量来引用我们需要的值。比如:let point = (0, 3) switch point { case (_, 0): println("rown number of \(point.0)") case (0, _): println("headline of \(point.1)") default: println("data of (\(point.0), \(point.1))") }用
where给case加上条件判断。这让switch更像一系列if...else了。let point = (3,3) switch point { case (_, _) where point.0 > 0 && point.1 > 0: println("point is on the first quadrant") case let (x, y) where x > 0 && y < 0: // 用了值绑定,是不是方便多了。 println("point is on the forth quadrant") case let (x, y) where x < 0 && y > 0: println("point is on the second quadrant") case let (x, y) where x < 0 && y < 0: println("point is on the third quadrant") default: println("point is on the axes") }
带标签的语句
在嵌套循环中,有时我们想直接跳出到最外层循环。另外,在嵌套的
switch里,或循环和switch混合嵌套的情况下,同样有这种需求。在 C/C++ 中可以使用
goto语句来实现。有时这也不失为一种优雅的办法。在很多教材或文章中,甚至在很多老师和前辈的口中,goto语句都被妖魔化了。为了避免使用goto,宁可增加很多标志变量再绕几个弯儿来实现一句goto就可以实现的逻辑。即使有充分的理由在代码中使用了goto,心理上也承受着会被别人嘲讽的压力。在 Swift 中,你完全可以抛掉这些心理负担了。因为只需在
for、while或switch等语句前加个标签,你就可以随心所欲的break或continue指定的控制流了。fl: for i in 0...20 { sl: switch i { case 0: fallthrough case 1: break sl default: for j in 2..<i { switch i % j { case 0: continue fl default: break } } println("\(i)") } }未完待续
Except where otherwise noted, content on this site is licensed under a
Creative Commons Attribution 4.0 International license
.