swiftc
でコンパイルすると手元で15秒くらいかかるんだけどそれはそういうもんなのかな var fuga1: Int! = 1 var piyo1: Int! = 1 let hoge: [(fuga: Int?, piyo: Int?)] = [ (fuga: fuga1, piyo: piyo1), (fuga: fuga1, piyo: piyo1), (fuga: fuga1, piyo: piyo1), (fuga: fuga1, piyo: piyo1), (fuga: fuga1, piyo: piyo1), (fuga: fuga1, piyo: piyo1), ] print(hoge)
Int!
から Int?
に変えるとすぐ終わるExpressibleBy***Literal
があるからリテラルの型推論は組合せ爆発が起こるのだと僕は推測してます。let hoge: [Int?] = [ fuga1, fuga1, fuga1, fuga1, fuga1, fuga1, ]
これはすぐに終わる(Int, Int)
から (Int?, Int?)
へのアップキャストにも見えてるのかvar fuga1: Int! = 1 var piyo1: Int! = 1 struct A { var fuga: Int? var piyo: Int? } let hoge: [A] = [ A(fuga: fuga1, piyo: piyo1), A(fuga: fuga1, piyo: piyo1), A(fuga: fuga1, piyo: piyo1), A(fuga: fuga1, piyo: piyo1), A(fuga: fuga1, piyo: piyo1), A(fuga: fuga1, piyo: piyo1), ]
これでも同じだけ時間かかるlet hoge: [A] = [ A(fuga: fuga1 as Int?, piyo: piyo1 as Int?), A(fuga: fuga1 as Int?, piyo: piyo1 as Int?), A(fuga: fuga1 as Int?, piyo: piyo1 as Int?), A(fuga: fuga1 as Int?, piyo: piyo1 as Int?), A(fuga: fuga1 as Int?, piyo: piyo1 as Int?), A(fuga: fuga1 as Int?, piyo: piyo1 as Int?), ]
明示してもだめだたvar fuga1: Int! = nil
だったらクラッシュしない?Int?
には nil
はいるやんInt!
は nil になってはいけないのでは? if x == nil { }
とかOKnil
になっていることを想定していないのが Foo!
だと思ってる。.some()
の引数部分に書くと駄目って意味か。 (edited)x as Int?
と .some(x)
の違いがあるとnil
の可能性があるなら Foo?
にすべきInt!
が、 nilのとき、nilじゃないときを、プログラマーが意識して分岐するコードはありえるFoo!
が nil
になっているコードは Logic failure だと思う。Foo?
にすればよくない?@IBOutlet
は利用時に nil
でない想定じゃないですか?UIImageView!
を UIImageView?
として扱いたいみたいなコードを書いてる時にコンパイルが終わらなく鳴って発見したFoo!
の !
は foo!
の !
と同じ文脈のものと考えるのが自然だと思うけどなぁ。nil
でないけど型ではそれは表せない場合のショートカット。lateinit var
っていう機能があって、こいつは、同じような目的なんだけど、 nil
の再代入ができないからT
なんだよねNotNull<T>
っていう Delegated Property
っていう言語機能を使うようになっていたDelegated Property
ってのは、まさにgetter/setterをオブジェクトとして差し込む仕組みでnil
の再代入ができないけど未初期状態を持てる って実現できるんだよね@IBOutlet view: HogeView!
の1点にはできますね。!
で定義したくなっちゃうな?@IBOutlet
だけは諦めて、その他の状態についてはちゃんと型に切り出してイニシャライザで初期化して、適切なライフサイクルで生成・破棄するのがいいんじゃないかなぁ。 var estimator: Estimator! var network: Network! var edges: [(Vector3, Vector3, Line3, Edge)]!
class App { func openDialog() { /* ... */ } func closeDialog() { /* ... */ } func doDialogSomething1() { self.dialog!.something() } func doDialogSomething2() { self.dialog!.something() } func doDialogSomething3() { self.dialog!.something() } }
doDialogSomething1
の呼び出し規約が、 dialogが利用可能な状態である、ってことを規定しているなら、!
を毎回付けるより、そもそも dialog: Dialog!
と IUO を使っちゃってもいいような気がしてるdoDialogSomething
の冒頭で、 guard let dialog = self.dialog else { fatalError("aaa") }
とか let dialog = self.dialog!
とかやって、 !
を減らす工夫はできるんだけどもね。foo!
を毎回書く代わりに Foo!
にするってことは、 IUO で Logic failure を引き受けているということになる。IUO
にするってパターンが出てくるんじゃないかなとdoSomethingDialog
相当の処理が実行される func doDialogSomething1() { if let dialog = self.dialog { dialog.something() } }
!
を使ってないからね)doDialogSomething1
を呼び出す時には前提として nil じゃないんだ、っていう表明はむしろできないdoDialogSomething
みたいな抽象的な例だと話がすれちがっちゃって空中戦になりそうだから、具体的なケースを考えたほうがよさそう。!
使うのが適切に思える場面が出てくる。!
でクラッシュしてたほうが、デバッグがしやすい場合がある → そういう場合なら、型で解決しないで、 !
を含むコードを書いておいたほうが、総合的にお得!
使っても同じ話。?
もほぼ存在しないのは、 subscribe
しない っていう状態に逃したからなんじゃないかなあT?
がなくなったとしても、本質的には if let x = x { x.func() }
と同じ事が起こってるのではないかなあopenDialog { dialog in // ここ }
// ここ
でセットアップした内容にディスパッチさせるときはどうするのっていう前提で話してたけどself: App
のイベントハンドラなりなんなりに繋ぎこめば!
は出てきそう。EventEmitter
とか Rx.Subject
にイベントを転送して、ハンドラをひっかける接続点を作る必要があるね。.rx
で 接続点がぶら下がってるのはそう考えると便利だな。!
で殺す側じゃなくて if let
とか ?.
で回避した場合のエンバグと等価な形。if let
で回避しているよりは、 コードとしての局所性が意味の局所性と対応していて、クロージャで引っ掛けるほうが絶対良いと思う!
で殺す以前に、局所性が低いからコーディングが難しくてそもそもバグを踏みやすそうな気もしてきたfunc fastUnwrap<T>(_ arg: ImplicitlyUnwrappedOptional<T>) -> Optional<T> { switch arg { case .some(let wrapped): return .some(wrapped) case .none: return .none } } var fuga1: Int! = 1 var piyo1: Int! = 1 struct A { var fuga: Int? var piyo: Int? } let hoge: [A] = [ A(fuga: fastUnwrap(fuga1), piyo: fastUnwrap(piyo1)), A(fuga: fastUnwrap(fuga1), piyo: fastUnwrap(piyo1)), A(fuga: fastUnwrap(fuga1), piyo: fastUnwrap(piyo1)), A(fuga: fastUnwrap(fuga1), piyo: fastUnwrap(piyo1)), A(fuga: fastUnwrap(fuga1), piyo: fastUnwrap(piyo1)), A(fuga: fastUnwrap(fuga1), piyo: fastUnwrap(piyo1)) ]
ImplicitlyUnwrappedOptional
これ直接使う発想なかったfuga.fastUnwrap()
このコードだと、fugaのほうが先に型が決定して、fastUnwarpを探しに行くんだけど この時にInt!として解釈してくれない。fastUnwrap(fuga)
これだと、引数がIUO<T>に束縛出来るし、返り値からT==Intが決定できるので、引数がInt!として決定できる+
みたいな演算子のオペランドとして扱われる前に、 T
か T?
のどちらかへのキャストが強制で入るんじゃない?!
型を推論で伝搬できたT
へのキャストを試して、コンパイルできなかったら、 T?
へのキャストを試す!
をたくさん含む式があると、倍々に探索時間が増えてるんじゃないかなT?
で通って、 T
で 通らない ことを確定しないとT!
から仮定された T
は T?
にさらに暗黙キャストされないって規則もあれば筋が通りそう。canBeUpcastToOptional: Bool
みたいな。 (edited)T!
から 仮定する T
を生成する時にはそれを true にしとく。T
と 仮定 T?
どっちかしか通らない事を保証する必要があるなら// Kotlin fun List<Int>.sum(): Int { return this.fold(0) { a, b -> a + b } } fun List<Double>.sum(): Double { return this.fold(0.0) { a, b -> a + b } }
// Kotlin fun List<Int>.square(): List<Int> { return this.map { it * it } } fun List<Double>.square(): List<Double> { return this.map { it * it } }
~`^_|
あたりも読み方知ったのは随分後な気がする。1位 XYZ色空間に迫る(1) by Ushio (191いいね) 2位 new!JSなんてもう怖くない!JavaScript/ES2015速習ガイド by niba1122 (157いいね) 3位 new!滝沢カレンの理解不能な文章を言語解析してみた。 by naoyu822 (144いいね) 4位 new!Pull Requestに潜むタイポを自動的に検出し、修正を代行するBot by icoxfog417 (142いいね) 5位 new!インタフェースと型クラス、どちらでもできること・どちらかでしかできないこと by koher (117いいね) 6位 最強のWikiと呼び声の高い「Crowi」を、更に最強にした話 by yuki-takei (105いいね) 7位 new!Git、GitHubを教える時に使いたい資料まとめ by yuyakato (97いいね) 8位 JavaプログラマがKotlinでつまづきがちなところ by koher (89いいね) 9位 おじさんが若者たちにモテるためのモダンなHTML/CSSマークアップ by kyoyababa (87いいね) 10位 Pythonのテキスト作りました by KatsunoriNakamura (82いいね) [PR] 社内wikiの更新が止まっている方へ Qiita:Team-ドキュメントを軸にした、プロダクト開発チームのためのサービス 10位 ゲームアプリの「ドット絵」をディープラーニングで自動生成する by shu223 (82いいね) 12位 new!2017年度版 細かすぎて伝わらないJavaScriptの速度の話 by gctoyo (76いいね) 13位 new!TwitterそっくりなMastodonクライアントを作った。Webクライアント制作でハマったことなど by N_ee_t (72いいね) 14位 new!JavaプログラマがKotlinで便利だと感じること by koher (68いいね) 15位 JavaプログラマのためのKotlin入門 by koher (61いいね) 16位 new!デジタルサイネージを作ったので学んだことを晒してみる Part.1 by Akoarum_K (60いいね) 17位 Docker で使えるデータベースの Web GUI まとめ by yamitzky (59いいね) 18位 new!GitHubと連携する新しいアプリの形:GitHub Appsの作り方 by icoxfog417 (55いいね) 19位 new!XYZ色空間に迫る(2) by Ushio (54いいね) 20位 new!Webサービスのフロント側の基本的な確認観点を列挙してみる。 by gctoyo (51いいね)
guard let `self` = self else { return }
って、selfをクォートするので、特殊だけどOptional
かどうかってこと? Self?
から Self
になる って言ったほうがよかった。guard
によって循環参照が生まれうるかという質問なのかと思ったので。self?.hoge()
の hoge() の呼び出し中にweak self
は var self: Self?
にそのクロージャが実行される瞬間に値が代入されるようなものと捉えれば良いと。クロージャ実行の瞬間までに対象が deinit
されてれば nil
が入る。weak self
の self
が参照を保持しているから開放されることはない。self?.
のたびじゃないですかねguard let self = self
を書きましょうという事でclass A { } var a: A = A() func dealloc() { a = A() } let weakClosure = { [weak a] in print(a) // A dealloc() print(a) // nil } weakClosure()
guard let a = a
これがretain countを増やしていて、増やすまではクロージャの中で消えるかもしれないclass A { } var a: A = A() extension A { func deallocSelf() { a = A() print(self) // A } } let weakClosure = { [weak a] in print(a) // A a?.deallocSelf() print(a) // nil } weakClosure()
そもそもメソッド実行中に消えたら世界が壊れますねwクロージャーでつかうweak selfをguard letでアンラップした変数はweak selfでしょうか?それともstrong selfなのでしょうか?
については、「 strong self 」の意図次第で、 guard let foo = self
の foo
は強参照だけど、それがキャプチャされてるわけではないので循環参照の心配はないですよ、と。 (edited)guard let `self` = self
のことは言ってない気がする・・・。guard let foo = self
でアンラップした瞬間に参照カウントが一つ増え、 foo
が消えた瞬間(遅くともクロージャを抜ける前)に解放されて参照カウントが一つ減ります。guard let
self = self else { return }
はコンパイラのバグだから避けた方がいう話はありますよね。 https://github.com/apple/swift-evolution/blob/master/proposals/0079-upgrade-self-from-weak-to-strong.mdguard unwrap x else {}
これ実装して欲しいguard unwrap
はMLで誰かが言ってたやつthiz
とか clazz
とかだった気がする。typ
も使ったことある気がしてきた。type
を置き換える必要があるの??let type = 42 type(of: type) // Int
stride
があったらstride()
が呼べないとかあったようなtype(of:)
が特殊だからじゃない?type(of:)
は Swift3 では パースの段階で特別扱いだったのですが、 Swift4 では タイプチェック時に特別扱いということになったので、 4 だと Swift.type(of: )
にする必要があります。type
をシャドーイングしている箇所があったら、マイグレーターが面倒みてくれるはず。let type = 42 type(of: type) // error: cannot call value of non-function type 'Int'