案例如何适用于案件

时间:2016-06-17 18:45:36

标签: swift

一位老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语句似乎不像函数那样。

我只是很想知道这里发生了什么。任何见解将不胜感激。

5 个答案:

答案 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}的概念声明要广泛得多。 我通常认为它通过使用各种技术(包括布尔测试)来访问范围。

您可以将ififguardwhile - 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)
 }