2016-04-08 9 views
0

guard-letを使って式に変数を代入したいが、代入する前に式を修正したい。式がnilの場合はelseブロックを入力し、そうでない場合は変数をf(expression)に割り当てる必要があります。変数を割り当てる前にguard-letを使ってnil式を変更する

let arr: [Int] = [] 
// Do stuff, maybe add elements to arr 
guard let x = abs(arr.first) else { return } // Syntax error 
// If arr was nonempty, then we want x = abs(arr.first!) 

しかしabsは、非オプションの引数を必要とし、arr.firstはオプションであるため、スウィフトは、この構文を許可しない:ここで私がやりたいものの一例です。だから、arr.firstを評価する方法はありますか?nilabs(arr.first!)を割り当てようとすると、xに割り当てられますか?私はif-letでこれを行うことができ、あるいは2つの変数(guard-letの変数とその変数の絶対値に割り当てられた変数)を使用してこれを行うことができます。しかし、guard-letは、これを達成するための方法があれば、仕事のためのツールのように思えます。私はクリーンなと最も簡単な解決策は、このようなことだと思う

答えて

2
let arr:[Int] = [-1,1,3,-9] 
guard let x = arr.first.flatMap({ $0 < 0 ? -$0: $0 }) else { return } 
    // ... 

または(dfriのノートに基づいてUPDATE)

// .... 
let arr:[Int] = [-1,1,3,-9] 
guard let x = arr.first.map(abs) else { return } 
+0

うーん、これは最善の答えかもしれません... Swiftはこの作業を行い、私が探していたものに正確に答えてくれるようです。あなたが 'flatMap {abs($ 0)}'だけではない理由は何ですか? – BallpointBen

+0

@James absは素早い言語の一部ではありません...他の理由はありません。可能であれば、私は '純粋な'迅速なソリューションを好む – user3441734

+0

ああ、あなたはそれを使用するために財団をインポートする必要がありますか?とにかくすべてのファイルについてそれをやっていると思いますので、それは大したことではありません。それぞれ自分自身に。 – BallpointBen

2

arr.first != nil場合

guard let first = arr.first else { return } 
let x = abs(first) 

は今、計算abs(first)のみが到達しました。

+0

あなたは正しいです。ごめんなさい!それはコンパイルせずに私の電話で答えるために得られるものです。私はそれに応じて私の答えを修正した。 – tonisuter

+0

私は時代遅れのコメントを削除しました。 – BallpointBen

2

Optional(Some<Int>) -> Int -> Optional<abs(Some<Int)> -> Int ... MEH

次のように汚いguard let ..., let ... else修正を行うことができます(あなたが、その後すぐにアンラップとxAbsに結合するオプションになるためにxのバインドさ確か-not- nil値を強制的に)

func foo() { 
    let arr: [Int] = [-1, 2, -3, 4] 

    guard let x = arr.first, 
      let xAbs = Optional(abs(xAbs)) else { return } 
    print(xAbs, xAbs.dynamicType) 
} 

foo() // 1 Int 

しかしこれは非常にきれいに見えない、と私はCOVうとして、私は、個人的には、好むが、Int拡張子を追加し、オプションのチェーンを利用するだろう次は

代わりに:あなたが明示的にxなどxAbsを格納する必要がない限り、代替とよりSwiftyアプローチがIntへの簡単な拡張との組み合わせで、オプションのチェーンを使用することです

連鎖拡張機能やオプションを使用します。

arr.firstはオプション Int変数があるので
extension Int { 
    var absValue: Int { return abs(self) } 
} 

func foo() { 
    let arr: [Int] = [-1, 2, -3, 4] 

    guard let xAbs = arr.first?.absValue else { return } 
    print(xAbs, xAbs.dynamicType) 
} 

foo() // 1 Int 

は、あなたがeとselfに望むものは何でも方法/計算プロパティを実装することができますxtensionをIntに変更し、オプションのチェーンarr.first?.someMethod()/(上記のように.absValueとして)を使用して、そのメソッド/プロパティにアクセスします。

それとも、単にguard let ... elseブロック(技術的な議論を除く)しかし、私は理由を見ない

xの絶対値を保持する追加の不変を導入していない後にarr.first(開封された)値を変更します。これによりコードの可読性も向上します。少なくともw.r.t.上記汚れたguard let ..., let ... elseに修正してください。

// ... 

guard let x = arr.first else { return } 
let xAbs = abs(x) 

それとも、あなたはxAbsプロパティは、理論的な観点のうち、可変であるために、それは許容あなたではなくguard var ...ブロックを使用することにより不変仲介人を削除することができ見つけた場合guard let ...

guard var xAbs = arr.first else { return } 
xAbs = abs(xAbs) 

xAbsをもう一度突然変異させる場合にのみ使用してください(実際には変数を必要としない場合はいつでもimmutablesを使用してください)。

+1

私は 'absValue'アプローチが好きです。これについて考えると、デフォルトでは、計算されたプロパティとして 'absValue'を実装する必要があったようです。静的な「abs」関数は、Cからの不器用なホールドオーバーです。 – BallpointBen

2

何がcase letを使用して達成することができますしたいです。

let arr: [Int] = [1,2,3,4] 
guard let first = arr.first, case let absolute = abs(first) else { return } 
// use `absolute` 
関連する問題