一位老C程序员可以使用Swift的一些帮助。
我不了解if-case语法。 E.g:
if case 20...30 = age {
print ("in range.")
}
case 20...30 = age
似乎是if
语句的条件测试。所以我最初感到困惑的是看到使用赋值运算符(' =')而不是比较运算符(' ==')。
好吧,我想,这可能意味着case
语句实际上是一个返回布尔值的函数调用。然后返回的值将满足if
语句中的比较测试。
作为一项实验,我尝试将case
语句视为常规条件测试并在其周围放置括号。斯威夫特很乐意接受if (x == 5)
或if (true)
。但if (case 20...30 = age)
会产生错误。因此case
语句似乎不像函数那样。
我只是很想知道这里发生了什么。任何见解将不胜感激。
答案 0 :(得分:21)
操作符为if case
,因此您无法添加括号。语法和行为基于Swift case
语句中switch
语句的语法和行为(如果需要详细信息,请参阅my online book)。在case
语句中,20...30
是一个区间,用作模式,它使用contains
对区间进行操作。等号确实令人困惑,但这是他们首次尝试表达case
语句应该与之比较的语法(即switch
之后的标记 switch
语句中的关键字。
所以,如果你明白这一点:
switch age {
case 20...30:
// do stuff
default:break
}
...然后你就会明白它是如何直接变成这个的:
if case 20...30 = age {
// do stuff
}
答案 1 :(得分:6)
@matt很好地解释了代码的作用。我在这里建议一个更好的选择。
您可以使用~=
运算符检查范围。它是一个常规的操作符/函数,只返回Bool
,没有特殊的语言魔法。
if 20...30 ~= age {
print ("in range.")
}
答案 2 :(得分:1)
关于这些Swift运算符的另一个注释。必须记住,Swift有一个非常先进和抽象的编译器,因此关键字只是关键字,它们的行为取决于它们的用法。
与C(以及从C ++到JavaScript的其他语法相关语言)不同,其中if
仅用于测试布尔值(或可转换为一个的值),在Swift中,{{1}的概念声明要广泛得多。 我通常认为它通过使用各种技术(包括布尔测试)来访问范围。
您可以将if
,if
,guard
和while
- repeat
视为更一般的控制流语句,具有更高级的行为。当然他们仍然可以测试布尔值,但他们也可以测试其他条件。在您的方案中,正在测试的条件是某个变量是否与定义的模式匹配(while
匹配模式age
)。
您还可以测试变量是否已成功设置为非20...30
值(nil
)。 if let
操作的结果不会返回布尔值,但由于它发生在let
语句中,因此Swift运行时知道它是控制流的一部分。另请注意,这会稍微改变if
的行为,因为let
块中的任何代码现在都会看到新的非if
值,并确保它不是nil
。
这些行为也可以与逗号结合使用,如下所示:
nil
所以if !skipAgeTest, // `if` tests a Boolean
let age = Double(ageString), // `if` tests optional assignment
case 20...30 = age // `if` tests pattern matching
{
// `age` variable exists and is not `nil` and is between `20` and `30`, inclusive
}
或if let
是独立运算符的概念......并没有以正确的方式正确地考虑它。
就像我说的,这种语法在其他控制流程中也有效:
if case
答案 3 :(得分:0)
即使已经给出了正确的答案,仍然还有一个选择:
20...30
是 ClosedRange ,并且具有一种内置的方法,该方法可读性更高,可以为您工作:contains
if (20...30).contains(age) {
print ("in range.")
}
答案 4 :(得分:0)
使用~=运算符,如@Alexander所述。
if (1...10).contains(n) {
print("pass")
}
switch n {
case 1...10: print("pass")
default: print("bug")
}
if case 1...10 = n {
print("pass")
}
if 1...10 ~= n {
print("pass")
}
您甚至可以执行字符范围:
if "a"..."z" ~= "a" {
print("pass")
}
我进行了两次重载,因此您不仅可以检查范围,还可以检查数组和集合
func ~=<T: Equatable> (pattern: [T], value: T) -> Bool { return pattern.contains(value) }
func ~=<T: Equatable> (pattern: Set<T>, value: T) -> Bool { return pattern.contains(value) }
func ~=<T: Equatable> (pattern: Set<T>, value: Set<T>) -> Bool { return pattern.union(value).count < pattern.count + value.count }
您可以执行以下操作:
if [1, 2, 3] ~= 2 {
print("pass")
}
if [1, 2, 3] ~= [3, 4, 5] {
print("pass")
}
但是,在使用元组时,您仍然必须使用 if case
if case (1...10, 1...10) = (number1, number1) {
print("0")
}
您甚至可以使用_
语法糖
if case (1...10, _) = (number1, number1) {
print("0")
}
if case .some = Optional(number) {
print("pass")
}
if case .some(let x) = Optional(number) {
print(x)
}
if case let x? = Optional(number) {
print(x)
}