2017-01-17 15 views
1

は、以下のコード例を検討:スコーピングは、スウィフトの実行遅延にどのように影響しますか?

enum Counter { 

    case value(Int) 

    mutating func add(value: Int) { 

     // part A 
     var orig = self 
     defer { print("[part A] direct defer : ", value, "+", orig, "=", self) } 

     // part B 
     do { 
      var orig = self 
      defer { print("[part B] do block defer: ", value, "+", orig, "=", self) } 
     } 

     if case let .value(prev) = self { 
      self = .value(value + prev) 
     } 
    } 
} 

var c = Counter.value(0) 
c.add(value: 10) 

我々がintカウンタとして格納するために使用される一つのケースを有する単純なカウンタ列挙しています。関数addは、valueを抽出したカウンタ値にselfで加算して更新します。そうでない場合、両方のものとどのような最終的な出力に加えなっているものの値のログを印刷 -

part A機能レベルでスコープれるディファー文における2つのprint sがあり、そしてpart B、ローカルdoブロック内スコープれますされます。

コードに基づいて、出力は両方とも延期されたprintで同じに見えるはずです。ただし、それらは異なっています:

[part B] do block defer: 10 + value(0) = value(0) 
[part A] direct defer : 10 + value(0) = value(10) 

なぜ同じではありませんか?

ブロックdoブロックは自分自身をキャプチャし、それを早めに遅延させるか、この意図されたデザインと認識しておく必要があるものですか?

+0

'defer'ブロックにはC++デストラクタセマンティクスがあり、それらはブロックを離れるポイント実行時に直ちに実行されます。あなたが見ている動作は設計によるものです。 – Mgetz

答えて

5

この現象は予期したとおりです。 the Language Reference - Statementsから

[重点鉱山]

延期書

がディファーステートメントは延期文が 内に表示されていることだけ範囲外 プログラム制御を転送する前にコードを実行するために使用されます

あなたの例ではAdeferが実行されたときに、変異add(value:)機能は、その作業を終えた、ひいては(10に)selfを増加させました。 Bdeferステートメントはdoボディ内に配置されていますが、doのプログラムコントロールをadd(value:)の直下のスコープに戻すと実行されます。したがって、Bdefer文が実行されると、selfはまだ変更されていません。

関連する問題