func hoge<Foo: Protocol>(foo: Foo)と、fucn (foo: Protocol) だとstruct API { private init() { } struct Request { private init() { } struct GetDayOfWeekStories: APIRequest { (edited)case なし enum だとどうやってもインスタンス化できないので、 private init 書く必要ないから いいんじゃないかと思ってます。private init() { fatalError() }くらいにした方がいいかなと思ってました)/// Namespace for diagnostics enum diag {} extension diag { // メンバー群 ... 実際にはすべてのメンバーを extension に実装することにより、 case を書けなくするということをやっています。 (edited)??って、もしかしてコンパイルすごい遅いんでしょうか func apiErrorWithPromise(_ errorMsg: String? = nil, _ httpNumber: Int? = nil) -> Promise<Void>{ let errorMessage = "エラーメッセージ:\n"+(errorMsg ?? "不明なエラー(iMast)")+" ("+String(httpNumber ?? -1)+")\n\nエラーメッセージに従っても解決しない場合は、アプリを再起動してみてください。" return alertWithPromise( title: "APIエラー", message: errorMessage ) }var errorMessage:String = "" errorMessage = "エラーメッセージ:\n" errorMessage += errorMsg ?? "不明なエラー(iMast)" errorMessage += " (" errorMessage += String(httpNumber ?? -1) errorMessage += ")\n\nエラーメッセージに従っても解決しない場合は、アプリを再起動してみてください。" のようにしたら早くなりました、ありがとうございます\()どうも個人的に読みにくいんですよねlet errorMessage に +で連結して代入 let errorMsg2 = errorMsg ?? "不明なエラー(iMast)" let httpNumber2 = httpNumber ?? -1String.localizedStringWithFormat("", a, b) ) 今回の場合、これだけで速くなりそう。 (edited) typealias DataSearchFlags : oneof { None, Backward, Anchored }[default: ] を指定するのは、値の存在が保証されてない場面では??dict[key]! += 1 ってできたっけ?dict[key] += 1 ができるかどうかはわからないけど、 それができないからといってdict[key, default: never()] += 1 こう?dict[key, default: undefined()] += 1 var x: [String: Int] = [:] x["aaa"] = 3 x["aaa"]! += 1 print(x["aaa"])Optional(4)! 演算子はオペランドが左辺値の場合、左辺値のままにしてくれるのか。dict[key]! += 1 で良いってことになるのか・・・?dict[key] ?? defaultValue += 1dict[key] ||= 3 rubyだとこういうのよく見る (edited)func doubleQuestion( left: (read: ()->T?, write: (T)->Void), right: (read: ()->T, write: (T)->Void) ) -> (read: () -> T, write: (T) -> Void) (edited)Neverがボトムになれba まどろっこしい関数用意しなくて良くなるんだがな これおもしろいですね。dict[key, default: fatalError()] += 1 (edited)Never がボトムタイプでない現状だと、 func never<T>(_ message: String = "") -> T { fatalError(message) } みたいなのがいると。Never がボトムタイプにならないのって誰も Proposal 書かないから?An uninhabited type can be seen as a subtype of any other type ... This can be considered as a separate proposal.enum Never {} がボトムってどうなの?とか、他の enum Foo {} はどうなるの?とか、色々ややこしいから後回しにされてるのでは。+1 みたいなリプライあるけどwsomeFunc(AnyProtocol, parameter...) 的なのを考えてたんですが型で判別できるから、ありかどうかで迷ってる感じですdownload は Alamofire.download ですよね 正式にはSwift.min ですdownloadでアクセスできるので 結局そこがどうなのかって話なわけですよねcom.omochimetaru.Alamofire.download とかなってシンドイけど Alamofire.download ならまあ別に平気だし、だいたいは引数の型でも区別可能だし。download が出てきてごちゃごちゃしてきたときはfunc alamofireDownload() { .. } とかを自作してラップするのが良いんじゃないでしょうかimport ... as ... 的なやつですかprotocol APIRequestable { func load<R: Request>(request: R) -> R.Response } って感じですかね?requests<R: Request>(adapter: RequestAdapter=DefaultRequestAdapter()) -> (request: R) -> R.Response みたいにしようかで悩んでました (edited)swiftcが生成したhello_world.bcのターゲットがx86_64-apple-macosx10.9になってるからダメだよ、となってる。swiftcでtargetがasmjs-unknown-emscriptenな.bcを生成できないとダメなんじゃないかな。emscriptenのissueには「asmjs-unknown-emscriptenはWebAssembly(wasm32)とほぼ同じだよね?」って話してる人がいて、同じ人がSwiftをWebAssemblyへクロスコンパイルする話題をswift-devに投げてる。 https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20170626/004860.html (edited)Promise みたいに非同期処理とエラー処理をまとめて扱うような設計が嫌いで、非同期処理なら非同期処理、エラー処理ならエラー処理と責務を分解しておくべきだと考えて、エラー処理を含まない Promise ↓を作ってました。 https://github.com/koher/PromiseK/tree/dev-3.0Promise と Result が対応してるなと思って、それらを throws, try と (edited)async, await に対応させれば、自由にまぜて使えるよなぁと考えたものです。Promise にエラー処理を担当させちゃうと、 catch 忘れがおこっちゃうんですよねぇ。Promise と Result を一緒に使うとモナドパズルになっちゃうんですよねぇ。Result<Promise<Result<Foo>>> を Promise<Result<Foo>> にしたいとか。Array<Promise<Result<Foo>>> を Primise<Result<Array<Foo>>> にしたいとか。let a: Promise<Int> = ... let b: Promise<() throws -> Int> = a.map { try foo($0) } みたいに、 map 等の中で throw される場合は戻り値の型パラメータを () throws -> Foo に変換する API を考えてます。async, await ができれば無用の長物ですが。typealias Promise<Value> = (@escaping (Value) -> ()) -> () とする Promisure (= Promise + Closure) というライブラリも作ってましたw// Wrapping let a: Promise<Int> = { $0(3) } // like `Promise.resolve(3)` in JS // Promisifying a callback let b: Promise<Int> = promise { resolve in // Gets 5 after 1.0 seconds DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { resolve({ $0(5) }) } } // Operators let sum: Promise<Int> = a >>- { a in b >>- { b in { $0(a + b) } } } // flatMap let square: Promise<Int> = { $0 * $0 } <^> a // map let vector: Promise<Vector2> = curry(Vector2.init) <^> { $0(2.0) } <*> { $0(3.0) } // applyObservable にエラーが組み込まれてるのも僕は好みじゃないんですが、どうにかならないものでしょうか。throws, try みたいな特殊構文用意するよりも、モナドに対して do 記法用意するとかの方が汎用性はありますよねぇ。Result と Promise なら Promise が外側にいてほしいとか、モナド感での precedence みたいなものが考えられる気がして、Monad 型に対して演算子みたいな precedence を指定できてsort 関数みたいに、それを使って入れ子を関数が解決する。let a: Result<Promise<Int>> = ... let b: Promise<Result<Int>> = magic(a) do { let c: Int <-- b // 多段アンラップ let d: Result<Int> <- b // 一段アンラップ }try とかキーワード足さなくても自作モナドを組み込みモナドと同じように便利に使える。then が map と flatMap になってるんですけど、ネストしてくると読みづらいんですよねぇ・・・。Result を作らなかったから thorws, try を別の型でラップしたい場合に Promise<() throws -> Int> とかなるのはちょっとつらいですよね。Observable とかでやろうとしたらできないですよね?=> レベルだと演算子の方が可読性高そうだけど。Any でもダメで、任意の型パラじゃないといけないから辛い・・・extension Any { func `let`<T>(_ f: (Any) -> (T)) -> T { ... } }Any になっちゃってSelf にする extension ってできるんだっけ?public func =><T, U>(lhs: T, rhs: (T) throws -> U) rethrows -> U { return try rhs(lhs) }class Animal {} class Cat : Animal { func nya() { print("nyaa") } } extension Animal { func exec(f: (Self) -> Void) { f(self) } } let cat = Cat() cat.exec { $0.nya() } error: TempGround.playground:11:12: error: value of type 'Animal' has no member 'nya' cat.exec { $0.nya() } ^~ ~~~extension SomeProtocol where Self: SomeClass {} (edited)extension Any where Self: SomeClass {}protocol Anything {} extension Anything { func `let`<T>(_ f: (Self) throws -> T) rethrows -> T { return try f(self) } } extension Double: Anything {} (42.0).`let` { $0 + 1.0 / $0 }protocol Proto {} class Cat : Proto { func nya() { print("nyaa") } } extension Proto { func exec2(f: (Self) -> Void) { f(self) } } let cat = Cat() cat.exec2 { $0.nya() }=> の議論からするとそれは問題ないのでは=> の実装をオペレータからメソッドにできるかどうかだけを今考えていてAny が nominal でないってことだけなわけだ。Self を f に渡す形で実装はできる。Any じゃなくてLettable という protocol のメソッドとして作って.let を使いたい型については extension Cat : Lettable {} => の方がいいと思う。<$> は順番が逆転しちゃう問題もありますしねぇ・・・Promise のチェーンはpromise.flatMap { ... }.flatMap { ... }.flatMap { ... }primise >>- { ... } >>- { ... } >>- { ... }=> は標準ライブラリに入れてほしい・・・。r''' 出せなかったし嘘だと思うr''' は正規表現じゃなくて生マルチライン文字列Swift >>- で検索したら、一つ目は https://www.apple.com/jp/swift/ だけど、二つ目は typelift/Operadics で、三つ目は thoughtbot/Runes だった。<^> も駄目っぽいですよ>>= は重複してるから >>- に、 <$> は言語仕様上の制約で <^> になってる。haskell <$> は https://stackoverflow.com/questions/37286376/what-does-mean-in-haskell が出たからEither<T, Either<U, V>>public enum Either2<A, B> { case a(A) case b(B) } public protocol Either2Convertible { associatedtype CaseA associatedtype CaseB var asEither: Either2<CaseA, CaseB> { get } } extension Either2: Either2Convertible { public var asEither: Either2 { return self } }enum の抽象化ってことは、 Either2<Int, String> と Either2<String, Int> は区別したいってことですよね?Enum2, Enum2Convertible は良さそうEnum1 と Enum0 もいらないですか? Box と NeverEnum3 とかだと CaseA より Case1 とかの方がよさそうenum Enum2<T0, T1> { case Case0(T0) case Case1(T1) }EnumN とか?Houyhnhnm 音節Hou・yhn・hnm 発音記号/hwínəm|húːɪ‐/ 名詞可算名詞 フーイナム 《Swift 作 Gulliver's Travels (ガリバー旅行記)の中の人間的な理性が徹底している馬; 人間の形をした Yahooを支配する》. [馬の鳴き声からのSwiftの造語]swift package init したときに面倒$ swift package init --help OVERVIEW: Initialize a new package OPTIONS: --type empty|library|executable|system-moduleYahoo!の名前の由来は英語の「Yet Another Hierarchical Officious Oracle」(さらにもう一つの階層的でお節介な神託)の略だといわれている[57]。また、ファイロとヤンは自分たちのことを「ならずもの」だと考えているので、「粗野な人」という意味がある「Yahoo」(『ガリヴァー旅行記』に登場する野獣の名前が由来)という言葉を選んだと主張している[10]。さらに感嘆符が付いていることに関しては「ヤッホー!」「やったー!」を意味する英語の感動詞「yahoo」と掛けているとも考えられる。EnumNConvertible を EnumN に convert するんじゃないんですか?CustomStringConvertible とかを考えても EnumNConvertible とかならおかしくない気も。$ gyb -D Key=Value でパラメータ渡せるから、できるよpublic func animatedItems<S: AnimatableSectionModelType, O: ObservableType, C0: Reusable, C1: Reusable, C2: Reusable, C3: Reusable, C4: Reusable>(for type0: C0.Type, _ type1: C1.Type, _ type2: C2.Type, _ type3: C3.Type, _ type4: C4.Type) -> (O) -> Disposable where C0: UICollectionViewCell , C1: UICollectionViewCell , C2: UICollectionViewCell , C3: UICollectionViewCell , C4: UICollectionViewCell , S.Item: Enum5Convertible , S.Item.T0 == C0.Dependency , S.Item.T1 == C1.Dependency , S.Item.T2 == C2.Dependency , S.Item.T3 == C3.Dependency , S.Item.T4 == C4.Dependency , O.E == [S] { 使う側がこんな感じの地獄じみた形相になってるから、任意個数サポートできるのはもはや必須の感じがするdataSourceObservable .bind(to: tableView.rx.animatedItems(for: MyCell1.self, MyCell2.self)) .disposed(by: disposeBag)curry は昔ジェネリック引数14個(?)でコンパイル終わらなくなる問題がありましたが大丈夫そうですか?--line-directive= 入れないと ###sourceLocation が各行入るからなんなのかと思った!! オペレータ。機能は ! と同じ。Codableを適用すると、encode/decodeを実現するための実装をコンパイラーが生...struct ObservableA<T> { func subscribe(onNext:(T) -> () = { _ in }) { } } ObservableA<(Int, Int)>().subscribe(onNext: { (a, b) in // ok }) struct ObservableB<T> { func subscribe(onNext:((T) -> ())? = nil) { } } ObservableB<(Int, Int)>().subscribe(onNext: { (a, b) in // 死ーん })[omochi@omochi-iMac bin]$ pwd /Users/omochi/work/swift-source/build/Ninja-RelWithDebInfoAssert/swift-macosx-x86_64/bin [omochi@omochi-iMac bin]$ ./swift --version Swift version 4.0-dev (LLVM a15decabe3, Clang 60a12bf739, Swift fcd389b17e) Target: x86_64-apple-macosx10.9XCTestにXFAIL欲しいlitはテキストファイルならなんでも良いので、.mdにテストを書いたりできるのが面白いと思った。 https://github.com/apple/swift-integration-tests/blob/master/swift-package-init-exec.mdlit.cfg で指定すればですね。 https://github.com/apple/swift-integration-tests/blob/master/lit.cfg#L56XCTAssertEqualWithAcuracyはフィールドごとに確認するので増えるほど書くのがきつくなる stcuct Hoge { val a: Float } let x = Hoge(a: 0) let y = Hoge(a: 0) XCTAssertEqualWithAcuracy(x, y, accuracy: 1e-10) かといって関数に切り出すとXCodeで停止地点が分かりづらくなる。 XCTAsserEqualはEquatableを実装するだけで使えるので 同様にNealyEquatableみたいなプロトコルを切ってXCTestがそれを使うXCTAssertEqualWithAcuracyを用意してくれるのがベストかな。swift testとかで結構密接に結びついてるのでこちらからどうこうもしにくい気が。かといって関数に切り出すとXCodeで停止地点が分かりづらくなる。 切り出した関数に…file: StaticString = #file, line: UInt = #line)とかつけると良いのでは。QuickSpec が(間接的に) XCTestCase を継承してるのか。 https://github.com/Quick/Quick/blob/cd89737d3d5306124e91c357b66cde274a3269b4/Sources/Quick/QuickSpec.swift#L13swift testもできるのかな?swift testPackage.swiftはdependenciesがなんか複雑になってますね……Quick を使いたいからじゃない? < 複雑XCTestCase を継承してる https://github.com/Quick/Quick/blob/cd89737d3d5306124e91c357b66cde274a3269b4/Sources/QuickSpecBase/include/QuickSpecBase.h#L8testDependenciesがなかったので、テストの時だけ使う依存を実現してる。testDependencies 見た気がしてたんだけど使えなくなってるのか・・・Remove testDependencies from PackageDescription This feature was supposed to support dependencies only for the root package but at some point it stopped working however the API still remained open. This patch removes the public API. This is a valid and desired feature which is supposed to come back after it goes through proper review on swift evolution.
https://github.com/apple/swift-package-manager/commit/34b7826cb586b0769ea5f60a7718d7de599ce27fPackage.swiftを用意してたけど、環境変数で切り替えられることをikesyoさんに伝えたら使ってくれた。 (edited)Package の dependencies がテストからも使えるのなんか変な気も。> SWIFTPM_TEST_Carthage ああこれはSPMが定義してくれるのか。 Makefileで実行するときに設定してます。 https://github.com/Carthage/Carthage/blob/master/Makefile#L82Package.swiftがサンドボックス内で解釈される際に、SwiftPMがあえて環境変数を引き継ぐ様にしてるので、あながち間違いでもない。$ which -a sandbox-exec /usr/bin/sandbox-execDESCRIPTION The sandbox-exec command is DEPRECATED. Developers who wish to sandbox an app should instead adopt the App Sandbox feature described in the App Sandbox Design Guide.sandbox-execを使う様にしたコミットには環境変数がらみが特に書かれてないぽいから「環境変数をあえて渡す」というのは、チャットの中だけの話だったかも。#lineを使うってこれのことですか。 http://masilotti.com/xctest-helpers/ そもそもrecordFailureの存在を知らなくてログに行番号出るだけじゃ分かりにくいとか思っていました。XCTAssert*()シリーズにも渡せます。XCTAssert*()シリーズに渡せるってのは何でしょう? recordFailureがXCTestCaseのメソッドなのでXCTAssert*()のようにトップレベルのを定義するにはデフォルト引数で呼び出し元のselfを渡すとかするのかなぁと思ったのですが。selfを渡す話をよく覚えていない……XCTestCaseは引数にないのでどこから渡っているのか謎。 別の仕組みになっているんだろうか。recordFailureはXCTestCaseのメソッドなんですよ。 で、XCTAssert*()はトップレベルなのでrecordFailureが使えない(はず)XCTestCaseのextensionにすればいいんですが XCTAssert*()と同名を用いると例のバグ?でトップレベルのほうが見えなくなる。 (edited)recordFailure() ではなく XCTFail() を使ってました。 https://github.com/realm/SwiftLint/blob/master/Tests/SwiftLintFrameworkTests/IntegrationTests.swift#L35recordFailureを使うんじゃなくて内部でfile, line指定付きのXCTAssert*()を使えってことですね。 間違った方向に進んでました。enum Foo { static var foo: Foo { fatalError() } } func bar(_ foo: @autoclosure () -> Foo, ....) { ... } bar(.foo, ....) これが可能になるFoo.foo が実際には生成されないのがポイント?delegate.scrollView(scrollView, .didScroll) とかにいいかも (edited)struct Foo {} let foo = Foo() func bar(foo: Foo, ....) { ... } bar(foo, ....) そもそもこれじゃ駄目な理由は?struct Foo { static var foo = Foo() } ならまあ差はそれほど無いのかもしれない。.foo で書けるねstruct BarOverloads { static let foo = BarFoo() static let poo = BarPoo() } func bar(_ overload: BarFoo, ...) func bar(_ overload: BarPoo, ...) bar(.foo, ...) // できない bar(.poo, ...) (edited)struct Bar { struct Foo { static let foo = Foo() } struct Poo { static let poo = Poo() } } func bar(_ overload: Bar.Foo, ...) func bar(_ overload: Bar.Poo, ...) bar(.foo, ...) bar(.poo, ...) (edited)\ を使う感じで。 https://github.com/apple/swift-evolution/blob/master/proposals/0182-newline-escape-in-strings.md (edited)let s = """ ... In Windows you have paths like C:\ ... """\ を \\ に直さないといけないけど、新使用だとコンパイルエラーにならないから問題だと。特に """ だからといって文字列コピペしてきたときとかに問題起こりそう。c:\news とかもそうなんで。ちょっと弱い。Optionalのclosureでtupleが分解できない問題治してもらえた。はやいw
swift-4.0-DEVELOPMENT-SNAPSHOT-2017-07-11-a以降で直ってるぽいですね。struct でもサイズが大きいと勝手に最適化されたりするんでしょうか?どこかで触れられてましたっけ? https://developer.apple.com/videos/play/wwdc2017/402/std::string は確か COW だったけど COW 止めたんよね?Array 等の場合はマルチスレッドをサポートしないことで問題を回避している??var a = [2, 3, 5, 7] // スレッドA a[2] = 4 print(a) // スレッドB a[3] = 8 print(a) (edited)startThread( closure: () -> Void ) var a = [2, 3, 5, 7] a[2] = 4 startThread { a[3] = 8 }func startThread(f: @escaping () -> Void) { f() } func main() { var a = [2, 3, 5] a[0] = 88 startThread { a[1] = 99 } print(a) // [88, 99, 5] } main()struct である Array に包まれてるからvar a = 2 let foo: () -> () = { a += 1 } foo() print(a) // 3@escaping が@nonescaping なときはキャプチャされていてもvar a = 42 if random() < 0.0001 { foo = { print(a) } }foo がエスケープしてないからならない (edited)aはスタック上には無いと思いますvar foo: () -> () = {} func bar() { var a = 42 if random() < 0.0001 { foo = { print(a) } } } for _ in 1...10000000 { bar() }bar のコールのほとんどではスタックで済ませられるはずだけど、a[0] = 99 に、バッファストレージインスタンスの参照カウンタを見て、1ならそのまま書き換える、2以上ならディープコピーする、だから・・・a のスコープ自体がヒープに確保されてるから a のバッファへの参照カウントは常に 1 になりそう。 var a = [2, 3, 5, 7] // スレッドA startThread { a[2] = 4 print(a) } // スレッドB startThread { a[3] = 8 print(a) }a の実体が1つだけあってa[2] = 4 とかを、ユーザ側で ロックしないとバグりそう?a の実体が消えて、その先のストレージも消える。Array がスレッドアンセーフなのと、 COW がスレッドセーフかどうかと、参照カウンタがスレッドセーフなことは独立な気がする。Array がスレッドアンセーフな時点で Array の COW もスレッドセーフである必要はない?それとも、 Array がスレッドアンセーフな時点で Array の COW もスレッドセーフである必要はない? これがYESだと思います。Array 自体がスレッドアンセーフな時点で、 ArrayのCOWだけのスレッドセーフティーを考える意味がなくて、それもアンセーフArray のCOWに同期のオーバーヘッドはないと。std::string 自体はスレッドセーフじゃないと思うんだよなあArray をロックして使ってれっば問題は起こらない気がする。std::string が COW でなくなったのは別の理由なのかな?std::string と COW だった頃の std::string はまた別かもしれない・・・std::thread が入るときにこの規格がちゃんと整理されたって話がこの記事に同時に書いてあるのでstd::string としては、2つに見えてるんだ。ユーザには。std::string 一個単位で readonly safe ってことしか聞いてないから (というかコピーをまたいだグループでロックを取るなんで不可能)Array の COW はスレッドアンセーフでいい話と矛盾してない?var a = [2, 3, 5] // スレッドA a[2] = 4 // スレッドB var b = a b[2] = 999a と b で同期とるとか無理でしょってことか。var a = [2, 3, 5] // スレッドA startThread { a[2] = 4 } // スレッドB startThread { var b = a b[2] = 999 }Array 自体はスレッドアンセーフでも COW はスレッドセーフでないといけないってこと?a[2] = 4 と var b = a の2行を、ユーザがロックすべきだと思う。b = a の代入の最中に、 a[2] = 4 の処理が走り始めて内部状態が壊れる可能性があるはず。a[2] = 4 が書き込み操作で、 b = a の右辺はreadだから、競合してるのでロックが要るって事になるはず (edited)int の書き込みは atomic で同時なんてないんじゃないの? Q4. 基本型intはスレッドセーフですか? A4. 「同時アクセスが全て読み込み操作であれば安全」というスレッドセーフ性レベルが保証される。
http://yohhoy.hatenablog.jp/entry/2013/12/15/204116// 同一変数に対して片方が変更操作 int y = 2; void th1() { int r2 = y; // NG: データ競合 } void th2() { y = 42; // NG: データ競合 }th1 と th2 の中でロックしてても不定じゃない?struct Counter { var count = 0 mutating func countUp() { count += 1 } mutating func reset() { count = 0 } } (edited)structの場合CoWで実体分かれて問題ないんではreset の write の方struct だからといって CoW は自動的には起こりません。// 同一変数に対して片方が変更操作 int y = 2; void th1() { int r2 = y; // NG: データ競合 } void th2() { y = 42; // NG: データ競合 }int y = 2; void th1() { y = 99; } void th2() { y = 42; } の代入が atomic なら↑も OK となりそうだけど・・・。int の代入は atomic なのかint の代入がatomicでないから、ってことやんね?疑問は二つで、 - C++ において int の代入は atomic なのか - atomic だと仮定して↑はスレッドセーフなのかint にたいしてどれが適用されるかよくわからない。long と double 以外のプリミティブや参照の読み書きは atomic っぽいから、 int を同時に読み書きすること自体には問題なさそう。 For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write. Writes and reads of volatile long and double values are always atomic. Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.
http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.htmlint の読み書きが atomic かどうかを調べて atomic だと知って安心した記憶があるんだけど、 Java の話だったのかなぁ。その感覚で int の読み書きを atomic だと思っていたから↓がおかしいんじゃないかと思ったけど、 // 同一変数に対して片方が変更操作 int y = 2; void th1() { int r2 = y; // NG: データ競合 } void th2() { y = 42; // NG: データ競合 } C++ では規格上 atomic でないからたとえそれを atomic に行う CPU 向けにコンパイルしたとしてもどのように最適化されるかわからず未定義動作なので↑は正しい、と。var a = 3 var b = 2 a = 4 b = 1 print("a=\(a), b=\(b)") (edited)Int 等の代入や、参照型のアドレスの代入が atomic なのか気になる。a = 3 や b = 2 の時間帯は削除されるんじゃないかなあ。Int やアドレスの代入が atomic でないなら、結構気を付けてプログラム書かないといけないなぁInt の read / write ですら atomic ではない?.swift か。Int じゃ駄目 (edited)Int であってもlet a = _stdlib_AtomicInt(42)let a = _stdlib_AtomicInt(42) print(a.load()) // 42 a.store(999) print(a.load()) // 999_stdlib_AtomicInt とかも atomic であるところまでの保証であって「「Intの代入がatomic」だとしても」は同じじゃないの?var x = 3 x = 2func a() -> Int { var a = 3 a = 2 return a }func a の例で言うなら、これってfunc a() -> Int { return 2 } と最適化されるかもしれないfunc a(x: inout Int) -> Int { x = 3 x = 2 return x } (edited)func a(x: inout Int) -> Int { return 2 } (edited)std::atomic<int> に対してはstore 命令の削除も禁止されるはず。x → a だったら inout だから x への代入は必須じゃない?func a(x: inout Int) -> Int { x = 2 return 2 } (edited)x = 3 の瞬間が削除されていることとreturn x じゃなくて return 2 になっていることがポイントx=3 が観測できないし、 どんだけ x に書き込んでも、 固定で 2 が返ってくるx = 3 が削除されるのは問題になりうる。a が atomic な挙動をしているだけだと思うんだけど、 (edited)int data = 0; volatile int flag = 0; // 生産側スレッド void producer_thread() { data = 42; // [A] flag = 1; // [B] ??? } // 消費側スレッド void consumer_thread() { while ( !flag ) {} // [C] assert(data == 42); // [D] ??? } (edited)func a() { lock.sync { atomicFoo(42) } } func b() { lock.sync { atomicFoo(999) } } の lock はいらないよね?ということでdata を読んだ時に、0か42以外の中途半端にビットが書き換わった変な数字になったり、CPUがぶっ壊れたりしない、としてもfunc a() { lock.sync { atomicFoo(42) } } func b() { lock.sync { atomicFoo(999) } } これ自体はlockはいらない。Int を同時に更新する(だけ)みたいなのでも同期が必要となると想定していないケースが多そうということです。lock が不要だったらうれしい。 var x: Int = 42 func a() { lock.sync { x = 999 } } func b() { lock.sync { x = 888 } } (edited)let x = LargeSizeValue() f1(x) f2(x) f3(x)let だからそのまま渡せるのかfunc consume1(_ b: BigStruct) { consume2(b) } func consume2(_ b: BigStruct) { consume3(b) } func consume3(_ b: BigStruct) { consume4(b) } func consume4(_ b: BigStruct) { print(b) } 極端だけどこういう場合。 (edited)func consume1(_ b: P) { consume2(b) } func consume2(_ b: P) { consume3(b) } func consume3(_ b: P) { consume4(b) } func consume4(_ b: P) { print(b) } extension BigStruct: P {} こうしたほうが速そう。結局のところ Swift4 の Existential CoW はヒープに 25 バイト以上のデカい構造体を alloc/initialize/dealloc するより参照カウンタ操作の方が速いってだけなのかな? は Swift 3 vs Swift 4 の話ではない??func consume1<T: P>(_ b: T) { consume2(b) } func consume2<T: P>(_ b: T) { consume3(b) } func consume3<T: P>(_ b: T) { consume4(b) } func consume4<T: P>(_ b: T) { print(b) } extension BigStruct: P {}// 1.swift protocol Hogeable { func hoge() -> Int } struct HogeCat: Hogeable { func hoge() -> Int { return 1111 } } func callHogeableHoge(hogeable: Hogeable) -> Int { return hogeable.hoge() } func callCatHoge(cat: HogeCat) -> Int { return callHogeableHoge(cat) } print(callCatHoge(HogeCat()))callHogeableHoge nofunc foo(_ a: P, _ b: P) { ... } extension Int: P {} extension String: P {} foo(2, 3) // スペシャライズされる foo(2, "abc") // スペシャライズされない@_specialize 付けなくてもスペシャライズって起こるんだっけ?func consume1(_ b: P) { consume2(b) } func consume2(_ b: P) { consume3(b) } func consume3(_ b: P) { consume4(b) } func consume4(_ b: P) { print(b) } extension BigStruct: P {} こうしたほうが速そう。 ↑これでいけそうですfunc consume1(_ b: shared BigStruct) { } void consume1(const BigStruct & b) と同じ意味func consume1(_ b: inout BigStruct) { consume2(&b) } func consume2(_ b: inout BigStruct) { consume3(&b) } func consume3(_ b: inout BigStruct) { consume4(&b) } func consume4(_ b: inout BigStruct) { print(b) } extension BigStruct: P {} (edited)var x = BigStruct() compose(consume1(&x), consume1(&x))std::atomic で実現されてました。 struct HeapObject に フィールド InlineRefCounts refCounts がある。 https://github.com/apple/swift/blob/b7d78853112c1279fc7bc5b85853779040f13703/stdlib/public/SwiftShims/HeapObject.h InlineRefCounts は RefCounts<InlineRefCountBits> のエイリアス class RefCounts<T> は フィールド std::atomic<T> を持ってる。 デクリメント処理はなんかいろいろあるけど doDecrement が基本的なやつっぽくて、 分岐もいろいろ複雑なんだけどstd::atomicのcompare_exchange_weakを呼び出してたりする。 InlineRefCountBits は RefCountBitsT<RefCountIsInline> のエイリアス RefCountIsInline は true な定数 RefCountBitsTはカウンタに加えて動作に関するビットが5こぐらいくっついたよくわからんやつ。 https://github.com/apple/swift/blob/b7d78853112c1279fc7bc5b85853779040f13703/stdlib/public/SwiftShims/RefCount.hthe-sharing-economy wSwift Static Analysis@Apple Cupertino, CA
https://twitter.com/CodaFi_Math@CMU 2019 どういうこと?未来人??val ( Swift の let に相当)で interface のプロパティ宣言して、具象クラス側で Computed property にできるよね・・・。mutating を一つももたないクラスはイミュータブルクラスになる。 mutable class Foo { func bar() -> Bar {} mutating func baz() -> Baz {} } (edited)mutating を作ろうとするとコンパイルエラー。mutating みたときは、これはもしかして?と思ったけどちょっと違った。けど、結局値型中心で考える方がセンスがいいと思う。pure について言及されてて、 D 言語はよく知らないですが、、 pure な方がデフォルトであるのがいいと思うのと、これを型にも広げられないんだったら効果半減だと思います。let なプロパティを Computed Property としてオーバーライドできないという制約はあるから、「もともと let な stored property だったものを、後から computed property の getter に差し替えても」動くとはいえ意図的に区別して制約が課されてるんじゃないかな?interface A { val value: Int } class A1: A { override val value: Int get() = A1.getCurrent() companion object { var value: Int = 0 fun getCurrent(): Int { value += 1 return value } } } fun main(args : Array<String>) { val a1 = A1() println(a1.value) println(a1.value) }
let in protocols https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170619/037676.htmlprotocol で nested type 作れないのって何か理由があるんですっけ?名前空間的に、その protocol でしか使わない型をネストしたい・・・。protocol Foo { var bar: Bar { get } struct Bar { ... } } みたいな (edited)protocol の内側に static func をかいたとき、それは、 Foo.hoge() と呼び出せるわけじゃなくてFoo に関連したいくつかのパラメータをまとめた Bar を作りたいけど、 Bar は Foo から独立したら意味を持たない型なのでネストしたいって感じです。struct Bar<F: Foo> を作るのが筋良さそうprotocol Foo { typealias Bar = FooBar var a: Bar { get } } struct FooBar { } struct FooImpl: Foo { var a: Foo.Bar }Foo の異なる具象型間で Bar をやりとりできないですよね?_FooBar にしておけばありかもしれないなぁ。 1> protocol Foo { 2. typealias Bar = FooBar 3. var a: Bar { get } 4. } 5. 6. struct FooBar { 7. 8. } 9> let bar: Foo.Bar = Foo.Bar() error: repl.swift:9:27: error: cannot call value of non-function type 'Foo.Bar' (aka 'FooBar') let bar: Foo.Bar = Foo.Bar() ~~~~~~~^~typealias はデフォルトではないのでは?associatedtype にしてデフォルト設定するんじゃないっけ? = で指定しておいた型になるんじゃなかったっけstruct FooBar {} protocol Foo { associatedtype Bar } extension Foo { typealias Bar = FooBar }struct FooBar {} protocol Foo { typealias Bar = FooBar }struct P0Param {} protocol P0 { typealias Param = P0Param var a: Param { get set } } var a = P0.Param() print(a) 1> protocol Foo { 2. typealias Bar = FooBar 3. var a: Bar { get } 4. } 5. 6. struct FooBar { 7. 8. } 9> let bar: Foo.Bar = Foo.Bar()
typealias in protocolswift-4.0-branch-07-11-2017 https://github.com/apple/swift/tree/swift-4.0-branch-07-11-2017 みたいなブランチからビルドされてたぽいだけど、beta 5はどこからビルドされているのだろう? (edited)swift-4.0-branch-07-11-2017 みたいなスナップショットが出ると、discordで報告していて、swift-4.0-DEVELOPMENT-SNAPSHOT-2017-08-02-a以降 swift-4.0-DEVELOPMENT-SNAPSHOT-2017-08-04-aより前 ぽい。 (edited)Copy-On-Write (🐮) types like Array and String are sharable リファレンスカウントとCOWはスレッドセーフだけど Array そのものの操作はスレッドセーフではない?async, await 出す前に来てしまった・・・。Concurrency is a broad and sweeping concept that can cover a wide range of topics. To help scope this down a bit, here are some non-goals for this proposal: - We are focusing on task based concurrency, not data parallelism. This is why we focus on GCD and threads as the baseline, while completely ignoring SIMD vectorization, data parallel for loops, etc. - In the systems programming context, it is important for Swift developers to have low-level opt-in access to something like the C or C++ memory consistency model. This is definitely interesting to push forward, but is orthogonal to this work. - We are not discussing APIs to improve existing concurrency patterns (e.g. atomic integers, better GCD APIs, etc).UIImage(named:) が挙げられてるんだけど、このレベルの API から非同期化するつもりなのかな? C# の世界みたいになりそう。async が良さそう。throws って言ってるのと同じ気がする。can of worms って出てきてなんだ?と思ったら↓のような意味の表現らしい。 UIImage(named:) にまで踏み込むなら、 pure Swift UI ライブラリもワンチャンあるかも?you should only have to teach your types how to serialize/🐟 themselvesfish なんだよなあSpeaking of reliable systems, introducing an actor model is a good opportunity and excuse to introduce a mechanism for handling and partially recovering from runtime failures (like failed force-unwrap operations, out-of-bounds array accesses, etc). We explore several options that are possible to implement and make a recommendation that we think will be a good for for UI and server applications.async / await まで来た。async と、呼び出しの await は (Int) -> Int // #1: Normal function (Int) throws -> Int // #2: Throwing function (Int) async -> Int // #3: Asynchronous function (Int) async throws -> Int // #4: Asynchronous function, can also throw.reasync がなさそうだから swift-evolution に書いておくか。await! もほしいな。! を使うのが良いのか自信がない。 actor TableModel { let mainActor : TheMainActor var theList : [String] = [] { didSet { mainActor.updateTableView(theList) } } init(mainActor: TheMainActor) { self.mainActor = mainActor } // this checks to see if all the entries in the list are capitalized: // if so, it capitalize the string before returning it to encourage // capitalization consistency in the list. func prettify(_ x : String) -> String { // ... details omitted, it just pokes theList directly ... } actor func add(entry: String) { theList.append(prettify(entry)) } } reliable actor Notifier { ... } reliable actor class Notifier { ... } distributed actor MyDistributedCache { ... } distributed actor class MyDistributedCache { ... }func queueHopping() async -> Void { doSomeStuff() await DispatchQueue.main.syncCoroutine() doSomeStuffOnMainThread() await backgroundQueue.asyncCoroutine() doSomeStuffInBackground() }/// Begins an asynchronous coroutine, transferring control to `body` until it /// either suspends itself for the first time with `suspendAsync` or completes, /// at which point `beginAsync` returns. If the async process completes by /// throwing an error before suspending itself, `beginAsync` rethrows the error. func beginAsync(_ body: () async throws -> Void) rethrows -> Void ↑の戻り値ってなんで T じゃないの?@IBAction func buttonDidClick(sender:AnyObject) { // 1 beginAsync { // 2 let image = await processImage() imageView.image = image } // 3 }rethrows はどこで活躍するの?If the async process completes by throwing an error before suspending itself, `beginAsync` rethrows the error.suspendAsync は func suspendAsync<T>( _ body: (_ continuation: @escaping (T) throws -> ()) -> () ) async rethrows -> T じゃないんだ??throws の位置がおかしいかfunc suspendAsync<T>( _ body: (_ continuation: @escaping (T) -> ()) throws -> () ) async rethrows -> T// Legacy callback-based API func getStuff(completion: (Stuff) -> Void) { ... } // Swift wrapper func getStuff() async -> Stuff { return await suspendAsync { continuation in getStuff(completion: continuation) } }asynchronize が間違ってるっぽいな。func suspendAsync<T>( _ body: (_ continuation: @escaping (T) -> ()) -> ()) async -> T func asynchronize(_ operation: ((T) throws -> ()) -> ()) async rethrows -> T // ラベル等を消すと func suspendAsync<T>( _ body: ((T) -> ()) -> ()) async -> T (edited)(T) throws -> () があるけど、() throws -> T じゃないと。func asynchronize(_ operation: ((() throws -> T) -> ()) -> ()) async rethrows -> Tfunc suspendAsync<T>( _ body: (_ continuation: @escaping (() throws -> T) -> ()) -> ()) async -> Treturn await suspendAsync { continuation, error in awaiters.append({ switch $0 { case .error(let e): error(e) case .value(let v): continuation(v) } }) } が return await suspendAsync { continuation in awaiters.append({ switch $0 { case .error(let e): continuation { throw e } case .value(let v): continuation { v } } }) } になる。pass みたい。async await じゃなくて yields と yield にするって選択肢についても書かれてますねasync / await は必ずしも意味が正しくないんよね。async(nonthrowing) を導入するasync(nonthrowing) より async nonthrows とかの方がいいな。 nonthrows は英語的におかしそうだけど。nothorw があるよthrows がよくなかった気がするな。 Java のせいだけど。throwing func とか async func とかの方が英語的によかったかも。 (edited)nonthrowing func だったら nonmutating func とかとも整合するし。do { let a = await foo() let b = await bar(a) ... } waitreasyncawait! もいいけど、まとめてブロックも必要かと。Blocking calls Affordances could be added to better call blocking APIs from async functions and to hard wait for an async function to complete. There are significant tradeoffs and wide open design space to explore here, and none of it is necessary for the base proposal.let a = await foo() let b = await bar() のときに foo と bar を並列に走らせるのか直列に走らせるのかはどうだろう?func processImageData1a() async -> Image { let dataResource = Future { await loadWebResource("dataprofile.txt") } let imageResource = Future { await loadWebResource("imagedata.dat") } // ... other stuff can go here to cover load latency... let imageTmp = await decodeImage(dataResource.get(), imageResource.get()) let imageResult = await dewarpAndCleanupImage(imageTmp) return imageResult }beginAsync していてget() async throws -> T なのでasync/awai に続いて Typed throws も。 Error が existential だからパフォーマンスが、ってことが書かれていて興味深い。One thing that I’m personally very concerned about is in the systems programming domain. Systems code is sort of the classic example of code that is low-level enough and finely specified enough that there are lots of knowable things, including the failure modes. Beyond expressivity though, our current model involves boxing thrown values into an Error existential, something that forces an implicit memory allocation when the value is large. Unless this is fixed, I’m very concerned that we’ll end up with a situation where certain kinds of systems code (i.e., that which cares about real time guarantees) will not be able to use error handling at all.JohnMC has some ideas on how to change code generation for ‘throws’ to avoid this problem, but I don’t understand his ideas enough to know if they are practical and likely to happen or not. で、 Chris Lattner のこのメールに John McCall が返信してるから、それ見たらわかるかも。This combination of requirements means that all operations must be implicitly "unwindable" starting from almost any call site it makes. For the stability of the system, this unwinding process must restore any invariants that might have been temporarily violated; but the compiler cannot assist the programmer in this. The programmer must consciously recognize that an error is possible while an invariant is broken, and they must do this proactively --- that, or track it down when they inevitably forget. This requires thinking quite rigorously about one's code, both to foresee all the error sites and to recognize that an important invariant is in flux. How much of a problem this poses depends quite a lot on the code being written. There are some styles of programming that make it pretty innocuous. For example, a highly functional program which conscientiously kept mutation and side-effects to its outermost loops would naturally have very few points where any invariants were in flux; propagating an error out of an arbitrary place within an operation would simply abandon all the work done up to that point. However, this happy state falls apart quite quickly the more that mutation and other side-effects come into play. Complex mutations cannot be trivially reversed. Packets cannot be unsent. And it would be quite amazing for us to assert that code shouldn't be written that way, understanding nothing else about it. As long as programmers do face these issues, the language has some responsibility to help them.More generally, by modeling both `throws` and `async` as effects on function types, we can eventually provide common abstraction tools to abstract over both effects in protocols and generic code
https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619#rethrows-could-be-generalized-to-support-potentially-async-operationseffects ってのが専門用語を匂わせてる気がするawait try と書いてたけど、プロポーザル通り try await じゃないといけない気がしてきた。try も await も flatMap と等価でモナドを剥がすわけだけど、 async throws は Promise が外側だからまず Promise を剥がさないといけず、その後 Result を剥がすと考えると try await じゃないとおかしい。beginAsync の rethrows と body の throws ってやっぱダメじゃない?I agree. I think `rethorws` for `beginAsync` is problematic. For example, what happens when the `foo` in the following code throws an `Error` asynchronously? func foo() async throws { ... } beginAsync(foo) `foo` is acceptable as `beginAsync`'s `body` by its type. However its error might be thrown asynchronously and it is impossible to rethrow it. So the error must be ignored or treated as an universal error by untyped propagation. It breaks type safety about error handling. So I think the signature of `beginAsync` should be the following one. func beginAsync(_ body: () async -> Void) -> VoidbeginAsync rethrows the error.await! についても違う方向で話されてたから blocking のことに言及してみた。 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170814/039096.htmlasync(nonthrowing) おもしろいけど、それをやっちゃうと throws, async に続く第三のエフェクトを導入したときに整合性をとるのに困ると思う。async/await の Proposal と同じような内容が話されてる。 https://gist.github.com/koher/5cd16adac7a62b6d3eb0b910ccc13534import Accelerate extension Array where Element: Comparable { mutating func clip(low: Element, high: Element) { print("normal version") for i in 0..<self.count { self[i] = Swift.max(Swift.min(self[i], high), low) } } @_specialize(Float) func clipped(low: Element, high: Element) -> [Element] { var ret = self ret.clip(low: low, high: high) return ret } } extension Array where Element == Float { mutating func clip(low: Float, high: Float) { print("accelerate version") var low = low var high = high self.withUnsafeMutableBufferPointer { bp in let p = bp.baseAddress! vDSP_vclip(p, 1, &low, &high, p, 1, vDSP_Length(bp.count)) } } } var int = (0..<10).map { Int($0) } int.clipped(low: 3, high: 5) // normal version int.clip(low: 3, high: 5) // normal version var x = (0..<10).map { Float($0) } x.clipped(low: 3, high: 5) // normal version x.clip(low: 3, high: 5) // acceerate version
Float用のclippedを多重実装せずにaccelerate versionを呼べないかと思ってるんですが@_specializeでもだめっぽい…… (edited)@_specialize ってそのメソッドや関数の型パラメータに利くんじゃないっけ?private func 化して@_specialize 付けるとか?protocol ArrayClippable を用意してprotocol ArrayClippable { static func clipArray(_ array: inout Array<Self>, min: Self, max: Self) } extension ArrayClippable { static func clippedArray(_ array: Array<Self>, min: Self, max: Self) -> Array<Self> { var ret = array Self.clipArray(&ret, min: min, max: max) return ret } } extension Array where Element : ArrayClippable { mutating func clip(min: Element, max: Element) { Element.clipArray(&self, min: min, max: max) } func clipped(min: Element, max: Element) -> Array<Element> { return Element.clippedArray(self, min: min, max: max) } }extension Comparable : ArrayClippable { static func clipArray(_ array: inout Array<Self>, min: Self, max: Self) { // ... } }@_specialize で呼び分けるのは無理なんじゃないかな?Playground execution failed: error: MyPlayground.playground:10:1: error: extension of protocol 'Comparable' cannot have an inheritance clause extension Comparable: ArrayClippable { ^ ~~~~~~~~~~~~~~ つけられない?@_specialize について、 _ で始まるものは本当に使わないほうがいいです。意図的にやっているのかっていうくらい頻繁に仕様が変わります。 by @rintarostruct S<T> { var x: T @_specialize(where T == Int, U == Float) mutating func exchangeSecond<U>(_ u: U, _ t: T) -> (U, T) { x = t return (u, x) } }_ に限らず破壊的変更がどのみち入るから(struct S<T> { var x: T mutating func exchangeSecond<U>(_ u: U, _ t: T) -> (U, T) { x = t return (u, x) } } extension S where T == Float { mutating func exchangeSecond(_ u: Int, _ t: Float) -> (Int, Float){ x = t return (u, x) } }@_specialize をなくせば動きはするしね。@_specialize では無理だと思う。MyArrayとMyArray2なんですが、同じテストコードでモジュール外にあるMyArrayの方が数百倍遅くて原因が分かりません。 モジュールまたぐ時ってwhole module optimization以外何かありましたっけ?makeIteratorはCollectionに生えているのが使えるのでMyArrayとおなじところにMyFloatArrayを作ってためしましたArrayに詰めたいけれど型が不定だと初期値をどうするのやらFloat に対して付けるんじゃないの?import Foundation var data = Data(bytes: [0x50, 0x4B, 0x01, 0x02, 0x41, 0x61]) data.removeFirst() print(data.startIndex) // swift-3.1: "0\n", swift-4.0: "1\n" data.customMirror // crash on swift-4.0 https://bugs.swift.org/browse/SR-5811 (edited)self[0..<nBytes]ってやってるからw https://github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/Data.swift#L1773 (edited)Data の件、 Array と挙動が違って混乱を招くかも? Welcome to Apple Swift version 4.0 (swiftlang-900.0.59 clang-900.0.34.2). Type :help for assistance. 1> var array = [2, 3, 5] array: [Int] = 3 values { [0] = 2 [1] = 3 [2] = 5 } 2> print(array.startIndex) 0 3> array.removeFirst() $R0: Int = 2 4> print(array.startIndex) 0subscript の index は startIndex が最初の要素を指すよ。 1> import Foundation 2> var data = Data(bytes: [2, 3, 5]) 3> print(data.startIndex) 0 4> data.removeFirst() $R0: UInt8 = 2 5> print(data.startIndex) 1 6> print(data[1]) 3 (edited)Array は必ず startIndex が 0 で endIndex が count - 1 として、わざわざ ArraySlice という型を設けて分離しているのに対して Data は一つの型でやってしまっていることとremoveFirst が startIndex に影響を及ぼすのか及ぼさないのかという仕様の違いをどっちも混ぜてしまったのが問題では。 1> var ns: ArraySlice<Int> = [2, 3, 5] ns: ArraySlice<Int> = 3 values { [0] = 2 [1] = 3 [2] = 5 } 2> print(ns.startIndex) 0 3> ns.removeFirst() $R0: Int = 2 4> print(ns.startIndex) 1ArraySlice とは一貫してるのかData は最初からスライスだと考えれば良いのか。Data はそういうのとは違うからInt で適切だと思う。String より遅いけど、計算量のオーダーは同じ。String インスタンスを作るのと大して変わらない。String から構築してるからString がヒープに確保してるでっかい領域をCharacter が参照してるだけになるのでは?String から characters を取り出したときに内部的にどうなってるか詳しいことはしらない。String より EasyText の Text の方が速そう。String がややこしいこと考えずに書記素クラスタで扱えるのはとても良いと思う。$ swift Welcome to Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36). Type :help for assistance. 1> : (lldb) script Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D. >>> [x * x for x in range(10)] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> [omochi@omochi-iMac SwiftSyntax (master *=)]$ swift Welcome to Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36). Type :help for assistance. 1> : (lldb) script Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D. >>> 3 + 3 6 >>> exit (lldb) ^D 1> ^D>>> ^D (lldb) ^D 1> ^D $ var exit: Never みたいなの生やせばexitで抜けれるようになるかしら$ swift Welcome to Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36). Type :help for assistance. 1> import Darwin 2> exit(0) REPL requires a running target process. error: REPL process is no longer alive, exiting REPL なら抜けられる。 (edited)struct Hoge { var foo: Int = 0 var bar: Int = 0 } var hoge: Hoge = Hoge() { didSet { print("didSet") } } みたいな、監視されている struct 値を更新するときに hoge.foo = 12 hoge.bar = 13 (edited) _ = { $0.foo = 12 $0.bar = 13 }(&hoge) っていう方法よりシンプルでわかりやすいのってありますか?(hoge.foo, hoge.bar) = (12, 13) これもだめ hoge.mutateメソッドを生やしたら少し分かりやすいかも?protocol Mutable { } extension Mutable { mutating func mutate(_ f: (inout Self)->Void) { f(&self) } } struct Hoge: Mutable { var foo: Int = 0 var bar: Int = 0 } (edited) hoge.mutate { $0.foo = 12 $0.bar = 13 } いいかも、使わせていただきまっす!Mutableプロトコルは名前が不自然なのでそこだけ変えて下さいwRxSwift.Variable に使いたかっただけなのでこんな感じにしました。 extension RxSwift.Variable { func mutateValue(fn: (inout Element) -> Void) { fn(&value) } }variable.value.foo = xxx をマルチスレッドでやらかすと死ねるdidSetの場合もですけど冪等に作っておいて多重実行は気にしないのが良いんですかね……extension RxSwift.Variable { func mutateValue(fn: (inout Element) -> Void) { _lock.lock() fn(&value) _lock.unlock() } } できるかな?こんな感じが良さそう。[T1: BinaryFloatingPoint]を[T2: BinaryInteger]に変換するメソッドが書けるようになって喜んでたら [T1: BinaryInteger]を[T2: BinaryFloatingPoint]に変換するほうができなかったSignedIntegerとUnsignedIntegerに分けてそれぞれInt64, UInt64を経由して変換するというろくでもない方法に落ち着いてしまったfatal error: Array<Foo> does not conform to Encodable because Pedestrian does not conform to Encodable.: (edited)Countable...Range を一掃できるのもうれしい。Codable のエラーメッセージがどうなってるかは知らないけど、原理的にはパスをたどれそうな気がする。エラーが throw されてきたら素通しにせず、一度 catch してからエラーメッセージにパスを追記して throw しなおせばいいんじゃない?そうなってなかったら swift リポジトリへの PR チャンスかも?Encoder, Decoderのエラーに含まれるパスは「とりあえずあるレベル」だと記憶。 (edited)Decoder につけなきゃいけないのか。=> の inout 版がほしい気がしてきた。func =><T>(lhs: T, rhs: (inout T) throws -> ()) rethrows -> T { var value = lhs try rhs(&value) return value } (edited)func =><T, U>(lhs: T, rhs: (T) throws -> U) rethrows -> U { return try rhs(lhs) }var teamToCount: [String: Int] = [:] for user in users { let team = user.team if let count = teamToCount[team] { teamToCount[team] = count + 1 } else { teamToCount[team] = 1 } } を、もし inout 版の => があれば reduce(into:_:) を使わなくても let teamToCount: [String: Int] = [:] => { teamToCount in for user in users { teamToCount[user.team, default: 0] += 1 } } って書けそうだなぁと。Codable など劇的にコーディングが楽になる新機能だと思いますが、ちょっとした便利な小技もあります。 そんな、 Swift 4 の小技の魅力の一面を 3 行...infix operator => : SwifletPrecedence precedencegroup SwifletPrecedence { higherThan: AssignmentPrecedence associativity: left } func =><T>(lhs: T, rhs: (inout T) throws -> ()) rethrows -> T { var value = lhs try rhs(&value) return value } print([Int]() => { (a: [Int]) -> () in a.append(42) })
$ swift inout-let.swift inout-let.swift:14:40: error: value of type 'Any' has no member 'append' print([Int]() => { (a: [Int]) -> () in a.append(42) }) ^ ~~~~~~ inout-let.swift:14:40: note: cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members print([Int]() => { (a: [Int]) -> () in a.append(42) }) ^ ( as AnyObject) (edited){ (a: inout [Int]) -> () in a.append(42) } クロージャパラメータに inout が必要inout がいるんですね・・・。考えてみれば当たり前だ。infix operator => : SwifletPrecedence precedencegroup SwifletPrecedence { higherThan: AssignmentPrecedence associativity: left } func =><T>(lhs: T, rhs: (inout T) throws -> ()) rethrows -> T { var value = lhs try rhs(&value) return value } print([Int]() => { (a: inout [Int]) -> () in a.append(42) }) print([Int]() => { a in a.append(42) }) print([Int]() => { $0.append(42) })
$ swift inout-let.swift inout-let.swift:15:25: error: value of type 'Any' has no member 'append' print([Int]() => { a in a.append(42) }) ^ ~~~~~~ inout-let.swift:15:25: note: cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members print([Int]() => { a in a.append(42) }) ^ ( as AnyObject) inout-let.swift:16:20: error: value of type 'Any' has no member 'append' print([Int]() => { $0.append(42) }) ^~ ~~~~~~ inout-let.swift:16:20: note: cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members print([Int]() => { $0.append(42) }) ^ ( as AnyObject)$ swift --version Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36) Target: x86_64-apple-macosx10.9reduce(into:_:) だとうまく推論できたのも謎。// 型の準備 struct User { var team: String } // 値の準備 let users = [ User(team: "A"), User(team: "B"), User(team: "B"), User(team: "A"), User(team: "C"), User(team: "A"), User(team: "C"), User(team: "B"), User(team: "D"), User(team: "A"), ] // 集計 let teamToCount: [String: Int] = users.reduce(into: [:]) { teamToCount, user in teamToCount[user.team, default: 0] += 1 } // 出力 for (team, count) in (teamToCount.sorted { $0.key < $1.key }) { print("\(team): \(count)") }teamToCount が inout なんですが、問題なく通ります。reduce(into:_:) と違うのは inout の後の第二引数があるかないかくらいな気がするけど・・・ func parseImportDecl(tokens: ArraySlice<TokenSyntax>) throws -> (decl: ImportDecl, rest: ArraySlice<TokenSyntax>)? { var index = tokens.startIndex ... return (decl: ImportDecl(keywordIndex: keywordIndex - tokens.startIndex, nameIndex: nameIndex - tokens.startIndex, tokens: Array(tokens[..<index])), rest: tokens[index...]) } (edited)echo 'Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated())'|TOOLCHAINS=swift swiftc -でswiftcがクラッシュする。export TOOLCHAINS=org.swift.3020170918aDictionary(uniqueKeysWithValues: ["a","b","c"].enumerated().filter { $1 != "a" }) もクラッシュ。Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated().filter { $1 != "a" }.map { ($0, $1) }) でクラッシュ回避。.map { $0 } でもいけますね 3> Dictionary(uniqueKeysWithValues: [(offset: 0, element: "a")]) $R2: [Int : String] = 1 key/value pair { [0] = { key = 0 value = "a" } }Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated().lazy) は別の形でクラッシュecho 'Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated())'|TOOLCHAINS=swift swiftc -でswiftcがクラッシュする。
swift-DEVELOPMENT-SNAPSHOT-2017-09-28-aで直った。[swift-evolution] Idea: Public Access Modifier Respected in Type Definition The core team would only consider a refinement or change to access control if there were something actively broken that mattered for ABI stability. -Chris$ swift Welcome to Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36). Type :help for assistance. 1> class Animal {} 2> class Cat: Animal {} 3> let a: () -> Cat = { Cat () } a: () -> Cat = 0x00000001000c5590 $__lldb_expr7`closure #1 () -> __lldb_expr_3.Cat in __lldb_expr_6 at repl.swift:3 4> let b: () -> Animal = a b: () -> Animal = 0x00000001000c5590 $__lldb_expr7`closure #1 () -> __lldb_expr_3.Cat in __lldb_expr_6 at repl.swift:3 5> let c: () -> [Cat] = { [Cat()] } c: () -> [Cat] = 0x00000001000c5680 $__lldb_expr11`closure #1 () -> Swift.Array<__lldb_expr_3.Cat> in __lldb_expr_10 at repl.swift:5 6> let d: () -> [Animal] = c error: repl.swift:6:25: error: cannot convert value of type '() -> [Cat]' to specified type '() -> [Animal]' let d: () -> [Animal] = c ^ 6> let e: [Cat] = [Cat()] e: [Cat] = 1 value { [0] = { __lldb_expr_1.Animal = {} } } 7> e is [Animal] $R0: Bool = trueis は 真になるのに、関数型に組み込まれたときはその互換性が発揮されないclass Animal {} class Cat: Animal {} let a: () -> Cat = { Cat () } let b: () -> Animal = a // OK let c: () -> [Cat] = { [Cat()] } let d: () -> [Animal] = c // NG: error: cannot convert value of type '() -> [Cat]' to specified type '() -> [Animal]' let e: [Cat] = [Cat()] e is [Animal] // truelet f: () -> Cat? = { Cat() } let g: () -> Animal? = f // OK こっちはできたwis の振る舞いってdo { let a: (Animal) -> () = { _ in } let b: (Cat) -> () = a // OK } do { let a: ([Animal]) -> () = { _ in } let b: ([Cat]) -> () = a // error: cannot convert value of type '([Animal]) -> ()' to specified type } do { let a: (Animal?) -> () = { _ in } let b: (Cat?) -> () = a // OK }do { let a: () -> () -> Cat = { { Cat() } } let b: () -> () -> Animal = a // OK } do { let a: () -> () -> [Cat] = { { [Cat()] } } let b: () -> () -> [Animal] = a // error: cannot convert value of type '() -> () -> [Cat]' to specified type '() -> () -> [Animal]' } do { let a: () -> () -> Cat? = { { Cat() } } let b: () -> () -> Animal? = a // OK }Array だけ壊れてるみたいdo { let a: [String: Cat] = ["": Cat()] let b: [String: Animal] = a // OK } do { let a: [String: [Cat]] = ["": [Cat()]] let b: [String: [Animal]] = a // OK } do { let a: [String: Cat?] = ["": Cat()] let b: [String: Animal?] = a // OK }as, is をoperatorにしてユーザーが定義できる様にして欲しくなる話だね。do { let a: () -> [String: Cat] = { ["": Cat()] } let b: () -> [String: Animal] = a // error: cannot convert value of type '() -> [String : Cat]' to specified type '() -> [String : Animal]' }代入文の型検査時は静的だから書き換えたisが評価できない
func as(lhs: A) -> Bの有無で決まるとか? (edited)func as<T, U>(_ v: My<T>) -> My<U> where U: T こういうの。無くても出来るかな?class Box<out T> とかやるのが楽だしわかりやすいとは思うけどstruct Box<T> { let value: T }T についての変性をどう扱うのかが気になってます。rintaro - 04/18/2017 この辺の話(Ty<Some> から Ty<Covariant> への変換) って https://devforums.apple.com/thread/261699 で語られているんですが、 https://devforums.apple.com/message/1102432#1102432 のArrayとかは出来るけど任意の value type には当てはまらないって文脈で > this doesn't apply to every value type (because value types can contain references and not enforce copy-on-write) らしいのですが、どういうケースなんでしょう?protocool Foo: classはできるけど、逆は出来ない。[Int] とかってboxingしないメモリレイアウトじゃないんか??unsafeBitCast([Int](), [String].self) これ動きそう 1> var a: [Int] = [0,1,2,3] a: [Int] = 4 values { [0] = 0 [1] = 1 [2] = 2 [3] = 3 } 2> var b: [String] = a as! [String] Could not cast value of type 'Swift.Int' (0x1013e0430) to 'Swift.String' (0x1013e36f8). 2017-10-06 11:35:18.511301+0900 repl_swift[28561:24355268] Could not cast value of type 'Swift.Int' (0x1013e0430) to 'Swift.String' (0x1013e36f8). b: [String] = <extracting data from value failed> Execution interrupted. Enter code to recover and continue. Enter LLDB commands to investigate (type :help for assistance.) Process 28561 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT frame #0: 0x00007fffc4cf5d42 libsystem_kernel.dylib`__pthread_kill + 10 libsystem_kernel.dylib`__pthread_kill: -> 0x7fffc4cf5d42 <+10>: jae 0x7fffc4cf5d4c ; <+20> 0x7fffc4cf5d44 <+12>: movq %rax, %rdi 0x7fffc4cf5d47 <+15>: jmp 0x7fffc4ceecaf ; cerror_nocancel 0x7fffc4cf5d4c <+20>: retq Target 0: (repl_swift) stopped.class Animal {} class Cat: Animal {} let a: [[Cat]] = [[Cat()]] a is [[Animal]] // truetrue になるんだっけis の検査と as の成功が一致してないといけないのか。is はあくまでインスタンスをチェックしてるだけで式の型を調べているわけではないと。 (edited) 1> let a: [Int] = [] a: [Int] = 0 values 2> type(of: a) $R0: [Int].Type = [Int] 1> let a: [Int] = [] a: [Int] = 0 values 2> type(of: a) $R0: [Int].Type = [Int] 3> func foo<T>(_ value: T) { 4. print(type(of: value)) 5. } 6> foo(a) Array<Int>let cats: [Cat] = [Cat()] let animals: [Animal] = cats 一瞬、↑みたいなケースで cats は animals にコピーされないからインスタンスの型という概念が成り立たないかと思ったけど、コピーされないのはあくまでバッファであって、インスタンス自体の領域は別だからやっぱりインスタンスの型で判断できる気がする。animals から cats に as で戻せなくなるのか。 (edited)Optional の is や as もややこしくなるな・・・。final class _EmptyArrayStorage : _ContiguousArrayStorageBase { } final class _ContiguousArrayStorage<Element> : _ContiguousArrayStorageBase { } // rawValue is passed inout to _isUnique. Although its value // is unchanged, it must appear mutable to the optimizer. @_versioned internal var rawValue: Builtin.BridgeObject @_inlineable // FIXME(sil-serialize-all) public // @testable var nativeInstance: Native { @inline(__always) get { _sanityCheck(isNative) return Builtin.castReferenceFromBridgeObject(rawValue) } } var objCInstance: ObjC { @inline(__always) get { _sanityCheck(isObjC) return Builtin.castReferenceFromBridgeObject(rawValue) } }internal typealias _ArrayBridgeStorage = _BridgeStorage<_ContiguousArrayStorageBase, _NSArrayCore> で、左側が さっきの pure swift のときの Storage の _ContiguousArrayStorageBase だから、as とかでObjC側にブリッジしたりするときにめんどくさいことが起こるんだろう・・・[Animal] as? [Cat] これを実現するためには、1要素毎にキャストして成功したらOKみたいな処理にする必要があってvar a: [Int] = [] var b: [String] = [] print(a == b) これで結論が出ると思ったらコンパイルエラーだったwfunc foo(x: Any) { switch x { case let strings as [String]: print("strings \(strings)") case let integers as [Int]: print("integers \(integers)") default: print("unknwon") } } let ints: [Int] = [] foo(x: ints) これで strings 判定されちゃうことになるので、やっぱキャスト出来ちゃうと駄目だと思います。 (edited)let x = [Int?.none, Int?.none, Int?.none] let y = x as? [String?] // [nil, nil, nil] これもなかなか。func foo<T>(value: T, type: T.Type) { switch type { case is Array<String>.Type: print("strings \(value as! Array<String>)") case is Array<Int>.Type: print("integers \(value as! Array<Int>)") default: print("unknwon") } } let ints: [Int] = [] foo(value: ints, type: type(of: ints)) // integers [] (edited)func cast<T, U>(from: U) -> T? { return from as? T } let z: Int?? = cast(from: String?.none) switch z { case .none: print("a") case .some(.none): print("b") // ココ case .some(.some): print("c") } で、やはりOptional.noneも同様にキャストが成功している。func foo<T>(value: T) { switch T.self { case is Array<String>.Type: print("strings \(value as! Array<String>)") case is Array<Int>.Type: print("integers \(value as! Array<Int>)") default: print("unknwon") } } let ints: [Int] = [] foo(value: ints)var a: [Int] = [] var b: [String]? = a as? [String] // Cast from '[Int]' to unrelated type '[String]' always fails この警告だけ (edited)func foo(_ x: Any) { switch type(of: x) { case is [String].Type: print("strings \(x as! [String])") case is [Int].Type: print("integers \(x as! [Int])") default: print("unknwon") } } var a: [Int] = [] foo(a) // integers [] (edited)as で出来るのはおかしい。こっちは世界の崩壊を招くlet x = [Int?.none, Int?.none, Int?.none] x is [String?] // true type(of: x) is [String?].Type // falselet x = [Int??.none, Int??.none, Int??.none] let y = x as? [Int?] // [nil, nil, nil]let x = [Int?.none, Int?.none, Int?.none] type(of: x) == [Int?].self // true== でも書けるね、継承を区別したいときはこれが必要になる (edited)as? の考え方が違うってだけだと思う/// If the dynamic type of `obj` doesn't implement a `getIntegerValue()` /// method, the system returns a runtime error when you initialize /// `certainValue`. /// /// Alternatively, if you need to test whether `obj.getIntegerValue()` exists, /// use optional binding before calling the method. /// /// if let f = obj.getIntegerValue { /// print("The value of 'obj' is \(f())") /// } else { /// print("'obj' does not have a 'getIntegerValue()' method") /// } /// // Prints "The value of 'obj' is 100" public typealias AnyObject (edited)public typealias AnyObject = Builtin.AnyObject public typealias AnyClass = AnyObject.Typetypealias Any = protocol<> が実際にあったけど、 & 記法になったタイミングで Any がキーワードになり、Parser で特別扱いになりました。typealias Any = Builtin.Any になるかもしれないですね。let x = Int??.none as? Int? let y = Int?.none as? Int?? switch x { case .none: print("print") case .some: print("-") } switch y { case .none: print("-") case .some: print("print") } (edited)let x = [Int?.none] as? [Int??] switch x?.first! { case .none: print("x") // !! case .some(.none): print("y") case .some(.some): print("z") } let y = [Int?.none] as [Int??] switch y.first! { case .none: print("x") case .some(.none): print("y") // !! case .some(.some): print("z") } (edited)as? の使用に対して警告だしながら > Conditional cast from '[Optional<Int>]' to '[Int??]' always succeedsEncoder, Decoderはサポートする型により、Codable自身のコーディング表現をオーバーライドする様になってます。URLをURL自身にエンコードさせると、["relative":"http://apple.com"]みたいな辞書表現になります。On implementing Codable conformance, if it uses container.encode(_:…) instead of container.encodeIfPresent(_:…), container.encode(url, forKey: .url) produces dictionary. But, `JSONDecoder` tries to decode Optional<URL> from string.JSONEncoderは"http://apple.com"として扱いたいので、EncodableがURLだったらこうする、と特別扱いします。 } else if T.self == URL.self { // Encode URLs as single strings. return self.box((value as! URL).absoluteString)Optional, Set, Arrayにこれらの型が入っていた場合にも特別扱いしなければいけないのですが、Conditional Conformanceがないため、Decodableのコードが素直にかけませんでした。extension Optional : Decodable
extension Optional : Decodable /* where Wrapped : Decodable */ { @_inlineable // FIXME(sil-serialize-all) public init(from decoder: Decoder) throws { // Initialize self here so we can get type(of: self). self = .none assertTypeIsDecodable(Wrapped.self, in: type(of: self)) let container = try decoder.singleValueContainer() if !container.decodeNil() { let metaType = (Wrapped.self as! Decodable.Type) let element = try metaType.init(from: container) self = .some(element as! Wrapped) } } } (Swift 4.0のコードに変更) (edited)Decoderの処理を優先して、こう書きたい。 let container = try decoder.singleValueContainer() if !container.decodeNil() { - let metaType = (Wrapped.self as! Decodable.Type) - let element = try metaType.init(__from: container) - self = .some(element as! Wrapped) + self = .some(try container.decode(Wrapped.self)) } } } (edited)JSONEncoderとかのCoderで特別扱いされるURLの側で「JSONEncoderだったら辞書表現をやめる」みたいな力技で対応されていました。 https://github.com/apple/swift/pull/10766 (edited)Coderではバグっていたのです。Coder実装がどれくらいあるのか知りませんが…YAMLのCoder実装は未リリース。これがSwift 4.0.1で直りそう、というお話。 4.0.1に入るかどうか微妙な時期らしい…let results = scheduler.createObserver(Void.self) XCTAssertEqual(results.events, [next(0, ()), next(10, ())]) と書くとコンパイルエラーになってしまいます。 どのように書くと良いのでしょうか…? (そもそもObservable<Void>はTestableObserverでテストを書くべきでは無いのでしょうか…?)() == () // truefunc f<X: Equatable>(x: X) {} f(x: ())public func == (lhs: Recorded<Void>, rhs: Recorded<Void>) -> Bool { return lhs.time == rhs.time } これその辺に書いたら何とかなりませんかねimport Foundation class A: Encodable { let f1: String init(f1: String) { self.f1 = f1 } } class B: A { let f2: String init(f1: String, f2: String) { self.f2 = f2 super.init(f1: f1) } } let b = B(f1: "f1", f2: "f2") let x = try JSONEncoder().encode(b) String(data: x, encoding: .utf8) // -> { "f1": "f1" } (edited)protocol C: Encodable { var f3: String { get } } struct D: C { var f3: String } let d: C = D(f3: "f3") let y = try JSONEncoder().encode(d) // ここでコンパイルエラー (edited)Dとして渡すと通りますCにencodeメソッドを足してDや各々でエンコードってのが良さそうですかね/// A type that can encode itself to an external representation. public protocol Encodable { /// Encodes this value into the given encoder. /// /// If the value fails to encode anything, `encoder` will encode an empty /// keyed container in its place. /// /// This function throws an error if any values are invalid for the given /// encoder's format. /// /// - Parameter encoder: The encoder to write data to. func encode(to encoder: Encoder) throws }protocol C: Encodable { var f3: String { get } func encode() throws -> Data } struct D: C { var f3: String func encode() throws -> Data { return try JSONEncoder().encode(self) } } let d: C = D(f3: "f3") let y = try d.encode() open func encode<T : Encodable>(_ value: T) throws -> Data {protocol P {} class Cat : P {} func f<X: P>(_ p: X) {} var a: P = Cat() var b: Cat = Cat() f(a) // NG f(b) // OKC のextensionにencode書けばいいのか。protocol C: Encodable { var f3: String { get } func encode() throws -> Data } extension C { func encode() throws -> Data { return try JSONEncoder().encode(self) } } struct D: C { var f3: String } let d: C = D(f3: "f3") let y = try d.encode() これがいける?toJSON() -> Data という名前の方が良さそうOptional.noneは常にフィールド自体省略になってnullにすることができない気が…… fileprivate func box<T : Encodable>(_ value: T) throws -> NSObject { return try self.box_(value) ?? NSDictionary() } Container上では return try JSONSerialization.data(withJSONObject: topLevel, options: writingOptions)encode(to:)だとそうなりますね。OptionalだとencodeIfPresent(_:forKey:)が使われるコードが生成される。これをencode(_:forKey:)を使うコードを自分で書けばnullが使われる。 https://github.com/apple/swift/blob/master/lib/Sema/DerivedConformanceCodable.cpp#L623-L624 (edited)Codable使う旨味が減っちゃいますねぇ。 Optional.noneのあつかいもstrategyで書けたらいいんじゃないかと思うんですが データ全体じゃなく部分ごとにここは省略したいとかある可能性もあるんで微妙ですかねstruct Foo: Encodable { var optionalInt: Int? private struct FooEncode: Encodable { var optionalInt: KeyedOptional<Int> /* Foo <-> FooEncode 変換書く */ } func encode() throws -> Data { return FooEncode(self).encode() } } こげな{ "objects": [ { "key": 1, "value": "foo" }, { "key": "2", "value": "bar" } ] } こういう意地悪すると、 enum Key: Codable { case int(Int) case string(String) } こんなのが生える{ "objects": [ { "key": 1, "value": "foo" }, { "key": null, "value": "bar" } ] } で、 struct Object: Codable { let key: Int? let value: String } (edited)superEncoder/superDecoderの利用は必須ではないですね。superclassのデータをキーsuperに入れるかどうかはユーザー次第になってるかと。public class Comprehensive: Encodable { private let field1: String private let field2: String? private let field3: String? fileprivate init(field1: String, field2: String?, field3: String?) { self.field1 = field1 self.field2 = field2 self.field3 = field3 } } public class Child1: Comprehensive { public init(field1: String, field2: String) { super.init(field1: field1, field2: field2, field3: nil) } } public class Child2: Comprehensive { public init(field1: String, field3: String) { super.init(field1: field1, field2: nil, field3: field3) } } めちゃくちゃ汚いですがこれでやりたかったことはできそうですpublic class AnyKeyPath {} public class PartialKeyPath<Root> : AnyKeyPath {} public class KeyPath<Root, Value> : PartialKeyPath<Root> {} public class WritableKeyPath<Root, Value> : KeyPath<Root, Value> {} public class ReferenceWritableKeyPath<Root, Value> : WritableKeyPath<Root, Value> {} (edited)responds(to:)とか使えるという話import Foundation class Cat { @objc func eat() {} } (Cat() as AnyObject).responds(to: #selector(Cat.eat)) // true#selector(Cat.eat) ってやってるけどclass Dog { @objc func eat() {} }@objcがついてないと当然Selectorは生えないのでfalseになる- (oneway void)release;Codableに準拠した型のletプロパティは、エンコードはされるけどデコードされることはないのね。letプロパティをエンコードされない様にするには、letプロパティを含まないCodingKeysを用意すると。letプロパティだ。NSDictionaryからDataを経由せずに直接デコードしたい… 作った。 https://github.com/norio-nomura/ObjectEncoder[String: Any], [Any] or Any as payload.import Foundation import ObjectEncoder // single value let string = "Hello, ObjectEncoder" let encodedString = try ObjectEncoder().encode(string) (encodedString as AnyObject).isEqual(to: string) // true let decodedString = try ObjectDecoder().decode(String.self, from: encodedString) // dictionary struct S: Codable { let p1: String } let s = S(p1: "string") guard let encodedS = try ObjectEncoder().encode(s) as? [String: Any] else { fatalError() } encodedS["p1"] // "string" let decodedS = try ObjectDecoder().decode(S.self, from: encodedS) decodedS.p1 // "string" // array let array: [S] = [s, s] guard let encoded = try ObjectEncoder().encode(array) as? [[String: Any]] else { fatalError() } encoded[0]["p1"] // "string" let decoded = try ObjectDecoder().decode([S].self, from: encoded) decoded[0].p1 // "string"JSONEncoderやPropertyListEncoderみたいに、各型についての特殊な処理が一切入っていないCoders実装になってます。[String: Anyや[Any]へそのまま突っ込むイメージ。let source = CGImageSourceCreateWithURL(url as CFURL, nil), let properties = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as NSDictionary? let decoded: ImageProperties = try ObjectDecoder().decode(from: properties) みたいなAPIからNSDictionaryで返ってきたデータのモデリング。 (edited)JSONEncoderかPropertyListEncoderへData以外も受け付けるAPIを作ってPR出すことも考えたけど、変換部分が邪魔だった。{ “id”: 1, “url”: “” } というAPIのレスポンスがあったとして、 struct Hoge: Codable { let id: Int let url: URL? } これでデコードしようとすると、Invalid URL StringということでdataCorrupted扱いになります。このとき、urlをnilで取り扱うためのワークアラウンド、どなたかお持ちですか? (edited)struct Hoge: Codable { let id: Int let jsonUrl: String? var url: URL { get { ... } set { ... } } }struct Landmark: Codable { var name: String var foundingYear: Int var location: Coordinate var vantagePoints: [Coordinate] enum CodingKeys: String, CodingKey { case name = "title" case foundingYear = "founding_date" case location case vantagePoints } }struct Hoge: Codable { let id: Int private let jsonUrl: String? var url: URL? { return URL(string: jsonUrl) } enum CodingKeys: String, CodingKey { case id case jsonUrl = "url" } } (edited)struct Hoge: Codable { let id: Int private let jsonUrl: String? var url: URL? { return jsonUrl.flatMap(URL.init) } enum CodingKeys: String, CodingKey { case id case jsonUrl = "url" } } (edited)struct Hoge: Codable { let id: Int let url: String? } extension Hoge { var urlurl: URL? {return url.flatMap {URL(string: $0)}} } Codableがjsonをそのままうつしていると考えればこう (edited)url: String は image: UIImageView と同じレベルでやめたいurl のほうを使わずに urlurl を使うのが注意点かurl: String は合理的だと思いますよ。 URL オブジェクトはデータ構造というよりはユーティリティ。struct _Hoge: Codable { 略 } と struct Hoge { 略 } でこいつら相互変換可能に。hoge.カッコイイ名前.url になるのではHoge と Hoge.JSON にするの良さそうCGSize(width: 100, height: 50) に対応するのは { "width": 100, "height": 50 } ではなくて [100, 50] なんですよid: Int から id String に変わったとかあるので、外部APIを最初に受けるところはあまり厳格にしてもというのはあります。import Foundation struct Model<Base: Modelable> { var base: Base } protocol Modelable { var model: Model<Self> { get } } extension Modelable { var model: Model<Self> { return Model(base: self) } } struct Hoge: Codable, Modelable { fileprivate var int: Int fileprivate var url: String? } extension Model where Base == Hoge { var int: Int { return base.int } var url: URL? { return base.url.flatMap(URL.init) } } func x(hoge: Hoge) { hoge.model.url // URL? } よさそうstruct Cat { subscript(ex ex: Void) -> Ex<Cat> { get { return Ex(self) } set { self = newValue.t } } var age: Int = 3 } struct Ex<T> { init(_ t: T) { self.t = t } var t: T } var cat = Cat() cat[ex: ()].t.age = 6 print(cat) // Cat(age: 6)func M<A: Modelable>(_ arg: A) -> Never { fatalError() } こいつ作っておけば cat[M].t.age = 6ってできるんじゃん?cat[Rx].tap.subscribe ...import Foundation struct Model<Base: Modelable> { var base: Base } protocol Modelable { var model: Model<Self> { get } } extension Modelable { var model: Model<Self> { return Model(base: self) } } struct Hoge: Codable, Modelable { fileprivate var int: Int fileprivate var url: String? var model: Model<Hoge> { get { return Model(base: self) } set { self = newValue.base } } } extension Model where Base == Hoge { var int: Int { get { return base.int } set { base.int = newValue } } var url: URL? { get { return base.url.flatMap(URL.init) } set { base.url = newValue?.absoluteString } } } func x(hoge: Hoge) { hoge.model.int var hoge = hoge hoge.model.url = URL(string: "https://www.google.com") } いけた。struct Model<Base: Modelable> { var base: Base } protocol Modelable { var model: Model<Self> { get } } extension Modelable { var model: Model<Self> { get { return Model(base: self) } set { self = newValue.base } } } struct Hoge: Codable, Modelable { fileprivate var int: Int fileprivate var url: String? } extension Model where Base == Hoge { var int: Int { get { return base.int } set { base.int = newValue } } var url: URL? { get { return base.url.flatMap(URL.init) } set { base.url = newValue?.absoluteString } } } func x(hoge: Hoge) { hoge.model.int var hoge = hoge hoge.model.url = URL(string: "https://www.google.com") }Modelに対してJSON<Model>を作りたい (edited)URLComponents として保持するのもありなのかも?と思ったけど、これはどういう状態なんだろうか。 import Foundation var comps = URLComponents(string: "")! comps.url! // (no URL) (edited).url が作れないって感じ?String で持つべきだと思います?UUID にするのはもちろんやるべきですし、私もそう書きます。UUID で定義するなら、 UUID を String で持つべきなのはどういうケースですか? (edited)UUID、サーバから受ける場合は String?url.flatMap {URL(string: $0)} を都度書きたくない/// デコードしたStringと、TypedなURLは纏めて独自型に押し込めるほうがいい struct RobustURL: Codable { let rawValue: String var typed: URL? { return URL(string: rawValue) } func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(rawValue) } init(from decoder: Decoder) throws { rawValue = try decoder.singleValueContainer().decode(String.self) } } /// CoreGraphicに依存しない独自型 struct Size: Codable { let width: Double let height: Double } import CoreGraphics extension Size { var asCGSize: CGSize { return CGSize(width: width, height: height) } } struct Fuga: Codable { let url1: RobustURL // 不正なURLが来うることを型として示せる let url2: RobustURL // 不正なURLが来うることを型として示せる let url3: URL // 不正なURLが来ないことを型として示せる let size: Size } let data = """ { "url1": "https://failable.url", "url2": "不正なURL", "url3": "https://ensured.url", "size": { "width": 100, "height": 50 } } """.data(using: .utf8)! let fuga = try! JSONDecoder().decode(Fuga.self, from: data) fuga.url1.typed // https://failable.url fuga.url2.typed // nil fuga.url3 // https://ensured.url fuga.size.asCGSize // {w 100 h 50} let json = try! JSONEncoder().encode(fuga) print(String(data: json, encoding: .utf8)!) // {"size":{"width":100,"height":50},"url3":"https:\/\/ensured.url","url1":"https:\/\/failable.url","url2":"不正なURL"}ウソもデコードできるURL型を自分で定義これすねasURL は欲しくないですねstruct Bar: Codable, RawRepresentable { let rawValue: String init?(rawValue: String) { self.rawValue = rawValue } } これはエンコードできないな。struct RobustURL: Codable, RawRepresentable { let rawValue: String var typed: URL? { return URL(string: rawValue) } init?(rawValue: String) { self.rawValue = rawValue } } すっきり{"rawValue": ...} の階層つくらないんですね、まじか‥init?(rawValue: String) も要らないんじゃないかな。publicにする時には要るか。internalなら要らないですね。: class をつけることが多いんだけどprotocol と mutating 関連の Proposal なかったっけ?: class にしてしまっているprotocol Foo: class {} class Bar<X: class> {} Bar<Foo>() // 🙅:class ってそこでもつかえる? :AnyObject にしてた。@objc protocol Foo: class {} class Bar<X: AnyObject> {} Bar<Foo>() // 🙆@objc は深入りしたくない・・・互換性のためにいろいろ諦めてそうだしちゃんと考えて無さそう (edited)@optional なメソッドとかSwift上にそんな概念ないのにちゃんと考慮されたりするし:class つけなくてもその前提条件だとコンパイルはできるんだけど、 考慮せずぜんぶ func にしてるんだって自覚を表明するためにつけといたほうがマシかなって思ってるAnyObject って参照型なら OK じゃなくてクラスじゃないとダメなのか。 1> let a: () -> Int = { 42 } 2. let b: AnyObject = a error: repl.swift:2:20: error: value of type '() -> Int' does not conform to specified type 'AnyObject' let b: AnyObject = a ^ as AnyObjecttypealias AnyObject 1> let a: () -> Int = { 42 } a: () -> Int = 0x00000001000c5030 $__lldb_expr8`closure #1 () -> Swift.Int in __lldb_expr_7 at repl.swift:1 2> let b = a b: () -> Int = 0x00000001000c5030 $__lldb_expr8`closure #1 () -> Swift.Int in __lldb_expr_7 at repl.swift:1 3> a === b error: repl.swift:3:3: error: cannot check reference equality of functions; operands here have types '() -> Int' and '() -> Int' a === b ~ ^ ~var f: () -> String = { "hello" } var array: [() -> String] = [] array.append(f) print(array[0] === f) /Users/omochi/temp/swer/Sources/swer/main.swift:5:16: Cannot check reference equality of functions; operands here have types '() -> String' and '() -> String'=== のオペランドの型が AnyObject なのかも。let c = { (i: Int) in print("\(i)") } func f(i: Int) { print("\(i)") } (c as AnyObject) === (c as AnyObject) // false (f as AnyObject) === (f as AnyObject) // false まあそもそもBoxのポインタ比較だと思うんでvar a = 0 let b: () -> Int = { a = a + 1; return a } let c = b print(b()) // 1 print(c()) // 2@convention()によって挙動がいろいろですね。c() は 1 にならないとおかしい。
@conventionは7種類あるらしい - ``@convention(thin)`` indicates a "thin" function reference, which uses the Swift calling convention with no special "self" or "context" parameters. - ``@convention(thick)`` indicates a "thick" function reference, which uses the Swift calling convention and carries a reference-counted context object used to represent captures or other state required by the function. - ``@convention(block)`` indicates an Objective-C compatible block reference. The function value is represented as a reference to the block object, which is an ``id``-compatible Objective-C object that embeds its invocation function within the object. The invocation function uses the C calling convention. - ``@convention(c)`` indicates a C function reference. The function value carries no context and uses the C calling convention. - ``@convention(objc_method)`` indicates an Objective-C method implementation. The function uses the C calling convention, with the SIL-level ``self`` parameter (by SIL convention mapped to the final formal parameter) mapped to the ``self`` and ``_cmd`` arguments of the implementation. - ``@convention(method)`` indicates a Swift instance method implementation. The function uses the Swift calling convention, using the special ``self`` parameter. - ``@convention(witness_method)`` indicates a Swift protocol method implementation. The function's polymorphic convention is emitted in such a way as to guarantee that it is polymorphic across all possible implementors of the protocol.@convention(thin) indicates a "thin" function reference, which uses the Swift calling convention with no special "self" or "context" parameters. あー、ここに出てくる、 self と context がミソっぽいなあ 今の話let b: () -> Int = { [x=a] in a = x + 1; return a }AnyObjectには入らなかった>7種類。class やめるのダメ?var a = 3 let b: () -> Int = { [x=a] in a = x + 1 return a } print(b()) // 4 print(b()) // 4 print(b()) // 4idにはブロックが入った気がするから、AnyObject != idvar a = 3 let b: () -> Int = { [x=a] in a = x + 1 return a } let c = b print(b()) print(c()) print(b()) print(c()) 4 4 4 4class 使うとか? class Ref<Value> { var value: Value }& と * がほしくなってきた。 struct と & と * の世界、実は良かったのでは? malloc や free が面倒だっただけで、そこをリファレンスカウントで勝手にやってくれるなら。& じゃなくて、実体コピーした上で参照型化かな。struct Foo を作ったけど、それを共有したいときは Foo * として取り扱えるとうれしい。 (edited)* の意味は C と同じになるけど、 & はちょっと違うから別の記号が良さそう。Box<Foo> と同じなんだけどbox 1Optional や Array みたいに Box ( Reference でもいい)のシュガーがあればいいのかも。Foo* が Reference<Foo>weak var foo: Foo*? こうなる? (edited)class Reference<Value> { var value: Value }prefix func * もほしいかFoo* が Reference<Foo> だとうれしくない?weak var a: Reference<Int>? で良いんじゃない? (edited)weak var foo: Foo*? かな?let a: () -> Int = { 42 } let block = a as @convention(block) () -> Int as AnyObjectlet a: () -> Int = { 42 } let block = a as AnyObject print(block)
as AnyObject はそもそもそのままできそうですよlet a: () -> Int = { 42 } print(a as AnyObject === a as AnyObject) // false let b = a as @convention(block) () -> Int print(b as AnyObject === b as AnyObject) // true() -> Int false @convention(block) () -> Int truea は as AnyObject でボクシングされるけどb はすでに AnyObject だからlet a: () -> Int = { 42 } let b = a as AnyObject b === b // truelet a: () -> Int = { 42 } print(type(of: a)) print(a as AnyObject === a as AnyObject) let b: @convention(block) () -> Int = a as @convention(block) () -> Int print(type(of: b)) print(b as AnyObject === b as AnyObject) var x: AnyObject = b // NG: value of type '@convention(block) () -> Int' does not conform to specified type 'AnyObject'dump(P.method)もダメだった。var x: AnyObject = b // NG: value of type '@convention(block) () -> Int' does not conform to specified type 'AnyObject' (edited)poをやるみたいなの。>dump (edited)print(b as AnyObject === b as AnyObject) // true var x: AnyObject = b // NG: value of type '@convention(block) () -> Int' does not conform to specified type 'AnyObject'import Foundation let a = "str"; let b: NSString = aclass Cat {} let a: AnyObject = Cat() print(type(of: a)) // Cat
func f() -> Int { return 42 } let a: AnyObject = f as AnyObject print(type(of: a)) // _SwiftValue_SwiftValue なる型になってた。swift-string.swift:3:19: error: cannot convert value of type 'String' to specified type 'NSString' let b: NSString = a ^ as NSString; が付いてるas NSString なら通る。明示的なキャストを言語的に強制してるということです。:tarunon: 絵文字ほしくなってきたなfalse だから。 import Foundation let a = "str" a as NSString === a as NSString // false=== が true になるところimport Foundation let str = "str" let b = str as NSString (b as AnyObject === b as AnyObject) // true と同じじゃないかと。 (edited)let b: @convention(block) () -> Int = { 42 } b as AnyObject === b as AnyObject // trueimport Foundation let str = "str" let b = str as NSString let c: AnyObject = b // OKlet b: @convention(block) () -> Int = { 42 } b as AnyObject === b as AnyObject // true let c: AnyObject = b // ERRORlet b: @convention(block) () -> Int = { 42 } b as AnyObject === b as AnyObject // true b is AnyObject // true let c: AnyObject = b // ERRORis AnyObject が true なのに代入できない・・・import Foundation let a = "aaa" a is NSString let b: NSString = a is trueだけど代入できないのはよくあるからOptional も含め@convention(block) の時点で ObjC の世界に入っているわけだから、 AnyObject にそのまま突っ込めてもいい気はしますね。protocol Proto : AnyObject {} class Box1<X> {} Box1<Proto>() // OK class Box2<X: AnyObject> {} Box2<Proto>() // NG: 'Proto' is not convertible to 'AnyObject''Proto' is not convertible to 'AnyObject' ってエラーメッセージ出てるけど Proto : AnyObject なんだけどなあprotocol Proto {} struct S: Proto {} func foo<P: Proto>(x: P) {} let p: Proto = S() foo(x: p) // error: cannot invoke 'foo' with an argument list of type '(x: Proto)' これと同じですね。AnySequence とか使いたくなるケースの 8 割くらいは実はいらないんじゃないかなぁ。as とか is の挙動がReference と同じように。後は使いやすいシュガーがあれば。protocol と参照型の相性が良くないような。{ ∃X, X: Animal } という存在型を略して Animal 型と書くのをやめてぱっと見で存在型だってわかるようにすればもうちょい理解しやすくなりそうですねtypealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> let strings: AnySequence<String> = ["a", "b", "c"]P1 & P2 は Any<T where T: P1, T: P2> とか?Any<P1 & P2> が Exitentialになるという仕様になってほしい P1 & P2 はあくまで protocol (edited)protocol<P1, P2> が P1 & P2 になりました。import UIKit class MyScrollViewDelegate: NSObject, UIScrollViewDelegate { } let myScrollViewDelegate = MyScrollViewDelegate() let tableView = UITableView() let scrollView = tableView as UIScrollView scrollView.delegate = myScrollViewDelegate tableView.delegate is UITableViewDelegate // true myScrollViewDelegate === tableView.delegate // true myScrollViewDelegate is UITableViewDelegate // false Objc絡むととたんにやばくなるやつunrecognized selector sent to instance 0xXXXXX いつものだwAnimal がbark() メソッドをもってるとして、Any<Animal> 型のanimal に対して animal.bark() を呼びだせるのはAny<Animal>: Animal なわけではなく、 Opening existentials のシンタックスシュガーだって考えればよさそう? let animal: Any<Animal> = Dog() // OK animal.bark() // ↑は以下のシンタックスシュガー // aの型はA。AはAnimalに準拠。 let a = animal openas A a.bark()struct S { var a: Int = 3, b: Int = 4 }CGFloat って Swift 3.1 まで Float や Double の typealias じゃなかったっけ? https://developer.apple.com/documentation/coregraphics/cgfloatstruct になった?struct でしたっけ?struct の方が良いと思います。(環境によって Float や Double に切り替わるとやっかいなので)CGFloat は昔 Double か Float の typealias だったような気が…Obj-Cとの記憶が混乱したのか TimeInterval と ObjC の両方と混同してたような気がしますCGFloat のコンパイルが通らなくなる夢を見てた気がしてたんですが、この頃の記憶かも。CoreGraphics だし import Foundation しないと使えないし@_fixed_layout public struct CGFloat { #if arch(i386) || arch(arm) /// The native type used to store the CGFloat, which is Float on /// 32-bit architectures and Double on 64-bit architectures. public typealias NativeType = Float #elseif arch(x86_64) || arch(arm64) /// The native type used to store the CGFloat, which is Float on /// 32-bit architectures and Double on 64-bit architectures. public typealias NativeType = Double #endif ... /// The native value. public var native: NativeType } (edited)NativeType の typealias になったね +public struct CGFloat { +#if arch(i386) || arch(arm) + public typealias UnderlyingType = Float +#elseif arch(x86_64) || arch(arm64) + public typealias UnderlyingType = Double +#endif (edited)昨日話していてそんな気がしたんですが やっぱりOptionalの暗黙変換とOptionalの共変性は矛盾した結果を生むので両方入ってるのは厳しいですね// Kotlin open class Animal class Cat: Animal() // Rule A // Cat is subtype of Animal run { val cat: Cat = Cat() val animal: Animal = cat } // Rule B // Int is subtype of Int? run { val int: Int = 0 val intOptional: Int? = int // 0 } // Rule C // Optional has covariance run { val catOptional: Cat? = null val animalOptional: Animal? = catOptional // null } // Question // What happen replace `Cat : Animal` to `Int : Int?` run { val intOptional: Int? = null val intOptionalOptional: Int?? = intOptional // null (Int?? == Int?) }String?.none as? Int? => Int??.some(.none) は確かにおかしい結果を生むんですが、それ以前に共変性周りが崩壊していることに気がついたInt?? でネストを表現できないですがInt は Int? のサブタイプじゃないですからねぇ。Optional<Cat> が Optional<Animal> のサブタイプでも、 Int が Int? のサブタイプでなければ Optional<Int> は Optional<Int?> のサブタイプにならないですし。String?.none as? Int? => Int??.some(.none) こいつをウソのサブタイプを倒した後でどう説明するのが良いのか、どう言う振る舞いであるべきなのかを考えないといけない気がするCat?.none as Animal? これが暗黙のmapであるとするのであれば上の結果は正しいということになりますねString?.none as? Int? => Int??.some(.none)
String → Int はパースですか?
String?.none as? Int? ってやると結果が Int??.some(.none)になるんですよ。つまりキャストが成功するas? の ? を忘れてた。 (edited)[String]() as? [Int] これは 空配列になる。 1> Int?.none as? Int? $R0: Int?? = nil (edited) 2> print(Int?.none as? Int?) Optional(nil) 1> dump(Int?.none as? Int?) ▿ Optional(nil) - some: nil $R0: Int?? = nilString?.none as? Int? // .some(.none).none であるべきだと思います。[String]() as? [Int] // .some([]) (edited).none であるべきかとAnimal?.none as? Cat? ではこれは?([String]() as [Any]) as? [Int] (edited)Animal?.none as? Cat? ダメな気がしてきたlet cats = [Cat]() let animals: [Animal] = cats // OK let cats2: [Cat] = animals as! [Cat] // これは? (edited)let animals: [Animal] = cats // OK ↑ここで CoW を効かせたいからなぁ。map すると先行コピーされちゃう。 (edited)map でもいい気も?List は参照型だけど、値型+ジェネリクス+ out のときどうなるのかなって。interface しか out 付けれなかった。 using System; namespace HelloWorld { interface IBox<out T> { T Get(); } struct SBox<T> : IBox<T> { private T _value; public SBox(T t) { _value = t; } public T Get() { return _value; } } class CBox<T> : IBox<T> { private T _value; public CBox(T t) { _value = t; } public T Get() { return _value; } } class Animal {} class Cat : Animal {} class Hello { static void Main() { IBox<Cat> sCat = new SBox<Cat>(new Cat()); IBox<Animal> sAnimal = sCat; // OK sCat = (IBox<Cat>)sAnimal; // OK Console.WriteLine(sCat); IBox<Cat> cCat = new CBox<Cat>(new Cat()); IBox<Animal> cAnimal = cCat; // OK cCat = (IBox<Cat>)cAnimal; // OK Console.WriteLine(cCat); } } }beginAsync の throws をなくそうという話への反応が少なくて悲しい。 Chris Lattner と Joe Groff の見解が知りたい。(Foo) async -> Void の戻り値を受けなくても別に問題ないですよね?await foo() await bar() await baz()foo の非同期処理が完了後 bar が実行され、 bar が完了後 baz が実行されるだけで。 (edited)async -> Void ができなきゃいけないって意味ですね。beginAsync の throws について反応がないのはなんでなんだろう?静的チェックの安全性を壊すか壊さないかの重要な話だと思うんですけどねぇ・・・。class Cat { func nya(_ a: Int) -> String { return String(a) } } let nya: (Cat) -> (Int) -> String = Cat.nya let cat = Cat() nya(cat)(3) // "3" Cat.nya(cat)(4) // "4"- Indices.swift.gyb + Indices.swiftCountableRange 系の削除に期待。CountableRange 消す PR 書くの気持ち良さそう。CodableとかAPI自体を見直さないとダメそう。>Conditional Conformanceimport Foundation struct S<Wrapped> { var value: Wrapped } extension S: Codable where Wrapped: Codable { enum CodingKeys: String, CodingKey { case value } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) value = try container.decode(Wrapped.self, forKey: .value) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(value, forKey: .value) } } let s = S<Int>(value: 1) let encoder = JSONEncoder() let data = try encoder.encode(s) print(String(data: data, encoding: .utf8)!) // {"value":1} がswift-DEVELOPMENT-SNAPSHOT-2017-11-13-aで動いた。extension S: Sequence where Wrapped: Sequence { func makeIterator() -> Wrapped.Iterator { return value.makeIterator() } } はコンパイラクラッシュSequence は Element, Iterator, SubSequence とあって、それらが関係しているので複雑そうです。Wrapped.Iterator を自分の Iterator として解決する辺りとかヤバそう。[Any]はCodableでは無くなる?extension Array: Codable where Element: Codable {} かと。Equatable とかと同様に。[AnyHashable: Any]も。[String: Any]の代わりに[String: Codable]を使っても、Encoder,Decoder側に扱うAPIが無いかも。 Fatal error: Dictionary<String, Decodable & Encodable> does not conform to Encodable because Encodable does not conform to itself. You must use a concrete type to encode or decode.extension Dictionary: Codable where Value: Codable {} が必要な気がします。正確には Encodable と Decodable 別々に。extension Dictionary: Codable where Key == String, Value: Codable {} こうかな?AnyCodableみたいなものが必要なんじゃないかな?と。Codable は associatedtype も Self も持たないだたの protocol だから、 Codable 型として existential になりますよね? struct Foo: Codable {} let foo: Codable = Foo() // OKprotocol P0 { } struct A : P0 {} func f<X: P0>(_ x: X) {} var a: P0 = A() f(a) // error<T: Encodable>を受けるAPIはありますがEncodableを直接受けるAPIは無いです。<T: Encodable>ではなくEncodableを直接受け取れば良いのでは?」とコメントしたのですが、受け入れられませんでした。AnySequence がなくせる話と絡んで、 Any<Codable> とかできるようになるのかな? 1> let a: Any = 42 a: Int = 42 2> func foo<T: Any>(_ x: T) { print(x) } 3> foo(a) 42Encodableではなく<T: Encodable>なのは、decode()側が<T: Decodable>を使う必要があり、そちらと一貫性を持たせる為だと言われた。よさそうですね! んで、 `Animal` が`bark()` メソッドをもってるとして、`Any<Animal>` 型の`animal` に対して `animal.bark()` を呼びだせるのは`Any<Animal>: Animal` なわけではなく、 Opening existentials のシンタックスシュガーだって考えればよさそう? let animal: Any<Animal> = Dog() // OK animal.bark() // ↑は以下のシンタックスシュガー // aの型はA。AはAnimalに準拠。 let a = animal openas A a.bark()
@ukitaka 前結局理解できなかったのだけどAny<Animal>がAnimalのextentialでなくなる理由とか嬉しい点って何ですか?func foo<T: SomeProtocol>(...) これに対して、Tの型はかなりカッチリしていてlet a = animal openas A // 将来opening existentialが入るとするa の型ってなんですか?test2 の型パラメータの <A> と同じって意味?protocol Animal {} struct Cat: Animal {} func bar<T: Animal>(_ x: T) { print(x) } let b: Animal = Cat() bar(b) // NG (edited)func foo<T: Sequence>(_ x: T) { print(x) } let a: AnySequence<Int> = AnySequence([2, 3, 5]) foo(a) // OK (edited)typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element>
https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials (edited)foo に Any<Sequence where .Iterator.Element == Element> という Existential Type を渡せるということになります。Animal が bar に渡せてもいいように思うのですがいかがでしょう?remove()実装、1個づつmoveInitialize()してるけど、まとめて出来るはず。 https://qiita.com/omochimetaru/items/f32d81eaa4e9750293cdremoveSubrange も O(n) だからいいじゃないかなと思ったりする https://developer.apple.com/documentation/swift/array/2884498-removesubrangemoveInitialize にしても O(n) なのは変わらないですね でも、ループを自分でやるより関数に畳み込むほうが最適化も期待できるし、コードはシンプルにできるので、ちゃんと動くなら書き換えたほうが良さそう。remove 系のメソッド全部確認して見たらやはりremoveLast だけ O(1) だった /// - source: A pointer to the values to copy. The memory region /// `source..<(source + count)` must be initialized. The memory regions /// referenced by `source` and this pointer may overlap.source and this may overlap だからExpressibleByRegularExpressionLiteral を話してる中で Chris Lattner が↓言ってるんですがおもしろくないですか? 2) I’d like to explore the idea of making // syntax be *patterns* instead of simply literals. As a pattern, it should be possible to bind submatches directly into variable declarations, eliminating the need to count parens in matches or other gross things. Here is strawman syntax with a dumb example: if case /([a-zA-Z]+: let firstName) ([a-zA-Z]+: let lastName)/ = getSomeString() { print(firstName, lastName) }let sortedScores: [Int] = ... if case /([\(0)-\(59)]+: let 不可)([\(60)-\(69)]+: let 可)([\(70)-\(79)]+: 良)([\(80)-\(100)]: let 優)/ = sortedScores { print("優: \(優.count)人") print("良: \(良.count)人") print("可: \(可.count)人") print("不可: \(不可.count)人") } a = someValue.someMember someValue.someMember = a mutateParameter(&someValue.someMember)
a = someValue[dynamicMember: "someMember"] someValue[dynamicMember: "someMember"] = a mutateParameter(&someValue[dynamicMember: "someMember"]) (edited)a = [2, 3, 5] a.empty? とか。subscript(dynamicMember:) 内で適宜書き換えてあげないとだめっぽいですね。 (edited)add_trick のままなだけで、 PyVal の subscript で読み替える実装にすれば addTrick にもできるわけですね。 // import DogModule // import DogModule.Dog as Dog // an alternate let Dog = Python.import("DogModule.Dog") // dog = Dog("Brianna") let dog = Dog("Brianna") // dog.add_trick("Roll over") dog.add_trick("Roll over") (edited)SOFT HYPHEN(U+00AD) かな? https://github.com/swift-script/swift-script/pull/18 Apple のドキュメントをコピペすると入ってる時がある。subscript には @_specialize が許可されてない? struct Foo { @_specialize(where T == Int) // OK func foo<T>(_ x: T) -> T { return x } @_specialize(where T == Int) // Error subscript<T>(x: T) -> T { return x } } (edited)subscript は元々ジェネリックじゃなかったけど、ジェネリックになったときに対応忘れたとか? (edited)_ つきだから、 stdlib で使用する要求が無いと実装されないかもしれないですね。@_specialize と言えば、昨日過去最多の @_specialize をつけました・・・。 https://github.com/koher/EasyImagy/blob/dev-0.4.0/Sources/EasyImagy/ImageSpecialized.swift#L2-L677@_specialize の付いてるコードは見つけられないかもしれないwRGBA で倍増して、それを組み合わせたのでこんなことに・・・。 (edited)@inlineable って @_inlineable として既に実装されているような?_ を外して正規仕様にするために提案を整理してるけど内容は現状あるやつ@inlineable ではできないけど、現状 @_versioned でできてるから、これは別の提案で出す、とか。@_versioned はわかりにくいから別の名前が良いって意見があった@_inlineable も最初 @_fragile だった。いずれにしてもパッとは分からないですねー。 1> let a = [2, 3, 5] a: [Int] = 3 values { [0] = 2 [1] = 3 [2] = 5 } 2> let f: (Int) -> Int = a.subscript Segmentation fault: 11 error: value of type '[Int]' has no member 'subscript' let f: (Int) -> Int = a.subscript ^ ~~~~~~~~~
Rintaro Ishizaki added a comment - 15 Sep 2016 4:51 AM Minimum repro: class C { subscript(x: Int) -> Void { return } } _ = C().subscriptsubscript のリファレンスを取る方法は封じられたんでしたっけ? (edited)class C { subscript(x: Int) -> Void { print(x) } } let idx = 12 let kp = \C.[idx] C()[keyPath: kp] keypath はインデックス固定のリファレンスと見れなくもないか? やりたいこと逆ですがw(Int) -> Element として高階関数に渡したいのでpublic class Disposable: DisposableConvertibleにしてユーザー側ではサブクラス作れないようにする (edited)Disposables.create になっているけど、Disposable.init() にしたかったんだよね // this is kind of ugly I know :( // Swift compiler reports "Not supported yet" when trying to override protocol extensions, so ¯\_(ツ)_/¯ /// Optimizations for map operator internal func composeMap<R>(_ transform: @escaping (Element) throws -> R) -> Observable<R> { return _map(source: self, transform: transform) }_map ってどこに定義されてるんだ?public class Disposable { public init() { // ここはクラスクラスタ } } private class CompositeDisposable: Disposable {} // ... その他諸々 protocol DisposableConvertible { var asDisposable: Disposable { get } } public extension Disposable: DisposableConvertible { var asDisposable: Disposable { return self } }_NSArrayCore ふくめ、このファイルの型は Foundation なしの stdlib で Foundation 系の型を扱うためのもの。みたいな感じだと思ってます。 (edited) func bind0<X: EventSourceProtocol>(modelStream: X) where X.Event == Model func bind1(modelStream: EventSource<Model>) (edited)bind1(modelStream: .of(3)) とか書ける事もあって便利bind1(modelStream: Property(3).asEventSource()) 変換が必要EventSource is EventSourceProtocol だから、曖昧なんだけどEventSourceProtocol.of と EventSource.of が曖昧になりそうだ .of() だけ書いてある場合 (edited)protocol MyProtocol { static var foo: Self { get } static var bar: Self { get } } final class MyClass: MyProtocol { static var foo: MyClass { return MyClass() } static var bar: MyClass { return MyClass() } } func func1<X: MyProtocol>(_ arg: X) {} func func1(_ arg: MyClass) {} func1(.foo)おもちprotocolはと解釈したprotocol AnimalProtocol { static func makeNya() -> Cat } ↑は Cat.makeNya() や Dog.makeNya() が呼べる事を示す定義であって、 AnimalProtocol.makeNya() という式で呼べる関数を定義するわけじゃないからいいけどprotocol AnimalProtocol {} class Cat : AnimalProtocol {} extension AnimalProtocol { static func makeNya() -> Cat { return Cat() } } こういう話ではなくて?Float 使いますか? Double 使いますか? Java だと double が普通だと思うんですが。Double ですかね?そもそも指定がなかったらデフォルトで Double 使われますし…Double のみ(もしくは Float のみ)の API ってありますっけ? 1> let a: Float = -3.14 a: Float = -3.1400001 2> abs(a) $R0: Float = 3.1400001var と func と init( で数検索して見たけど func だけFloatが1個少なくて軽く見て見たらFloatのページにだけ abs がなかったけどドキュメント作った人のせいかCGFloat なんですよねぇ。CGFloat は標準ライブラリーで使えなかったっけ?let a = 0.12 print(type(of: a)) // DoubleHashMap の loadFactor みたいなのないかと思ったけど、 https://docs.oracle.com/javase/jp/9/docs/api/java/util/HashMap.html#HashMap-int-float-Dictionary にはなかった・・・。 https://developer.apple.com/documentation/swift/dictionaryDouble を優先して使うのがいいのかな。
char が一遍に8バイト処理できる計算になるけどそんな話聞いたことないですね(聞いたことないだけかもしれないが
Float 優先で使ってたんだろうと考えてみたけど、Float になっていることがUITouch の分解能ってどれくらいなんだろう? (edited)UITouch の分解能が低いなら Float でも合理的か。CGFloat だから、 64bit 環境では 64bit 浮動小数点数になってると思う。Float とか普通かと。GLK_INLINE GLKMatrix4 GLKMatrix4Add(GLKMatrix4 matrixLeft, GLKMatrix4 matrixRight) { #if defined(__ARM_NEON__) float32x4x4_t iMatrixLeft = *(float32x4x4_t *)&matrixLeft; float32x4x4_t iMatrixRight = *(float32x4x4_t *)&matrixRight; float32x4x4_t m; m.val[0] = vaddq_f32(iMatrixLeft.val[0], iMatrixRight.val[0]); m.val[1] = vaddq_f32(iMatrixLeft.val[1], iMatrixRight.val[1]); m.val[2] = vaddq_f32(iMatrixLeft.val[2], iMatrixRight.val[2]); m.val[3] = vaddq_f32(iMatrixLeft.val[3], iMatrixRight.val[3]); return *(GLKMatrix4 *)&m;Float と Double のどちらが使われてるのかということですね。let a = 0.12 の場合 a が Double なので Double の方が一般的かと思いますね Float 使ってたのかを考えると、昔の iOS アプリ開発から惰性でそうしてるだけな気がしてきました。 (edited)public struct CGFloat { /// The native type used to store the CGFloat, which is Float on /// 32-bit architectures and Double on 64-bit architectures. public typealias NativeType = Double これ好きFloat ではなく字面の意味通りのFloatだから(震え声public typealias Float64 = DoubleなのでセーフFloat と Double って名前に統一感ないですよね。せめて Single と Double にするか、 Float32 と Float64 にするかしてほしい。 Swift が悪いわけじゃないけど。Float32 と Float64 作って、 Int みたいな位置の Float ほしい。Unsafe*Pointer<Int32>受ける関数とかありますけどね。 そもそもIntのサイズがネイティブに依存するメリットがいまいち分かっていないです。Int32 だろうが Int64 だろうが成り立つことがほとんどで、Int って書いてるときはオーバーフローは Logic failure だし、バイト数で壊れるようなコードはそもそも Int で書いちゃいけないかと。 (edited)Int32 って書いたコードは未来に Int128 が当たり前になった世界でも Int32 のままになっちゃうよ。Int64 とか Int32 使って、普通の環境は Int でよしなりにプラットフォームに合わせて使わせてくれる方が嬉しいかな派ですねInt32 でも Int64 でも変わらないでしょう派()Int が色々なビット数で動いてくれるとうれしいとは思う。Int32 で足りないシチュエーションって相当レアですよね…int が 32 bit 固定だけど、今の 64 bit 当たり前の時代でも 32 bit に縛られちゃってるのでは?int を long にするとか無理では。List を出したのは例であって、一般的に整数の意味合いで使われてる int がずっと 32 bit のままが辛いということです。int が 32 ビットのまま変わらず 20 年使われてますよ。UITableView のセルの数&インデックスは Int32 だけど Array の要素数&インデックスは Int64 で境界で全部明示的変換が必要ですとか辛くないですか?ArrayList 的なものを想定してると思うけど、 LinkedList とかを考えると話が変わってくるのでは? List は一般的なインタフェースだし。List が動的に要素を計算するとかあり得るのでは?( List のアップデート系のメソッドはオプションのはず)Int から Int32 とかに変換するわけで、その境界で気付くんじゃないかな?普段は Int として扱っていて、ビット数を気にする処理をする際に IntXX に変換で十分だと思うけどなぁ。Int32 とか Int64 とか色分けするのは変だと思うし、それが 32 ビット(に限らない XX ビット)に取り残される原因を生むと思う。size は int なんです。int を全部 long にしましょうとか無茶でしょ?int を 64 ビットにします(もしくは int で書かれてた API の大部分を long にします)とかやったら世界崩壊しそうな気が。 (edited)Int はプリミティブすぎて影響範囲が他よりめちゃくちゃ大きいんじゃないかなぁ。long を使ってたものが、 64 bit の世界では普通にとりあえ使えるようになってるのに、古い仕様にひきずられて永久に面倒な取り扱いを強要されるの辛そう。 (edited)fseek はそんな事になってますねlong なんだけど long が32bitの環境があるので64bit用のオーバーロードがOSによってはオリジナルで提供されているlong は Java の64 bit 整数の意図ね。wchar_t は 2バイト以上」っていうのも同じ問題をおこしましたよlong でポインタをハードキャストしてるところをまた直さないといけないのか・・・IntXX と Int でキレイに分かれてたらそんなにひどいことにはならない気が。Int 、固定したいケースは IntXX でうまくいくと思うんだけどなぁ。UITableView のセル数は概念として一般的な整数だと思うんですよね。ユースケースを考えたら 99% のケースではそれが Int32 に収まるとしても。 (edited)Int32 になって、概念を写し取っているべきだとすると Int になるんじゃないでしょうか。Intっていうのはほとんどのケースには便利だけど、、、という感じですね。Int32 等にすることに(僕が)違和感を感じるのかもしれません。FooProtocol か Foo の foo の実装をコメントアウトすれば動きます。少なくともエラーメッセージはおかしいと思います。 protocol FooProtocol { func foo(_ f: (inout Int) -> ()) } extension FooProtocol { func foo(_ f: (inout Int) -> ()) { var x = 0 f(&x) print(x) } } struct Foo : FooProtocol { func foo(_ f: (inout Int) -> ()) { var x = 42 f(&x) print(x) } } let a = Foo() a.foo { $0 += 1 }
inout-hof.swift:22:9: error: passing value of type 'Int' to an inout parameter requires explicit '&' a.foo { $0 += 1 } ^ & (edited)a.foo { $0 += 1; () } でも動きます。public typealias ArraySlice<T> = Slice<[T]> にするPR (edited)Slice を導入するのは大きな変更では?typealias Substring = Slice<String> (edited)ImageSlice の名前どうしよ。できるだけ ArraySlice を踏襲するようにしてたのに。ImageProtocol を導入して Image と ImageSlice で共通の実装を持たせるとこが今朝大分できたのに・・・。Slice にできないと思う。ArraySlice の名前が残るならそれでもいいけど、Subimage にするか ImageSlice にするかで迷って、 ArraySlice 的なアップデートができるからそっちに寄せて ImageSlice にした。ArraySlice おもしろくて、↓みたいな挙動する。 let a = [2, 3, 5, 7, 11] let b: ArraySlice<Int> = a[1...3] // [3, 5, 7] let c: ArraySlice<Int> = [3, 5, 7] b[1] // 3 c[0] // 3 b == c // true 9> b[b.startIndex..<b.endIndex] $R2: ArraySlice<Int> = 3 values { [1] = 3 [2] = 5 [3] = 7 } 10> c[c.startIndex..<c.endIndex] $R3: ArraySlice<Int> = 3 values { [0] = 3 [1] = 5 [2] = 7 }let a = Image<Int>(width: 4, height: 3, pixels: [ 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, ]) let b: ImageSlice<Int> = image[1...2, 1...1] // [[8, 9]] let c = ImageSlice<Int>(width: 2, height: 1, pixels: [8, 9]) b[1, 1] // 8 c[0, 0] // 8 b == c // true (edited)Slice<T> is T みたいなサブタイピングが追加されそうな予感The downside of having two types is the inconvenience of sometimes having a Substring when you need a String, and vice-versa. It is likely this would be a significantly bigger problem than with Array and ArraySlice, as slicing of String is such a common operation. It is especially relevant to existing code that assumes String is the currency type -- that is, the default string type used for everyday exchange between APIs. To ease the pain of type mismatches, Substring should be a subtype of String in the same way that Int is a subtype of Optional<Int>. This would give users an implicit conversion from Substring to String, as well as the usual implicit conversions such as [Substring] to [String] that other subtype relationships receive.Optional だけでなくさらなる黒魔術を導入しようとしてるのか?Substring is a String 無理だと思うんだけどな。let s = "abc" let t: Substring = s[s.index(s.startIndex, offsetBy: 1)...] // "bc" let i = t.startIndex print(t[i]) // "b" let u = String(t) print(u[i]) // "c"Optional はもう一歩踏み込んでいて、↓ができる。 class A { func foo() -> Int? { return nil } } class B : A { override func foo() -> Int { return 42 } }String と Substring は今はできない。Int も Int? のサブタイプにはなってなくて、↓はエラー。 9> let a: Int? = 42 a: Int? = 42 10> a.map { $0 * 2 } $R0: Int? = 84 11> let b: Int = 42 b: Int = 42 12> b.map { $0 * 2 } error: repl.swift:12:1: error: value of type 'Int' has no member 'map' b.map { $0 * 2 } ^ ~~~String は UnsafePointer<UInt8> に渡せるし。Substring should be a subtype of String in the same way that Int is a subtype of Optional<Int>. let str: String = "hello" strlen(str) // これはだめにして strlen(^str) // こうするみたいな。 (edited)UnsafePointer 周りは & がその役割してるのでは?in the same way that Int is a subtype of Optional<Int>. はもっと強い意味だけど、 the default string type used for everyday exchange between APIs. を解決するのにサブタイプは必要ないんじゃないか?っていう意見です。& も構文失敗してる気がする。↓ややこしい。 func f(_ p: UnsafePointer<Int>) { print(p[0]) } func g(_ p: UnsafePointer<[Int]>) { print(p[0].count) } var a = 42 var b = [2, 3, 5] f(&a) f(&b) g(&b)f(&b) が良くないinternal な後置演算子作って変換すればいいし^ で変換、今もできる。 prefix operator ^ prefix func ^(value: Substring) -> String { return String(value) } let s = "abc" let t: Substring = s[...] let u: String = ^t print(u)strlen(str) // 元のコード // 変換先のコード str.withUnsafeBufferPointer { strlen($0) }strlen(^substr) // 元のコード // 変換先のコード (^substr).withUnsafeBufferPointer { strlen($0) } になるのではなく? (edited)var ary = [2, 3, 5] func f(_ p: UnsafePointer<Int>) { } f(ary) // は ary.withUnsafeBufferPointer { f($0.baseAddress!) } // の sugar (edited)Array の内部のポインタをそのまま取り回せないようにするのがその意図なんじゃない?( Array をぶっ壊したり、ライフサイクルを超えて取り回したりできてしまうから)
This contrasts with Array, which can store its elements in either a contiguous region of memory or an NSArray instance if its Element type is a class or @objc protocol.import Foundation prefix operator ^ prefix func ^(value: Substring) -> String { return String(value) } let s = "abc" let t: Substring = s[...] let u: String = ^t print(u) print(strlen(u)) // OK: 3 print(strlen(^t)) // OK: 3ArraySlice → Array にせよ、変換してから渡すから問題ないのでは?mutating じゃないといけないときはダメだけど。import UIKit protocol ProtocolA {} class CustomCell: UITableViewCell, ProtocolA {} func hoge<T>(cellType: T.Type) where T: UITableViewCell & ProtocolA {} let typeA: (UITableViewCell & ProtocolA).Type = CustomCell.self let typeB: CustomCell.Type = CustomCell.self hoge(cellType: typeA) // error: generic parameter 'T' could not be inferred hoge(cellType: typeB) // ok こういうもんなのかfunc fuga(cellType: (UITableViewCell & ProtocolA).Type) {} fuga(cellType: typeA) // ok fuga(cellType: typeB) // ok ジェネリクスじゃなくしたら行けた。hoge(cellType: CustomCell.self)[UITableViewCell & ProtocolA).Type] に詰めてforEachで全部処理しようとしたら詰まったという感じですAny<Error> が許されるようになれば T: Error に Any<Error> を入れられるようになるのかな??typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> が成り立たないか。AnySequence 等の個別の実装をなくせない)だし、 typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> でもそのために早期 ABI 安定化ができないのだとすると、どちらかを諦めるしかなさそうですね。Any<FooProtocol> の形に統一するのがいいんじゃないかと思ってます。Self や associatefdtype を持つプロトコルは型として使えないのに、一部のプロトコルが型として使えることに気持ち悪さを感じてます。protocol は interface ではないので。protocol Functor { associatedtype A func fmap<FB where FB ~= Self>(f: A -> FB.A) -> FB }protocol<P1, P2> が Any<P1, P2> ではなく P1 & P2 に置き換えられちゃったみたいだけど、 generalized existential と整合がとれなくなっちゃってる気がするんだけどどうするんだろう・・・。 https://github.com/apple/swift-evolution/blob/master/proposals/0095-any-as-existential.mdAny<P1, P2> という表記で提案されていたのが最終的に P1 & P2 に変更されて採用されてるんです。The principle problem identified by community about the proposal is that "Any<T1, T2>” implies very strongly an “any of T1 OR T2” relationship
https://lists.swift.org/pipermail/swift-evolution-announce/2016-June/000182.htmlAny<P1 & P2 where ...> になるんじゃないかと思います。P1 & P2 は廃止される?Any<P1 & P2> の sugar として残る(残さざるおえない)んじゃないかなー。P1 & P2 is P1 になるってことですよね?まあゆるくなるだけだから互換性はありますが・・・。Any<P> よりも P が使われそうなのが微妙・・・P を型として書くのは existential であることを意識しないで使ってしまうので廃止してほしい。P を Any<P> と書かないといけなければ、 func foo<T : P>(_ x: T) が望ましいものが func foo(_ x: P) と書かれるケースが減りそう。 func foo(_ x: Any<P>) だと気持ち悪さがあるので。 (edited)class UITableView { var delegate: Any<UITableViewDelegate>? } これは受け入れられるのだろうかid<UITableViewDelegate> って書いてたんだよねprotocol と interface が概念的に違うことについて、公式ドキュメントでちゃんとした説明が必要だ・・・ (edited)Sequence<where Element == Int> みたいな 構文になる可能性もありますね。P1<where ...> & P2<where ...>Sequence<Int> にしないのかみたいな話を誘発しそうです・・・
protocol の static func は必要では? Argo の Decodable とかそれなしに成立しないし。 init は static func と同じだし。static func を持てるのは制約を表すために普通に必要だと思うけどなぁ。たとえば↓とか。 protocol Group { // 群 static func •(lhs: Self, rhs: Self) -> Self // 結合法則を満たす演算 static var identity: Self { get } // 単位元 var inverse: Self { get } // 逆元 } (edited)class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y)interface は protocol とは別の概念だから異なってていいのでは? (edited)Sequence<Element> じゃないの?ってとこだろうし。Sequence<Element> はでも結局不可能でSequence<where Element == Int> にしたとして、なんで Sequence<Int> じゃないの?ってなってSequence<Int, _, _>みたいにできるが…?protocol Sequence<Element> { ... } とはできないからやっぱり混乱するだけじゃないかなぁ。<>が出てくるから似た機能のGenericsが想起されて混乱する (edited)[ ] はArrayに使っちゃったしなあSequence[where .Element == Int]let array: [Sequence[where Element == Int].Type] = [Sequence[where Element == Int].self] んー、なんとかいけるか?let a: Int[] = [1] は未だに Fix-it 出してくれるという親切さ。Int[] の時代とかありましたね。 Java から来るとわかりやすかったけど、今となっては何がよかったのか・・・AnyIterator は struct なんだけど、値型捨て過ぎなのでもう class になった方がいいのでは? let a = [2, 3, 5] let i = AnyIterator(a.makeIterator()) let j = i print(i.next()) // Optional(2) print(j.next()) // Optional(3)struct なのに let で next できてることからも。next が mutating func じゃないという潔さ。class にしなかった意味がよくわからない。beginAsync has the following signature. func beginAsync(_ body: () async throws -> Void) rethrows -> Void However, I think it is better to forbid body to throw errors, that is to say, to change its signature to the followi...async -> Never? Theoretically, async -> Void means you're awaiting a result with only one possible value, but if you're not waiting at all, then there is truly no result, yes? ··· On Sun, Nov 12, 2017 at 9:27 AM, Yuta Koshizawa via swift-evolution < swift-evolution@swift.org> wrote: Sorry, I had got s...Norio_Nomuraになってしまってモヤモヤする…Username Yuta_Koshizawa People can mention you as @Yuta_Koshizawaomochimetaru なんですけどomochi.metaru になっていて@ の左の omochi.metaru になった。username 変更しちゃうと今までの @ と紐付かなくて困るって話です? (edited)Problems happen when someone who have posted mails to the ML in the past sign up using GitHub authentication. They hope to change their username, but cannot do it after once their accounts were created. I wish there were some additional explaination in the sign up screen, and to get a chance to change the username even if signup is done using github authentication.norio_nomuraにしておこうかな…joined にリネームされました。 [[2, 3], [5, 7, 11]].joined()joined() の文字見た気がするのに、無視してました...Array を用いるケース自体が稀な気がしますlet array: [Any] = [1, 2, 3, [4, 5, 6], [7, [8, 9]]]JSONSerialization でパースすれば↑のような Array が得られるでしょうが、どのようにネストされているか不定なネストした Array を処理するようなことは実用上ほぼないんじゃないでしょうか。Array をすべてつぶして flatten したいようなケースはあると思います。[[[1], [2, 3]], [[4, 5, 6]]] → [1, 2, 3, 4, 5, 6] とか。これならキレイに書く方法がありそうです。Data の write(to:options:) に倣って名詞を後ろにおいてもいいだろうということで write(to:formatting:) → write(to:format:) としました。ありがとうございました。 (edited)extrapolatedBy: を付与することで、 x, y が画像の範囲外にはみ出てしまった場合でも外挿してくれる API を提供しています。 let red = RGBA<UInt8>(red: 255, green: 0, blue: 0, alpha: 255) let pixel = image[x, y, extrapolatedBy: .filling(red)] // 例えば x = -1, y = -1 なら red が返される (edited)extrapolatedBy に与えているのは ExtrapolationMethod 型の値なのですが、次のように宣言されています。 enum ExtrapolationMethod<Pixel> { case filling(Pixel) // 画像の外側を与えられた値で埋める case edging // 画像の外側を最も近いエッジのピクセルで埋める case repeating // 画像の外側を画像の繰り返しで埋める case reflecting // 画像の外側を画像を鏡写しに折り返して埋める } (edited)edge, repeat, reflection に変えた方がいい気がしてるんですがいかがでしょうか。 (edited)edging を縁取り的な意図で使ってるんですが、無限の大きさを持った縁なので 縁取りのイメージと合わない気が。一方で、今のままだと -ing の統一感はあります。clampingToEdge とかになると思うんですがちょっと長すぎかなと。extrapolatedBy につながるので、 edge でも意味は通るかなぁとは思うのですが、悩ましいですね・・・。 repeating と reflecting は repeat, reflection にします。 filling は -ing でも変じゃないですよね? (edited)repeat が予約語だったから repeating にしたんだった・・・。loop とかかなぁ。.repeat では済むのか。repeat の方が一般的かな? CSS や GL も repeat だし。.repeat にします。GL_TEXTURE_WRAP_S Sets the wrap parameter for texture coordinate ss to either GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_MIRRORED_REPEAT, GL_REPEAT, or GL_MIRROR_CLAMP_TO_EDGE. constant かぁ。確かに filling(Pixel) → constant(Pixel) にしてもいいかも?extrapolatedBy: .constant(red) とか。 (edited)ExtrapolationMethodがconstantだとちょっと違和感ある気がしますね。 PaddingがconstantだとしっくりくるんですがextrapolatedBy を paddingBy にした方がいいかな?interpolatedBy とそろえたかったんだけど。paddedBy かな?interpolatedBy は .nearestNeighbor とか .bilinear とかが続く。padding というタームは浸透してるから paddingBy がいいけど、そうすると interpolatingBy も検討しないといけない・・・。resizedTo(width: ..., height: ..., interpolatedBy: ...) とかもあるからなぁ。enum ExtrapolationMethod<Pixel> { case filling(Pixel) // 画像の外側を与えられた値で埋める case edging // 画像の外側を最も近いエッジのピクセルで埋める case repeating // 画像の外側を画像の繰り返しで埋める case reflecting // 画像の外側を画像を鏡写しに折り返して埋める }InterpolationMethod です。subscript(x: Double, y: Double, interpolatedBy interpolationMethod: InterpolationMethod, extrapolatedBy extrapolationMethod: ExtrapolationMethod<Pixel>) -> Pixelsubscript のラベルは名詞を並べるだけで良さそうだから https://developer.apple.com/documentation/swift/dictionary/2894528-subscriptsubscript(x: Double, y: Double, interpolation: InterpolationMethod, extrapolation: ExtrapolationMethod<Pixel>) -> Pixel とか、 extrapolation → padding とかでいいかもだけどExtrapolationMethod を改造かなと思ってる。ExtrapolationMethod の case にも .repeat とかを用意しておいて .all(.repeat) の意味になるとか。で、 .all(.all(...)) とかはダメだから、 .repeat だけを分離した型も必要になる。.bilinear で横は nearestNeighbor で、とかあり得るよね。resizedTo の話ね。 (edited)InterpolationMethod と ExtrapolationMethod はそのままで、必要に応じて DirectedInterpolationMethod とかを追加するのが良さそう。 .both(.bilinerar), .each(x: .nearestNeighbor, y: .bicubic) とか。Dictionary の subscript[_:default:] に倣うなら subscript[_:_:interpolation:extrapolation:] とかかなぁ。resizedTo(width:height:) のラベルが難しい・・・DirectedInterpolationMethod でカバーできる想定で。enum じゃなくて sealed class だったら階層的にサブタイピングでうまいことわけられるんだけどね。InterpolationMethod SimpleInterpolationMethod NearestNeighbor Bilinear Bicubic DirectedInterpolationMethod Both(SimpleInterpolationMethod) Each(SimpleInterpolationMethod, SimpleInterpolationMethod)enum よりはキレイに整理できそう。open でない public なクラスを使えば Swift でも同じようなことはできる。resizedTo(width:height:interpolation:) は変な気がするけどなぁ。 interpolatedBy とかじゃなくても、 write(to:format:) と同じで別に気にしなくていい? (edited)To の後に width, height, interpolation が並列に並ぶのも気持ち悪い。resized(to: Size, interpolatedBy: InterpolationMethod) とすることもできるけど、そうすると Size の扱いが面倒。(Int, Int) の点に対して補間するだけでは?.filling はダメとか。さらに階層が増える・・・。.repeat とかと概念的に違うんだよなぁ。Bool とか)は .nearestNeighbor の境界上と同じようにどちらかに寄せるとかかな。.custom も考えてる。image[-100...100, -100...100, extrapolatedBy: .custom(...)]InterpolationMethod とかに case custom を追加する話じゃないの? (edited).custom((Double, Double) -> Pixel) と .custom((Int, Int) -> Pixel) を追加するだけなので大変ではない。.custom((Double, Double, (Int, Int) -> Pixel) -> Pixel) にしないとダメそう。(Int, Int) -> Pixel が要らないんだよな。.custom は保留しよう・・・(Int, Int) -> (Int, Int) にできるしね。.filling 以外はこれで表現できる。.filling のために ExtrapolationMethod がジェネリックになってるのもややこしいといえばややこしい。interpolation との組み合わせ爆発もするし。enum じゃ階層にしてすべて ExtrapolationMethod のサブタイプとかもできないしね。Int だったら 0 とかそういうこと?protocol を public にしないといけない・・・。enum Foo { case foo case bar case piyo(String) case fuga(Int) static var specificFuga1 = Foo.fuga(1) } Foo.specificFuga1 こんな感じかなPixel プロトコルを作ってしまうとUInt8 とか Float にプロトコルを後付しないといけないしRGBA<Channel> とかは付けれないし RGBA<UInt8> とかだけに付けるには conditional conformance がいる。_Summable っていうプロトコルを持っていて_Summable が zero みたいなのを持っててroteated(by:) では斜めになったときの背景を zero で埋めてる。( gyb で各型ごとに extrapolatedBy: .zero) を付与して呼ぶメソッドを大量生成してる。)rotated(by:) は使えなくてrotated(by:extrapolatedBy:) じゃないと使えない。rotated の interpolatedBy 省略で .bilinear が使われるけど、それ以外では .nearestNeighbor が使われるとかなってる。.nearestNeighbor ですらなくて、それ相当の計算だけど。 InterpolationMethod が使えるのは _Summable だけだから。( Bool に .bilinear しようがない) (edited)Numeric でもいけなくて、 UInt8 とか普通に足して平均とったらオーバーフローするからInt や Double に変換する処理とかがあって、そのあたりが全部 _Summable で抽象化されてる。複雑・・・。AnyImage も元は要らなかったんだけど、 image[-100...100, -100...100, extrapolatedBy: ...] の結果を ImageSlice で返そうとすると、 ImageSlice が内部に持つのが Image だけじゃダメになって、 ImageSlice が AnyImage を持つ必要に迫られた。internal なメソッドでも @abiPublic でインライン化できるのか。let double: Double = 3.123456 // 3.123456 var dec1 = Decimal(double) // 3.123456000000000512 var dec2: Decimal = Decimal() NSDecimalRound(&dec2, &dec1, 4, .bankers) dec2 // 3.1235 隠蔽してみたextension Decimal { func rounded(exponent: Int, roundingMode: RoundingMode = .bankers) -> Decimal { var me = self var result = Decimal() NSDecimalRound(&result, &me, exponent, .bankers) return result } } dec1 // 3.123456000000000512 dec1.rounded(exponent: 4) // 3.1235NSDecimalNumber, an immutable subclass of NSNumber, provides an object-oriented wrapper for doing base-10 arithmetic. An instance can represent any number that can be expressed as mantissa x 10^exponent where mantissa is a decimal integer up to 38 digits long, and exponent is an integer from –128 through 127.Decimal は NSDecimal で c 構造体 みたいです。let dec1 = Decimal(double) // 3.123456000000000512 let n = (dec1 as AnyObject) type(of: n) // __ObjC.NSDecimalNumber.Type_ObjectiveCBridgeable っていう ReferenceConvertible の一個下のレイヤーに準拠してますね。let double1: Double = 123456789000000000 let double2: Double = 1 print(String(format: "%.20f", double1)) print(String(format: "%.20f", double2)) print(String(format: "%.20f", double1 + double2)) let decimal1 = Decimal(string: "123456789000000000")! let decimal2 = Decimal(string: "1")! print(decimal1) print(decimal2) print(decimal1 + decimal2)123456789000000000.00000000000000000000 1.00000000000000000000 123456789000000000.00000000000000000000 123456789000000000 1 123456789000000001let decimal1 = Decimal(string: "123456789012345678901234567890")! let decimal2 = Decimal(string: "0.0000000000000000000000000001")! print(decimal1) // 123456789012345678901234567890 print(decimal2) // 0.0000000000000000000000000001 print(decimal1 + decimal2) // 123456789012345678901234567890let decimal1 = Decimal(string: "123456789012345678901234567890")! let decimal2 = Decimal(string: "0.0000000000000000000000000001")! print(decimal1) // 123456789012345678901234567890 print(decimal2) // 0.0000000000000000000000000001 let decimal3 = decimal1 + decimal2 print(decimal3) // 123456789012345678901234567890 print(decimal1 == decimal3) // true!let decimal1 = Decimal(string: "1234567890123456789012345678901234567890")! let decimal2 = Decimal(string: "1")! print(decimal1) // 1234567890123456789012345678901234567890 print(decimal2) // 1 let decimal3 = decimal1 + decimal2 print(decimal3) // 1234567890123456789012345678901234567890 print(decimal1 == decimal3) // true! fileprivate var __exponent: Int8 fileprivate var __lengthAndFlags: UInt8 fileprivate var __reserved: UInt16 public var _mantissa: (UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16) 160bitimport Foundation print(MemoryLayout<Decimal>.size) // 20let decimal = Decimal(string: "1234567890")! decimal._exponent // 1 decimal._length // 2 decimal._isNegative // 0 decimal._isCompact // 1 decimal._reserved // 0 decimal._mantissa // (.0 52501, .1 1883, .2 0, .3 0, .4 0, .5 0, .6 0, .7 0)Decimal.greatestFiniteMagnitude // 3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Decimal.greatestFiniteMagnitude._mantissa // (.0 65535, .1 65535, .2 65535, .3 65535, .4 65535, .5 65535, .6 65535, .7 65535) Decimal.leastNonzeroMagnitude // 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 Decimal.leastNonzeroMagnitude._mantissa // (.0 1, .1 0, .2 0, .3 0, .4 0, .5 0, .6 0, .7 0) (edited)func truelyLeastDecimal() -> Decimal { var x = Decimal(string: "0.1")! var r = Decimal() NSDecimalPower(&r, &x, 128, .plain) return r } func p(_ d: Decimal) { print("=====") print(d) print(d._mantissa) print(d._exponent) } p(Decimal.leastNormalMagnitude) p(truelyLeastDecimal()) /* ===== 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 (1, 0, 0, 0, 0, 0, 0, 0) -127 ===== 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 (1, 0, 0, 0, 0, 0, 0, 0) -128 */ Decimalには定義みあたらないけど、NSDecimalNumberのexponentは Decimal.leastNormalMagnitude > truelyLeastDecimal() こうなってしまうのでCustomStringConvertible じゃないものでも文字列に埋め込めるの良くなくないですか?何でもとりあえず文字列にしたいニーズはあるとして、それはデバッグ用にそういう関数を用意すれば良いだけに思います。 https://qiita.com/koher/items/6c855ddbda8797af4605CustomDebugStringConvertible を分けてる意味がなくなっちゃってる気が。 print が Any をとれるのも微妙。Optional は CustomDebugStringConvertible だったと思うからString.init(describing: Any) だったはずなんでString.init(describing: x) って書けばいいんじゃねえかと"\debug() " みたいなのでもいいけど 1> let a: Int? = 42 a: Int? = 42 2> a.debugDescription $R0: String = "Optional(42)" 3> a is CustomStringConvertible $R1: Bool = true 4> a is CustomDebugStringConvertible $R2: Bool = true 5> a.description error: repl.swift:5:1: error: value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'? a.description ^ ? 5> func debugPrint<T: CustomDebugStringConvertible>(_ value: T) { print(value) } 6> debugPrint(a) Optional(42) 7> func safePrint<T: CustomStringConvertible>(_ value: T) { print(value) } 8> safePrint(a) error: repl.swift:8:11: error: value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'? safePrint(a) ^ (edited)Optional は CustomStringConvertible ではないけど CustomDebugStringConvertible ではある(↑)。 (edited)CustomDebugStringConvertible だけ書いてある。 https://developer.apple.com/documentation/swift/optional (edited)extension Optional : CustomDebugStringConvertible where Wrapped : CustomDebugStringConvertible { ... }String.init(describing) で変換すればいいのか。 (edited)public init<T: TextOutputStreamable> (stringInterpolationSegment expr: T) public init<T: CustomStringConvertible> (stringInterpolationSegment expr: T) public init<T: TextOutputStreamable & CustomStringConvertible> (stringInterpolationSegment expr: T) (edited) public init<T>(stringInterpolationSegment expr: T) { self = String(describing: expr) } CustomDebugStringConvertibleのケースはこれに行きそう (edited)is で true はバグな気がする。 8> let b: CustomStringConvertible = a error: repl.swift:8:34: error: value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'? let b: CustomStringConvertible = a ^ ! 8> let c: CustomDebugStringConvertible = a c: CustomDebugStringConvertible = { payload_data_0 = 0x000000000000002a payload_data_1 = 0x0000000000000000 payload_data_2 = 0x0000000000000000 instance_type = 0x0000000101416700 libswiftCore.dylib`InitialAllocationPool + 80 protocol_witness_0 = 0x00000001013d1b78 libswiftCore.dylib`protocol witness table for <A> Swift.Optional<A> : Swift.CustomDebugStringConvertible in Swift }String(describing:) か debugDescription すればいいんだから、直接埋め込める必要はない気がします。あえて言えば初心者が混乱するくらい??String(desciribing:) 使ったら?」って出せばいいからそこはダイジョブそう
enum に偏りすぎな気が。 https://github.com/apple/swift-evolution/blob/master/proposals/0194-derived-collection-of-enum-cases.mdBool は ValueEnumerable でいいし、 ValueEnumerable な associated value を持つ case があってもその enum は ValueEnumerable でいい気がする。enum Foo { case bar case baz(Bool) } は ValueEnumerable になりたかったりしないかな・・・。The compiler will synthesize an implementation of ValueEnumerable for an enum type if and only if: - the enum contains only cases without associated values; - the enum is not @objc; - the enum has an explicit ValueEnumerable conformance (and does not fulfil the protocol's requirements).ValueEnumerable のときは生成で良い気が。 Codable が Codable なプロパティを持っている場合と同じように。Foo の ValueCollection が得られれば良いのでは?for x in Foo.allValues { } みたいに書けるようになってもif x == .bar { ... } if case .baz(false) = x { ... } こういう感じか。struct Card : ValueEnumerable { let suit: Suit // Suit : ValueEnumerable let number: Number // Number : ValueEnumerable } Card.allValues (edited)Card.ValueCollectionTo limit our scope, we are primarily interested in simple enums—those without any associated values—although we would also like to allow more complicated enums and structs to manually participate in this mechanism.Int に精度を明示すべきかどうかみたいな話とも関係してるんじゃないかなぁ。 Int は ValueEnumerable であってほしくないけど(概念としての整数は無限の要素を持つので) UInt8 は ValueEnumerable であってほしい。同様に考えると Int32 や UInt32 も ValueEnumerable であってほしいけど、 Int を associated value に持つ enum に ValueEnumerable であってほしいわけじゃなくて、 Int と Int32 の使い分けはやっぱり必要な気がする。Never の bottom 化早く・・・
allValues ができる Int64 とできない Int を区別しておきたいですねぇ。Int64 だと count が Int で表せないという話は別として)Int32 か Int64 かの選択が揺らぐようなのをなくしたいです。Int32 等に変換して使いたいイメージですね。Int にはビット演算とかオーバーフローとかもしたくないです。IntXX でやって、アプリ用に Int を使った型に変換するのか、それともエンティティレベルで Int にして、 DB に保存するときにエラーにしてしまうのか。Int に Java の BigInteger とか Ruby の整数のような無限精度になってほしいわけではないですが、コードの書き手が単なる整数を意図しているのかそうではないのかを型として区別しておきたいという感じですね。UInt8 だとオーバーフローを利用した計算とかもよくやると思うんですけど、 Int32 ではそれは OK だけど Int ではやりたくないです。そこは明示的に Int32 に変換してから処理したいです。Int が実行環境によって精度が変わるかどうかは別として、 Int32 や Int64 より strict な型がほしいという感じですね。Int が 32 bit に固定されていたとしても、 Int に対してオーバーフローを利用した演算はしたくないです。Intが無限長で有限長を使いたいならInt32然りInt64を使う、というのが個人的には一番しっくり来るInt が現実的に 32bit や 64bit なのには不満はないです。無限精度にはなってほしくない。ValueEnumerable の例で言えば func combination<T: ValueEnumerable, U: ValueEnumerable>(_ a: T.Type, _ b: U.Type) -> [(T, U)] みたいな関数があったときにUInt8 や Int32 や Int64 は ValueEnumerable だけど Int は違ったらcombination(Int, Bool) みたいなのを防げます。combination(UInt8, Bool) はやりたいですし、 combination(Int32, Bool) も同様に認められるべきだと思います。Int に BigInt (無限精度)になってほしいわけではなくて、今のままであってほしいと思います。Int は単に整数であってほしいだけだと思うので、基本的には制限された Int を使ってInt32 特有の操作をするときだけ明示的に Int32 に変換して使えたらいいんじゃないかと思います。Int は最もよく利用する型なのでパフォーマンスも求められると思います。 BinaryInteger として existential で扱うのは許容できないかと。たとえば、 count は Int を返しますが、これは整数を表していると思います。しかし、これが BinaryInteger になるのは許容できないのではないかと。Int や UInt に ~ が使えるのとかは違和感を感じますね。 1> let n: UInt = 0 n: UInt = 0 2> ~n $R0: UInt = 18446744073709551615 3> ~(UInt64(n)) $R1: UInt64 = 18446744073709551615 とすべきかと。Int のビット数を固定しなかったのが良くなかったという意見なのに対して、僕はそれでよかったと思ってるところでしょうか。そして、その裏には、 Int は整数だからという気持ちがあります。Int のビット数が固定されないことで、↑のようなビット演算が良くない行為となり、明示的な変換が求められます。ただ、もう少し踏み込んで Int には ~ や &+ 等はなくてよかったと思います。Int はほぼ最大値を気にしなくてよい整数なんですよね。 BigInteger が無限精度だと言っても実際には無限ではなくて、↓のような計算をすると精度が足りません。 $ irb irb(main):001:0> 2 ** (2 ** (2 ** (2 ** (2 ** 2)))) (irb):1: warning: in a**b, b may be too big => Infinity (edited)BigInteger で何であれ気にしないといけない、かもしれません。 (edited)Int だろうが BigInteger だろうがあまり関係なくどちらも整数と思えるという感じです。2 ** (2 ** (2 ** (2 ** 2))) と入力すると楽しいことになります。irb(main):012:0> a.class => Bignum irb(main):013:0> a = 2 ** a (irb):13: warning: in a**b, b may be too big => Infinity irb(main):014:0> a.class => Float2 ** (2 ** (2 ** (2 ** (2 ** 2)))) (edited)BigInteger の限界を突破するということです。BigInteger が必要そうですねぇ。AnyIterator が Sequence なのってなんでですか? https://developer.apple.com/documentation/swift/anyiterator
for x in (AnyIterator { hoge() }) {} これができたら楽Sequence としての責務を果たせてない気が。 let i = AnyIterator([2, 3, 5].makeIterator()) let i2 = i.makeIterator() print(i.next()) // 2 print(i2.next()) // 3 let i3 = i.makeIterator() print(i3.next()) // 5AnySequence { AnyIterator { hoge() } }になるのかなIteratorProtocol : Sequence もほしくならない?Sequence と IteratorProtocol の責務が同じにならない?struct Countdown: Sequence, IteratorProtocol { var count: Int mutating func next() -> Int? { if count == 0 { return nil } else { defer { count -= 1 } return count } } }IteratorProtocol との役割分担がよくわからない・・・。extension Array { /// Sequence of all sub sequences of specified `length`. public func subSequences(of length: Int) -> SubSequenceSequence<Element> { return SubSequenceSequence(array: self, length: length) } みたいなのを書いてたんですがSubSequenceIteratorをSequenceにしてそれを返すのも良いのか。Iteratorを返すと複数回呼んだ時に使用中のが返ってきたりする可能性も読み取れるような。 でもSequecne自体も複数回走査が保証されてないなら……Sequence が makeIterator で消費されることがありなら、 extension IteratorProtocol { func makeIterator() -> Self { return self } } 的な実装が可能で、すべての IteratorProtocol の実装は Sequence として振る舞えることになる。