2017-03-09 16 views
3

私はオーディオプレーヤーのグローバル変数を持っています。変数の初期化"try"キーワードの配置の違い

do{ 
    try audioPlayer = AVAudioPlayer(contentsOf: audioURL) 
}catch {} 

前にトライ単語を配置し、コンストラクタ2例は、上記のいずれかのコンパイルエラーを持っていないもちろん

do{ 
    audioPlayer = try AVAudioPlayer(contentsOf: audioURL) 
}catch {} 

を呼び出す前に試して置くことの違いは何ですか 。 ありがとう

+0

私は、最初のケースでは割り当てを試み、2番目のケースでは開始を試みることをお勧めします。しかし、私は確信していない、ちょうど推測する。 – JuicyFruit

答えて

5

実際的な違いはありません。 (強調鉱山)said by the language guideとして:

バイナリ演算子の左側の式がtrytry?、又はtry!付い ある場合、そのオペレータを 全体のバイナリ表現に適用されます。つまり、括弧を使用して、演算子のアプリケーションの範囲について明示的に とすることができます。ただ、+よう

// try applies to both function calls 
sum = try someThrowingFunction() + anotherThrowingFunction() 

// try applies to both function calls 
sum = try (someThrowingFunction() + anotherThrowingFunction()) 

// Error: try applies only to the first function call 
sum = (try someThrowingFunction()) + anotherThrowingFunction() 

、割り当ても二項演算子です。あなたは

do{ 
    try audioPlayer = AVAudioPlayer(contentsOf: audioURL) 
}catch {} 

を言うときしたがって、try表現audioPlayerAVAudioPlayer(contentsOf: audioURL)の両方に適用されます。孤独な表現audioPlayerはおそらくはここでエラーをスローすることはできません - したがって、この場合はtryのみAVAudioPlayerinit(contentsOf:)、どのできスローへの呼び出しに適用されます。

導出このためof the grammarがある:

//   "try"   "audioPlayer"  "= AVAudioPlayer(contentsOf: audioURL)" 
expression → try-operator­opt ­prefix-expression ­binary-expressions­opt 

prefix-expression → prefix-operator­opt ­postfix-expression 
postfix-expression → primary-expression­ 
primary-expression → identifier­ generic-argument-clause­opt 
identifier­ → // matches "audioPlayer" (I'm not going to fully derive this bit further) 

binary-expressions → binary-expression ­binary-expressions­opt 
binary-expression → assignment-operator ­try-operator­opt­ prefix-expression 
prefix-expression → prefix-operator­opt postfix-expression 
postfix-expression → initializer-expression­ // matches AVAudioPlayer(contentsOf: audioURL)

あなたはあなたが代入式has the grammar ofという事実を使用している

do{ 
    audioPlayer = try AVAudioPlayer(contentsOf: audioURL) 
}catch {} 

を言うとき:

binary-expression → assignment-operator ­try-operator­opt ­prefix-expression­

することができますように参照:try-operatorがオペレータの右側に表示されます。prefix-expressionに適用されます。この場合はAVAudioPlayer.init(contentsOf:)です。

どちらの場合も、AVAudioPlayer.init(contentsOf:)からスローされる可能性のあるエラーをキャッチしています。最初の例は、オペレータの左側の式からエラーが発生する可能性を示しています。は、おそらくにはありません。

私の個人的な好みと、言語の他の場所でのtryの配置とより一貫しているオプションは、tryを右側に置くことです。

+3

すばらしい説明。例外を持つ言語から来た人は、 'try'はlongjmpがどこに行くのか、あるいは他の"例外 "実装の詳細をマークする深刻な意味を持っていると仮定するかもしれません。スウィフトの例外はちょうどファンキーな「リターン」のバージョンであることを覚えておくと便利です。 'try'はコンパイラやコード生成に影響を与えません。プログラマに、このコードブロックが例外をスローするかもしれないことを思い出させるのは純粋にそこにあります。コンパイラが「試行」がそのリマインダを提供するのに十分に近いと感じると、それは満足です。 :D –

+0

実際これはあまり真実ではありません。行頭の 'try'がコンパイルされない状況があります。私はそれが今までコンパイルしているという事実はバグだと思う。 – matt

+0

@ハミッシュ、あなたの素晴らしい答えをありがとう! – GeRyCh

2

私の見解では、これはコンパイルという事実は、バグの一種である:基本的に、あなたがやるべきではない何かを

try audioPlayer = AVAudioPlayer(contentsOf: audioURL) 

やっている、とあなたはそれが過ぎて摺動するだけでラッキーコンパイラはこちら。 audioPlayerはここで宣言されていた場合に何が起こるか、反例として、考えてみましょう:はないコンパイル、および修正は、それが正しくそれが属する場所にtryを移動

try let audioPlayer = AVAudioPlayer(contentsOf: audioURL) // error 

こと:

let audioPlayer = try AVAudioPlayer(contentsOf: audioURL) 

私が従うことを推奨する規則は、try配置を正しく使用することです。 - それはスローできるメソッド呼び出しを変更します。それは時には全体としての課題には役立つかもしれませんが、必ずしもそうではありません。

+0

それはやや違ったことです - それは束縛です。定数宣言のための[文法](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097)を見てください。 -CH34-ID355)、 '='の右側の式までは 'try'の余地がありません。ルールが矛盾していることに同意しますが、rhsで '試行すること 'が望ましいです:) – Hamish

+0

@Hamish右、私は、"行頭で "試してください"という概念を一般的には否定していませんはい。私はそれが何か良いと思ったら、私はこれにバグをファイルするだろうが、私はそれがないと知っている。 :) – matt

+1

'try'は常に*式*に接頭辞を付けます(メソッド呼び出しではありません)。そのため、 '()'や 'Void'型の式である代入に接頭辞を付けるのは合法です。 'try'では、式の投げる部分にすぐにプレフィックスを付ける必要はありません。あなたの例 'let audioPlayer = ...'は宣言なので、 'try'でマークすることはできません。 –

関連する問題