質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

400閲覧

Swift クロージャーを用いたカウンターについて。「クロージャーは参照型」について。

moriman

総合スコア615

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2019/12/15 06:09

編集2019/12/15 07:20

よくあるクロージャーを用いたカウンターのサンプルコードをいじっていてたまたま気づいたのですが、

Swift

1func createCounter(countBy countBy:Int)->()->Int{ 2 var count:Int=0 3 return {()-> Int in 4 count += countBy 5 return count 6 } 7} 8 9var counter2=createCounter(countBy: 10) //(1) 10print(counter2()) //10 11print(counter2()) //20 12print(counter2()) //30 13print(counter2()) //40 14 15var counter3=counter2 //(2) 16print(counter3()) //50 17print(counter3()) //60 18print(counter3()) //70 19 20counter2=createCounter(countBy:3) //(3) 21print(counter2()) //3 22print(counter2()) //6 23print(counter2()) //9 24print(counter3()) //想定していた結果:12,実際の結果:80 25print(counter3()) //想定していた結果:15,実際の結果:90 26print(counter3()) //想定していた結果:18,実際の結果:100

上記コードで最後の3行より前の部分は全く問題ないのですが、
最後の3行が予想と違う結果が出ました。

https://docs.swift.org/swift-book/LanguageGuide/Closures.html
上記ページに「クロージャーは参照型です」のような説明があるのですが、「参照型」の定義自体のはっきりした説明がなく、結局参照型とは何を意味しているのかいまいちよくわかりません。
javascriptなどの他のプログラミング言語の知識を用いて考えた時、最後の3行はどう考えても
12
15
18
という結果になるんじゃないのかなあ、という感じで、しかし実際の結果は違うので混乱しています。

参照型なので変数counter3は変数counter2と同じものを指すので、counter2に別のカウンター(3ずつ数えるカウンター)をセットしたら、counter3も3ずつ数えるカウンターを指すのではないのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2019/12/15 07:51

counter2=createCounter(countBy:3) の後に counter3=counter2を書いてみてください
guest

回答2

0

ベストアンサー

javascriptなどの他のプログラミング言語の知識を用いて考えた時、最後の3行はどう考えても

12
15
18

javascriptでも結果は同じです。

js

1const createCounter = (countBy) => { 2 var count = 0; 3 return () => { 4 count += countBy; 5 return count; 6 }; 7}; 8 9 10 11var counter2 = createCounter(10); //(1) 12console.log(counter2()); //10 13console.log(counter2()); //20 14console.log(counter2()) ; //30 15console.log(counter2()); //40 16 17var counter3 = counter2 ; //(2) 18console.log(counter3()); //50 19console.log(counter3()); //60 20console.log(counter3()); //70 21 22counter2 = createCounter(3); //(3) 23console.log(counter2()); //3 24console.log(counter2()); //6 25console.log(counter2()); //9 26console.log(counter3()); //80 27console.log(counter3()); //90 28console.log(counter3()); //100 29

参照型なので変数counter3は変数counter2と同じものを指すので

変数counter3は代入した時点の変数counter2が指しているものと同じものを指しています。

投稿2019/12/16 03:06

ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moriman

2019/12/16 03:43

回答をいただきましてありがとうございます。 確かにjavascriptでも同じ挙動でした。 多分Swiftの参照型や値型のはっきりとした定義を私が掴めていない、あやふやな状態だと思うのですが、 公式ドキュメントで該当する箇所ってありますでしょうか? (結局javascriptでもあやふやな認識、ということでしょうから、javascriptでの値型・参照型の定義もはっきり知りたい、という感じなんです、はい。)
moriman

2020/01/02 01:06

ありがとうございました。読んでみます。
guest

0

counter3var counter3=counter2で初期化した時点counter2var counter2=createCounter(countBy: 10)になっていました。
そして、counter2=createCounter(countBy:3) にしてもcounter3createCounter(countBy: 10)のままです。だから、80,90,100の結果は正しいです。
counter3()を呼ぶ前に、counter3createCounter(countBy:3)になったcounter2 counter3 = counter2にすると、結果は12,15,18になります。
以下のコードの通り:

swift

1import Foundation 2func createCounter(countBy countBy:Int)->()->Int{ 3 var count:Int=0 4 return {()-> Int in 5 count += countBy 6 return count 7 } 8} 9 10var counter2=createCounter(countBy: 10) //(1) 11print(counter2()) //10 12print(counter2()) //20 13print(counter2()) //30 14print(counter2()) //40 15 16var counter3=counter2 //(2) 17print(counter3()) //50 18print(counter3()) //60 19print(counter3()) //70 20 21counter2=createCounter(countBy:3) //(3) 22print(counter2()) //3 23print(counter2()) //6 24print(counter2()) //9 25 26//counter3の内容を最新のcounter2にする 27counter3=counter2 28print(counter3()) //想定していた結果:12,実際の結果:12 29print(counter3()) //想定していた結果:15,実際の結果:15 30print(counter3()) //想定していた結果:18,実際の結果:18

後、この記事を楽しんでください。(英語だけど、サンプルコードが分かりやすいです)

投稿2019/12/16 02:50

編集2019/12/16 03:10
vanderlvov

総合スコア685

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moriman

2019/12/16 03:33

回答をいただきましてありがとうございます。 お示し頂いた記事は見てみたいと思います。 それはそれとして、Swiftの公式ドキュメントで値型、参照型の定義について示されている部分はありますでしょうか? はっきりとした定義、つまり 「こういう挙動をすることを参照型と言います。」 のような定義がスタート地点であり、そこから話が展開していくと思うのですが、 https://docs.swift.org/swift-book/LanguageGuide/Closures.html 上記ページでも「クロージャーは参照型です。こうでこうで、こうでこうで・・・」 と話が展開するのですが、「そもそも参照型とは何なの?」と思ってしまう状況で 悩んでいます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問