Rogue Likeななにか

ダンジョンの自動生成を作っているけどなかなかぐっとくる感じにならない

        -------------------------       -------
        |.......................|       |.....|
        |.......................+#######|.....|
        |.......................|      #+.....|
        |.......................|       |.....|
        |.......................|       |.....|
        ---+-+-------------------       --+----
           # #                            #
     ####### ##############################
     #                     ##
  ---+-----        --------++-----
  |.......|   #####+.............|
  |.......|   #    |.............|
  |.......|   #    |.............|
  |.......|   #    |.............|
  |.......|   #    |.............|
  |.......|   #    ------------+--
  |.......|   #                #
  |.......|   #                #
  |.......|   #        #########
  |.......|   #        #           -------------
  |.......|   #        #           |...........|
  |.......|   #        #        ###+...........|
  |.......|   #        #        #  |...........|
  |.......+####        #        #  |...........|
  |.......|            #        #  |...........|
  ---------     -------+-----   #  -+-----------
                |...........+####   #
                |...........|       #
                |...........|       ##
                |...........|    ----+----
                |...........|    |.......|
                -------------    |.......|
                                 |.......|
                                 |.......|
                                 |.......|
                                 ---------

Swift LANGUAGE GUIDE を読んで書いたブログエントリの一覧

Advanced Operators

昨日に引き続き https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html を読む。

  • Swiftの算術演算子はオーバーフローしない
  • Int16.max + 1 はエラー
  • オーバーフローする演算子
    • オーバーフロー 加算 &+
    • オーバーフロー 減算 &-
    • オーバーフロー 乗算 &*
  • 二項 static func + (left: T, right: T) -> T {…}
  • 単項前置 static prefix func - (v: T) -> T {…}
  • 複合代入 static func += (left: inout T, right: T) {…}
  • デフォルトの代入演算子オーバーロードできない
  • 3項演算子オーバーロードできない
  • 等価 static func == (left: T, right: T) -> Bool {…} プロトコルEquatableをconform
  • ==を実装したら、ふつう != は実装する必要はない
  • Equatableプロトコルをconformすると宣言したら Swift が==を合成してくれる場合
    • Equatable型の格納プロパティだけ持ってる構造体
    • Equatable型の関連型だけ持つ列挙型
    • 関連型を持たない列挙型
  • カスタム演算子 operator 宣言は ファイルスコープでなければならない
  • prefix operator ☹
  • static prefix func ☹ (v: T) -> T {…}
  • infix operator ☺: AdditionPrecedence
  • static func ☺ (left: T, right: T) -> T {…}
  • 演算子の優先順位は Swift Standard Libraryのほうで決まっているみたい

さてLANGUAGE GUIDEがひととおり終わったので なんかiOSアプリを作ってみたい。ゲームとか。 LANGUAGE REFERENCEを読むのは重箱の隅ほど美味しそうだけど深みにハマっていくのもアレなので。

Access Control

昨日に引き続き https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html を読む。

  • アクセスレベルは5段階
enum AccessLevel {
    case `open`
    case `public`
    case `internal`
    case `fileprivate`
    case `private`
}
  • レベルの高低は、openが最高(最も制限が少ない)、privateは最低(最も制限が多い)
  • openpublicの違いはmoduleを越えてsubclass化とoverrideできるかどうか
  • エンティティは より低い(より制限的な)他のエンティティが出てくるようなやつは 定義できない
    • publicな変数は、internalfileprivate,privteな型で定義できない
    • 関数は、パラメータや返り値の型より高いアクセスレベルにできない
  • デフォルトのアクセスレベルはinternal
  • 多くの場合、コードに明示的なアクセスレベルを指定する必要はありません。
  • 単純な単一ターゲットアプリを書く場合は、internalで充分要件を満たしている
  • フレームワーク開発では APIopenpublicにする
  • 単体テスト可能なのは openpublicだけどinternalなのをテストしたいなら@testableアトリビュートを付ける
  • 型のアクセスレベルは、メンバーの暗黙のアクセスレベルになる
    • privateかfileprivateにすると、メンバーの暗黙のアクセスレベルはprivateかfileprivateになる
    • internalかpublicにすると、メンバーの暗黙のアクセスレベルはinternalになる
  • タプルのアクセスレベルは、中身から最も低いアクセスレベルのやつになる
  • 関数の暗黙のアクセスレベルは、パラメータと返り値型のなかから最も低いやつになる
  • 列挙型の個々のcaseは、列挙型のレベルと同じになる。個々のcaseに異なるレベルはつけられない
  • 列挙型のrawValueと 関連付けられた値は、列挙型と同じか高いアクセスレベルでなければならない
  • ネストされた型の暗黙のレベル
    • private型にネストされた型は、private
    • fileprivate型にネストされた型は、private
    • publicinternal型にネストされた型は、internal
  • サブクラスは、スーパークラスより高いレベルにできない
  • オーバーライドは、スーパークラスでのアクセスレベルより高くできる
  • 定数変数プロパティは、その値の型のレベルより高くできない
  • subscriptはインデックス型・返り値型より高くできない
  • プロパティ等のgetterとsetterの暗黙のアクセスレベルは、そのプロパティ等と同じになる
  • setterにgetterより低いアクセスレベルを与える public private(set) var x = 0
  • イニシャライザは 型の レベルより低くできる
  • required イニシャライザは型のレベルと同じでなければならない
  • デフォルトのイニシャライザの暗黙のレベルは、型のレベルと同じ(public以外)
    • public 型のデフォルトイニシャライザの暗黙のレベルは internal
  • 構造体のmemberwiseイニシャライザは、
    • メンバーのレベルのうち一番低いやつがprivateならprivate
    • メンバーのレベルのうち一番低いやつがfileprivateならfileprivate
    • それ以外は internal
  • プロトコルの各要素のアクセスレベルは、プロトコルのレベルと同じで、違えられない
  • プロトコル継承は、元のプロトコルのレベルまで持てる。高くはできない。
  • プロトコルのconformは、型のレベルよりも低く出来る
  • 型がプロトコルをconformするという文脈は、型のレベルとプロトコルのレベルの最小値
  • extension で定義したメンバーの暗黙のレベルは、元の型のものと同じ(最大internal)
  • extensionにデフォルトのレベルを指定 private extension {…}
  • extensionでプロトコルをconformする場合は extensionのレベルは指定できない。替わりにプロトコルのレベルがデフォルトのレベルになる
  • 元の型と同じソースファイルに書いたextensionから、元の型のprivateにアクセスできる

ふつうinternalだよね〜と言われたので、とりあえず全て無指定で生きて行こうと思うの。

Memory Safety

昨日に引き続き https://docs.swift.org/swift-book/LanguageGuide/MemorySafety.html を読む。

  • シングルスレッドでも競合は起きる
  • 次のすべての条件を満たす2つのアクセスがある場合、競合が発生する
    • 少なくとも1つは書き込み
    • メモリ内の同じ場所にアクセスする
    • 期間が重複する
  • メモリアクセス期間には「瞬時」か「長期」がある
  • ふつうは瞬間的。いくつかの場合「長期アクセス」がある。長期アクセスは他のアクセスとオーバーラップできる
  • inoutパラメータの書き込みアクセスは、他の非inoutパラメータの評価が全て終わった後、 関数呼び出しの期間続く
  • 競合するとランタイムエラー
  • ひとつの解決方法は、値をコピーすること
  • 2つの inout パラメータをとる関数に、同一の変数を渡すとコンパイルエラー
  • 構造体の mutatingメソッド は メソッド呼び出しの期間 self への 書き込みアクセスを持つ
  • x.mutatingMethod(&x)コンパイルエラー
  • 構造体・列挙型・タプルの値の一部を変更すると値全体が変更される場合に競合するおそれがある
  • 次の条件が適用される場合、コンパイラは、構造体プロパティへの重複アクセスが安全であることを証明できる

ちょっと意図しないところで出そうで怖いけど、 コンパイルエラーでもランタイムエラーでも「modification requires exclusive access」と言われるので、 言われたらまあ気づけるかな、と思う。

Automatic Reference Counting

昨日に引き続き https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html を読む。

  • ARCは「ちょうどうまくいく」
  • 参照カウンタが適用されるのはクラスのインスタンスだけ
  • 強い参照の循環ができるとメモリが開放されない
  • 強い参照の替わりに、弱い参照か、所有されていない参照を使えば良い
  • 弱い参照はオプショナル型の 変数 var でなくてはならない
  • weak var tenant: Person?
  • 所有しない参照は参照されるインスタンスの寿命が同じか長いときに使われる
  • 非オプショナル型として定義される
  • deallocateされたあと、参照先にアクセスするとランタイムエラー
  • unowned let customer: Customer
  • お互いに参照しあうとどっちかがOptionalになる←非Optionalにするとコンストラクタでselfにアクセスする2段階初期化問題があるから
  • 暗黙にunwrapされたOptionalな型にする方法がある
  • var capitalCity: City!
  • クロージャはクラスのインスタンスと同様に参照型
  • クロージャ本体がselfにアクセスするとselfをキャプチャーする
  • そのクロージャselfが指すオブジェクトのプロパティ値に入れると、循環参照ができてしまう
  • 「キャプチャリスト」をつくることで、この問題を解決する
  • クロージャの開始{と(引数リスト)との間に
  • 引数リストと返り値方が型推論される時は、クロージャの開始{inとの間に
  • [unowned self, weak delegate = self.delegate!]
  • weak でキャプチャしたやつは Optional型

やっぱり参照カウンタからは逃れられなかったよ