引き続きお気に入りな技術ブログ「その Swift コード、こう書き換えてみないか」を眺めていきますね。今回は 乱数
を得ることについてのところからになります。Swift では乱数の取得方法が、途中から独特なものに変わった印象なのと、普段あまりランダムな値を取得する機会は少ない気がするので、この機に乱数の取得まわりについておさらいして馴染んでおきましょう。よろしくお願いしますね。
そんな今回は 北海道札幌市 からの配信になります。
——————————————————————————————————————————— 熊谷さんのやさしい Swift 勉強会 #268
00:00 開始 00:38 ランダムな値を取得する 01:15 Swift 4.2 からの新機能 01:59 Swift の乱数機能、使う? 03:10 ランダムな Bool 値が欲しいときに便利 03:57 ランダムな数が欲しいときにも便利 04:48 なぜ randomElement なんだろう 08:00 RandomNumberGenerator 08:48 RandomNumberGenerator を使えばテストも可能に 10:08 型には random ? インスタンスには randomElement ? 10:47 Collection に所属する randomElement 11:17 範囲は Collection に準拠しているか調べてみる 18:01 整数でストライド可能な Range はコレクション 20:41 randomElement という名前に違和感 22:49 ランダムに要素を選ぶコード 27:02 名前を randomElement にした理由は不明 29:20 乱数を生成したか、ランダムに選んだかの違い — という説 31:03 API デザインガイドラインから命名のヒントを探してみる 34:32 クロージングと次回の展望 ———————————————————————————————————————————
Transcription & Summarize : 熊谷さんのやさしい Swift 勉強会 #268
では、始めていきますね。今日は引き続き、個人的にお気に入りの田中陽佳さんのSwiftコードについて進めていこうと思います。前回はとても面白い話題が出ましたが、今回はまた少し落ち着いて見ていけるんじゃないかと思います。
今回の話題はランダムな値を取得するという、Swift特有の機能についてです。あまり使う機会は少ないかもしれませんが、このような機会に知識を蓄えておくと、いざ使う場面が来たときに役立つでしょう。
まず、Swift 4.2未満ではこれらの機能が用意されていなかったため、比較的新しいコードとなります。Swift 4.2以降では、ランダム関数が標準で提供されているため、積極的に使っていきましょう。
ランダムな値を使用するシチュエーションとして、例えばアンプレ出しやレビュー用に使うこともありますね。個人的には、Playgroundでテストケースをランダムに評価する際に利用することが多いです。また、0から9までのランダムな数字が欲しい時などにも便利です。
まず、コードの例を読んでみましょう。昔はarc4random()
などを使っていましたが、Swiftの標準ライブラリで提供されるInt.random(in: 0..<10)
のような範囲指定ができるランダム関数が格段に便利になっています。これにより、手続き的なコードを書く必要がなく、シンプルにランダムな数値を取得できます。
ランダムな値を取得するメソッドは、以下のようなものがあります。
let randomNumber = Int.random(in: 0..<10)
このように、手軽に範囲を指定してランダムな数値を取得できるようになりました。また、配列の中からランダムな要素を取得するrandomElement()
も同様に便利です。
次に、ランダムジェネレータに関してですが、独自のランダム番号生成器を利用することもできますよね。例えば、以下のように使用します。
let randomValue = (0..<10).randomElement()
シード値を使って同じランダムな値を繰り返し出すことが可能で、以前の方法よりも柔軟です。
以上の内容を踏まえて、引き続きSwiftのランダム関数について深掘りしていきましょう。興味深い点がたくさんありますので、一つ一つ確認しながら進めていきます。 「ランダムエレメント」の定義を見ていきましょう。まず、コレクションに対して randomElement()
のメソッドを使えば、要素の中からランダムに1つを選ぶことができます。このメソッドは、例えば配列やセットといったコレクションタイプに適用できますね。
次に、このメソッドの戻り値が Optional
であることを確認します。つまり、コレクションが空の場合には nil
を返すので、必ず Optional
の扱いを万全を期しましょう。
ここで一つ具体例を見てみましょう。以下のように配列 numbers
に対して randomElement()
を使用します。
let numbers = [1, 2, 3, 4, 5]
if let randomNum = numbers.randomElement() {
print("ランダムに選ばれた数: \\(randomNum)")
} else {
print("配列は空です")
}
このコードでは、numbers
配列からランダムに1つの要素を取り出し、その値を randomNum
に代入します。もし配列が空であれば、nil
が返されるため、else
ブロックに入ります。
また、コレクションの範囲を試す際に range
を使うことも良い方法です。例えば、0..<10
のように範囲を定義して、その中からランダムなエレメントを取得することができます。
let range = 0..<10
if let randomRangeElement = range.randomElement() {
print("ランダムに選ばれた範囲の要素: \\(randomRangeElement)")
} else {
print("範囲が空です")
}
このように、randomElement()
メソッドを用いることでコレクションからランダムな要素を簡単に取得することができます。
次に、ランダム選択に関する別のメソッドとして shuffled()
もあります。これを使うと、コレクション全体をランダムにシャッフルすることができます。
let shuffledNumbers = numbers.shuffled()
print("シャッフルされた配列: \\(shuffledNumbers)")
このコードでは、元の numbers
配列がランダムな順序にシャッフルされ、新しい配列 shuffledNumbers
に代入されます。
まとめとして、Swiftのコレクション操作では、用途に応じて randomElement()
や shuffled()
などのメソッドを上手く活用することで、効果的かつ効率的なランダム操作が可能です。 今回の話題は、Swift言語におけるランダムエレメントの取得方法についての議論です。
Swiftにはコレクションからランダムに要素を取得するrandomElement()
というメソッドがあります。このメソッドはコレクションの要素からランダムに一つの要素を返します。例えば、以下のように使用します:
let numbers = [1, 2, 3, 4, 5]
if let randomElement = numbers.randomElement() {
print(randomElement)
}
また、コレクションに対してrandomElement()
が適用されることから、コレクションとは何かについて少し触れていました。Swiftのコレクションは配列(Array
)、セット(Set
)、辞書(Dictionary
)などがありますが、これら全てがCollection
プロトコルに準拠しています。そのため、これらのコレクションタイプは全てrandomElement()
を使用することができます。
会話の中では、中間生成物として使う変数や一時的な計算結果の保持についても触れられています。例えば、ある値を基に条件を分岐させつつ、結果を再使用したい場合に、いくつか問題に直面することも話題に上がりました。特にエラーハンドリングやコンパイラーのビルドなどに関わる話題もあります。
また、ランダム要素の取得方法に関する意見交換も行われていました。メソッド名が直感的でないとの意見や、他のネーミングの提案もされているようです。例えば、「ランダムにピックアップする」といった具体的な機能名にすることでコードの可読性を向上させるべきではないかという意見も聞かれました。
さらに、Swift 4.2以降で導入されたrandomElement()
メソッド設計意図や背景についても触れられました。このメソッドの導入により、簡単かつ直感的にランダムな要素を取得できるようになった反面、名前のセンスや適用範囲についての疑問も出てきたようです。
結局、randomElement()
の実装詳細や利用方法についての議論は多岐に渡り、多くの視点から検討されました。このようにプログラミング技術や手法について深掘りする勉強会は非常に貴重であり、参加者の理解促進に役立つと思われます。 理由はランダム性を定義的に使うとこうなってしまうのかなと思ったりします。ランダム性で点数に対してランダムを得て、それが仕立ち占める場所を探していく感じです。あとは余韻だと思いますが、本当に余韻をキャプチャしているのは何でしょうか。余韻とは余韻で、コレクションはオフセットバイディスタンス(距離によってオフセットされる)です。距離は古くないかもしれませんが、昔は距離がアソシエイティブタイプだったんです。今もそうかもしれませんが、現在はイント型に固定されています。
ただ、どっちかというとトリプルかどうか、という話ですね。昔の名前です。これで距離型にキャストする話になります。重要な話をすれば、こんな感じでエボルーション(進化)を見たかったんですが、持っていませんでしたね。名前にしていたからなのかもしれません。自分の場合ですね。
ランダムエレメントにしたか、同じAPIをもう少しトリプル型にしてアソシエイティブタイプ(結びつきの型)に持っていませんでした。ランダムはアソシエイティブタイプの名前として、リプレーストリーフインペーターとファイナリティプローティングポイントとプールがあります。コレクションともあったけど、とりあえずその辺は終わらせてランダムにしましょう。
片名に対してランダムは名前として違和感はありません。エボルーションとコレクションと書いてあって、いきなりランダムエレメントが出てくる感じです。カミパリアンはどうだったかな。ランダム表現範囲内から返すという選択もありますが、ポテンシャルを考えなくてもファイナルインディジュアルと想定したときにランダムを当てた方が嬉しいかもしれません。その時にはレンジが必要で、現在の形が悪くなります。ランダムに無限の場から選ぶことができなくなりますが、レンジがあるので問題ありません。
アソシエイティブタイプの名前として、プールランダムはプールとランダムに設定します。ランダムとコレクション、ランダムエレメントもそれと同様です。名称としては当てはまっていますが、趣旨としてはナンバーデッドバリューMSナンバーのナンバー。これのバリューはイントのようなものです。そのため、イントダイナリウムと言っていました。これに対してスネークナンバーのような表記です。
アメリカにあったとき、ランダムバイルという店舗でエレメントを作るところがありましたが、遠くて構成ができないことがありました。通常エレメントを使用するとエレメントが必要だったという発想がありますね。リムーブエレメントについても同様で、エレメントをつける場合は自然な読み方ができます。
一方、バリアブル(可変)の場合は一言で、この用途はプリントリングのような用途ではなく、しっかりとした用途で使用しましょうという感じです。モドリッジはオーバーロードしないように気をつけるぐらいしか書いてありませんでした。メソッド名に関しては、対応する生成名称が名詞かET、またはINGのどれかです。アペンドとアペンディズのように。
インデックスについては、インデックスアクターだから生成の意味があります。ランダムエレメントを属させるという表現も悪くないかもしれません。最後にはテレビの時間帯にもなって、かなり脱線もしましたが、とにかくランダムはこうやって得られるので考えてみてください。次回はオプショナル系を見ていく予定です。またよろしくお願いいたします。
今日はこれで終わりにします。お疲れ様でした。ありがとうございました。