## クロージャの『キャプチャ』とは?
クロージャ
について、
#### ①
上記3つの引用は同じ事柄を指しているかと思いますが、
親関数(or子)で宣言された変数を参照できる、という理解で宜しいでしょうか?
また、自分(=クロージャ)が定義された「スコープをキャプチャ」するとは具体的にどのような意味でしょうか?
#### ②
**『キャプチャ』**とは... 参照、操作、扱うのようなニュアンスで宜しいでしょうか?
質問は以上です。
お時間あるときに、ご返信頂けましたら幸いです????
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
はっきりとしたことは示せていないので、回答と言えるかどうかはわからないのですけれど、何かのヒントになりそうなことを紹介しておきます。
キャプチャーの意味(①, ②)
たぶん、クロージャーの「キャプチャー」という言葉はいろんな意味に使われるような気がします。
その中のひとつに、挙げられていた「親関数(子⋯はないかも? ここは逆にもう少し詳しく聞きたい)で宣言された変数を参照できる」も含まれているように感じます。そして「参照、操作、扱う」みたいなニュアンスかといえば⋯、なんとなく、たしかにそうとも言えそうな気もします。
関連用語
クロージャーのキャプチャーに関連する言葉といえば、次の2つが思い浮かびますので、このあたりを調べてみるとクロージャーのキャプチャーに対する見識がもう少し膨らんでくるかもしれません。
- 自分が定義されたスコープの変数や定数をそのまま参照する「クロージングオーバー」
- 自分が定義されたスコープの変数や定数をコピーして自分のスコープに置くのに使う「キャプチャーリスト」
「自分が定義された「スコープをキャプチャ」する」の意味(①)
これはおそらく次のような感じで、そのクロージャーを定義したのと同じ(同列)の局所スコープに定義されている変数または定数をキャプチャーできるということを言おうとしていると思います。
swift
1func makeSerialNumberGenerator() -> () -> Int { 2 3 // クロージャーが定義されているのと同じスコープ 4 var number = 1 5 6 // クロージャーが定義されているスコープ 7 let closure = { () -> Int in 8 9 // この中で `number` を参照すると、それをキャプチャーできる。 10 // 参照できるだけではなくて、クロージャーが内部に参照を保持します。 11 defer { 12 13 number += 1 14 } 15 16 return number 17 } 18 19 // たとえば、定義したクロージャーを戻り値として外側に返すと、 20 // 通常であれば破棄されるはずの `number` も抱えたまま返す。 21 return closure 22}
たとえばこのコードを書いたときに面白いのが、コード内のコメントにも書きましたけれど、makeSerialNumberGenerator
関数がその中で定義したクロージャー closure
を戻り値で返したときに、そのクロージャーを作るときにキャプチャーした number
を内包したまま維持するところです。通常であれば、関数を抜けたときに number
が破棄されるのですけれど、今回みたいにクロージャーがキャプチャーして、それが戻り値として返されたりインスタンスプロパティーなどに保存されたときは、number
は破棄されずにクロージャーが破棄されるまで存続します。
クロージャーが単純に外側の変数や定数を参照しているのではなく、このように内部で使われる変数や定数をキープすることを、たぶん「キャプチャー」と表現しているのだと思います。
キャプチャーの仕方にも種類がある
そしてこのクロージャーを定義するとき、今回みたいに暗黙的にキャプチャー(クロージングオーバー)するか、それともクロージャー定義の冒頭あたりでキャプチャーリストを明記するかで、その中で使う変数や定数(今回であれば number
)の扱われ方が変わってきます。
これによって、キャプチャーした変数や定数の扱われ方が変わってきて、元の変数や定数に影響を与えるかどうかも変わってきます。大きいような小さいような、ともあれさりげなく挙動が変わってくるので、このあたりの変化をはっきり意識するか考慮せず広く考えるかでも「キャプチャーとは何か」の捉え方が変わってきそうな気がします。
なんにしても、先ほど挙げたコードの例と、挙げた2つの言葉「クロージングオーバー」と「キャプチャーリスト」について調べてみると、クロージャーに対する視野がまた広がってくるかもしれないです。
先ほどのコード例の遊び方
先ほどのコードを記載した後、次のようなコードを書くと、実際に動かしてキャプチャーの挙動を試すことができます。戻り値で受け取ったクロージャーがキャプチャーしているはずの number
の値の変化に注目してみてください。
swift
1let serialNumberGenerator = makeSerialNumberGenerator() 2 3serialNumberGenerator() // => 1 4serialNumberGenerator() // => 2 5serialNumberGenerator() // => 3
投稿2020/09/17 06:27
編集2020/09/17 06:53総合スコア441
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/09/17 08:53
2020/09/17 09:52 編集
2020/09/17 13:41 編集
2020/09/17 14:43
2020/09/17 16:36
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。