30913


swift3.01での条件文＋バインディング式の書き方の勉強中です。

TestSwitch関数は、「.Pass」 or 「.Fail(n) where n >100」のとき  
switch文が実行されるようにしたいのですが、

if文では、条件にすべて合致しないので、すべてswitch文が実行されます。  
guard文では、条件に合致するようで、switch文が実行されません。

条件式の、「or」「,」「where」など使い方が分かっていません。  
教えてください。

func TestSwitch(_ e:Exam){

1.  
//if case let .Fail(a) = e, a < 100 , case .Pass = e{  
// return  
//}  
2.  
//guard case let .Fail(a) = e, a > 100 , case .Pass = e else{  
// return  
//}

[code]

    switch e {
        case .Pass(let n) where n < 300:
            print("Pass:300:\(n)")
        case let .Pass(n) where n < 5000:
            print("Pass:5000:\(n)")
        case .Fail:
            print(e)
    
        default:
            break
    }
    
[/code]

}

enum Exam {  
case Pass(Int)  
case Fail(Int)  
}

let exam : [Exam] = [.Pass(100), .Fail(50), .Fail(500), .Pass(1000)]

for e in exam{

[code]

    TestSwitch(e)    
    
[/code]

}


CC BY-SA 3.0
2016-12-05T02:32:03.440
30910
2016-12-05T04:14:41.883
11148
question
swift swift3
条件文の書き方（if文,guard文）


あなたの所望の条件『「.Pass」 or 「.Fail(n) where n >100」のときswitch文が実行される』をearly
returnのパターンで実現しようと思うと、`if NOT(「.Pass」 or 「.Fail(n) where n >100」)
{return}`または`guard (「.Pass」 or 「.Fail(n) where n >100」) else
{return}`の意味のことが実現できないといけません。

Swiftの`if`/`guard`の`,`は論理で言うとANDの動作になりますし、同じ条件を`(NOT「.Pass」 and NOT「.Fail(n)
where n >100」)`と書き換えても(ド・モルガンの法則というやつです)、Swiftにはenum
caseに対して、`NOT「.Pass」`を容易に表現する手段が用意されていません。

どうしても、`if`や`guard`を使って書きたいのであれば、こんなことをすることになるでしょう。

[code]

    func TestSwitch(_ e: Exam){
    
        let pass: Bool
        if case let .pass = e {pass = true} else {pass = false}
        let failOver100: Bool
        if case .fail(let n) = e, n > 100 {failOver100 = true} else {failOver100 = false}
    
        if !(pass || failOver100) {
            return
        }
    
        switch e {
            //...
        }
    }
    
[/code]

あるいは、

[code]

    func TestSwitch(_ e: Exam){
    
        let pass: Bool
        if case .pass = e {pass = true} else {pass = false}
        let failOver100: Bool
        if case .fail(let n) = e, n > 100 {failOver100 = true} else {failOver100 = false}
    
        guard pass || failOver100 else {
            return
        }
    
        switch e {
            //...
        }
    }
    
[/code]

(Swift 3では、enum
caseも小文字で始めるのが習慣のようなので、`.Pass`と`.Fail`を`.pass`と`.fail`に書き換えてみました。まずければその部分を元に戻して試してみて下さい。)

* * *

Swiftでenum
caseとand/orが複雑に絡んだ条件をどううまく書くのかを突き詰めていくのも面白そうなのですが、もう少しあなたのケースに沿った簡略化を考えてみましょう。

あなたのenumには`.Pass`と`.Fail`の2つのcaseしかないわけですから、『「.Pass」 or 「.Fail(n) where n
>100」のときswitch文が実行される』と言うのは、『「.Fail(n) where n <=
100」のときにはswitch文は実行されない』と言うことになります。

これなら`if-return`で簡単に実現できます(`guard`では条件を否定しないといけないのでちょっと面倒)が、無理にswitchの外でearly
returnのコードを作らなくても、switchの中で判定しても良いのではないでしょうか。

[code]

    func TestSwitch(_ e: Exam){
        switch e {
    
        case .fail(let n) where n <= 100: //<-※
            return
    
        case .pass(let n) where n < 300:
            print("Pass:300:\(n)")
        case let .pass(n) where n < 5000:
            print("Pass:5000:\(n)")
        case .fail:
            print(e)
    
        default:
            break
        }
    }
    
[/code]

※Swiftでは、switchのcaseは上から順に評価されますので`return`のcaseは最初(少なくとも`case
.fail:`より前)に書く必要があります。

お試しください。(「条件文＋バインディング式の書き方の勉強」としては、期待に添わない回答かもしれませんが、`if`や`guard`が必ずしもそぐわないケースがあるというのも勉強のうちということで。)


CC BY-SA 3.0
2016-12-05T04:14:41.883
30913
2016-12-05T04:14:41.883
13972
30910
answer