Guild icon
swift-developers-japan
main / swift-2
話題が複数あるときの待避所
Avatar
omochimetaru 4/27/2017 3:32 AM
@tarunon wt は、 Cat が Protocol に準拠した時の、witness-tableへのポインタ。
3:32 AM
例えば Dog が Protocol に準拠した時 のテーブルは別に存在していて
Avatar
だから、呼び出せる関数はもう決まっていて
Avatar
omochimetaru 4/27/2017 3:32 AM
でもその2つのテーブルの、エントリの並びは、 Protocolの定義に従って揃ってる。
Avatar
テーブルの探索は浅くて済むんだよね
Avatar
omochimetaru 4/27/2017 3:32 AM
探索はしない。
3:32 AM
インデックス番号だけ。
3:32 AM
テーブルの2番目、とか、テーブルの3番目、とか (edited)
3:33 AM
静的なインデックスにコンパイルされてる。
Avatar
じゃあfunc hoge<Foo: Protocol>(foo: Foo)と、fucn (foo: Protocol) だと
3:33 AM
この関数の中で使われるfooが呼び出す関数は
3:33 AM
テーブルの探索の有無の差が生まれる
Avatar
omochimetaru 4/27/2017 3:34 AM
あ、いや、
3:34 AM
後者の場合も、
3:34 AM
Protocol 型の変数っていうのは
3:34 AM
結局、 (x, wt, xt) の 3つのフィールドを持つ 特殊な型なんだよね (edited)
Avatar
んー
Avatar
omochimetaru 4/27/2017 3:34 AM
だから結局同じ。
Avatar
おお
3:35 AM
じゃあ僕が最初に言っていた
3:35 AM
Protocol型の変数は暗黙的にGenerics型の変数と同じ状態になる?
3:35 AM
というが既に存在している、ということ
Avatar
omochimetaru 4/27/2017 3:35 AM
Associated Type が無い場合に限っては、YES (edited)
Avatar
おおお~
3:35 AM
理解完了
3:35 AM
あざっす
Avatar
omochimetaru 4/27/2017 3:35 AM
逆に言うと、
3:35 AM
Associated Typeがある場合でも
3:36 AM
引数には渡す事が今もできるわけで
Avatar
そうだね
Avatar
omochimetaru 4/27/2017 3:36 AM
その時にはさっきの3タプルになってるわけだから
3:36 AM
そもそも既にExistentalのバイナリ表現はこの3タプルで
3:36 AM
完成してるやんけ
3:36 AM
っていうのが
3:36 AM

導入

Swiftでは通常のプロトコルは変数の型として使用することができますが、 型パラメータ(associated type)を持つジェネリックなプロトコルの変数は作れません。 非ジェネリックな例 ```swift prot...
3:36 AM
この記事で最終的にぶつかってる謎で
3:37 AM
だから、パフォーマンスのために あえて やってないのかなあ?って話をした。
Avatar
ふーむ
3:37 AM
構文が完成してなかっただけでは?という気もしている
Avatar
omochimetaru 4/27/2017 3:37 AM
そうだね、SILの時点で表現可能な文法が無かったから、それもある。
3:38 AM
技術的にはできるけど作らないといけない部品がいっぱいあるのは確かだからそれで止まってるだけなのかもしれない。
Avatar
namespaceを作りたいときってclassとstruct(or enum)どちらを使いますか? struct API { private init() { } struct Request { private init() { } struct GetDayOfWeekStories: APIRequest { (edited)
Avatar
case なし enum だとどうやってもインスタンス化できないので、 private init 書く必要ないから いいんじゃないかと思ってます。
🙂 1
Avatar
おお、たしかに (いま、private init() { fatalError() }くらいにした方がいいかなと思ってました)
Avatar
/// Namespace for diagnostics enum diag {} extension diag { // メンバー群 ... 実際にはすべてのメンバーを extension に実装することにより、 case を書けなくするということをやっています。 (edited)
Avatar
なるほど。 ありがとうございます。
Avatar
Swiftの??って、もしかしてコンパイルすごい遅いんでしょうか
1:31 PM
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 ) }
1:31 PM
こういう関数があるのですが、この関数のコンパイルに30秒ほどかかってしまっていて
1:32 PM
以前はerrorMessageに代入しているところをmessageに直接書いていたのですが、複雑すぎるとSwiftコンパイラに怒られてしまったので分けたのですが
1:33 PM
他の似たような関数では遅くないので、??が原因なのかなあto
1:33 PM
思ったのですが
Avatar
applideveloper 6/10/2017 1:34 PM
?? あるケースとないケースで、計測してみては?
Avatar
とりあえず??を!にしてみたところありえん早くなりました
1:35 PM
認識はされていますが、なかなか直りませんねー。
Avatar
なるほど、認識はされているのですね...
1:35 PM
代わりの書き方とかあるんでしょうか(あまり良くわかってない)
Avatar
??が常に遅いわけではなく、遅くなるケースがちょくちょくある、ということですよね?
Avatar
そうですね
Avatar
もう少し細かく分離して変数で受けるだけでも速くなりそうな気がしました。 (edited)
Avatar
なるほど
Avatar
これリテラルと混ざって書いてるのが原因の一端なので、Optionalが関わるところを隔離するだけで楽になるはず
Avatar
var errorMessage:String = "" errorMessage = "エラーメッセージ:\n" errorMessage += errorMsg ?? "不明なエラー(iMast)" errorMessage += " (" errorMessage += String(httpNumber ?? -1) errorMessage += ")\n\nエラーメッセージに従っても解決しない場合は、アプリを再起動してみてください。" のようにしたら早くなりました、ありがとうございます
Avatar
大体リテラルいくつかとオペレーターいくつかと並べると、組み合わせ爆発して遅くなります。これは??に限らず、有名なのだとBoolでorを並べたら大変なことになる、とか。
Avatar
なるほど
1:40 PM
無理に一行で書こうとせず、何行かに分けたほうがいいんですね
Avatar
人間が読むのが大変なのは機械も大変だったりします。
Avatar
なるほど
Avatar
+=で連結ではなく、??絡むところだけ隔離して、()で文字列組み立てた方がベターに思いました。
1:44 PM
バッククォート()と書いたのにバッククォートの記号消えちゃいました。
Avatar
\()←こいつ、中にちょっと式書くと音を上げるのであまり使ってないw
👀 2
Avatar
うーん、\()どうも個人的に読みにくいんですよね
Avatar
文字列補間は他のモダンな言語でも大抵取り入れていて一般的に読みやすい気がしますが、それが嫌でも += ではなく、+でつなげるのが良いかなと思いました。
1:50 PM
名前は適当ですが、こう分離して、 let errorMessage に +で連結して代入 let errorMsg2 = errorMsg ?? "不明なエラー(iMast)" let httpNumber2 = httpNumber ?? -1
Avatar
なるほど
Avatar
多国語対応するつもりがなくても、Localizeファイル作っておいて、swiftgenなりR.swiftなりで、文字列を静的型で評価できるようにしておいた方が良い、というのもあった。
Avatar
ですね。
1:52 PM
一覧されて見やすく管理しやすくもなりますね( ´・‿・`) (edited)
Avatar
%@や%iだと、Stringを作るための関数群として提供されるので非常に楽ですね。おすすめです。
Avatar
本当に多言語対応するつもりが無いのか、単に直近で無いだけのか、怪しいこともあるので、そういう意味でも、分離しておいた方が無難かなと思っています、分離も大した手間ではないので。 (edited)
Avatar
なるほどー
Avatar
omochimetaru 6/10/2017 1:56 PM
なんか
1:56 PM
リテラルと足し算が絡んでると踏みやすい
1:57 PM
感じがしている
1:57 PM
配列リテラルに並べてjoinでくっつけるとかでも軽くなるかも
Avatar
Localizeファイル使うと、 いずれにせよ バッククォート() じゃなくて String(format: "", a, b) とかになりますね。 (数値絡んだりすると、 String.localizedStringWithFormat("", a, b) ) 今回の場合、これだけで速くなりそう。 (edited)
Avatar
なるほど、ありがとうございます
Avatar
applideveloper 6/15/2017 1:43 PM
‪アプリとWebが同じ機能をもっていて、万が一アプリで、ViewControllerが初期化できないとき開発ではfaitalError or nilでもいいが、本番ではnilで返して、遷移するコードでユーザーに遷移できません、その機能は現在使えませんでしたって伝えて戻るか、同じWebのページが表示できればバグ修正するまでWebを表示するのがいいんじゃないかと思うのですが、皆さんどうしてます?全部落とすとユーザーがもう一度アプリを開かない限りCrashlysticsにエラーが送られないので、障害検知できない気がするのですよ (edited)
Avatar
omochimetaru 6/16/2017 3:44 AM
@applideveloper #ui-ux で返信しました
Avatar
omochimetaru 6/21/2017 2:09 AM
Turns out that Tesla isn't a good fit for me after all. I'm interested to hear about interesting roles for a seasoned engineering leader!
Retweets
128
Likes
219
🚗 3
2:09 AM
クリスラトナーがテスラ辞めそう
Avatar
マジかよw
Avatar
@clattner_llvm Let's all fix code signing together 🤗
Avatar
ええっw
Avatar
セグフォで落ちる自動運転車が生まれずに済んだのかもしれない。
Avatar
omochimetaru 6/21/2017 2:12 AM
めちゃめちゃエラー出る自動運転車見たかったンゴ
Avatar
これでマイクロソフトとか行ったらおもしろそう。
Avatar
omochimetaru 6/21/2017 2:14 AM
リプライちょこちょこありますね
Avatar
GoogleがSwift採用はないだろうけど、Microsoftならワンチャンあるかも?
Avatar
omochimetaru 6/21/2017 2:16 AM
そして産まれるSwift.NET
Avatar
AWSとか行ってサーバーサイドSwiftもっとやってほしい
Avatar
そのうちもとの Swift がわざわざ Swift Native って呼ばれる流れか
Avatar
omochimetaru 6/21/2017 2:17 AM
www
Avatar
Microsoftに行ってWIndows対応→Obj-CとSwiftみたいにC#と連携できるように→これまでのWindows資産を活かしてSwiftで開発できるように
2:19 AM
ができればパイが広がりそう
Avatar
列強がドコドコリプライ送っててめっちゃおもろい
Avatar
omochimetaru 6/21/2017 2:20 AM
わかる
Avatar
My resume is easy to find online. 7 years of Swift experience 👍
2:33 AM
けっこうしっかり辞めそう
Avatar
omochimetaru 6/21/2017 2:36 AM
Swift(スウィフト)は、アップルのiOSおよびmacOS、Linuxで利用出来るプログラミング言語。Worldwide Developers Conference (WWDC) 2014で発表された。
2:36 AM
表に出てから3年しか経ってないから
Avatar
4年かけて作ってたんやなあ
Avatar
omochimetaru 6/21/2017 2:36 AM
Appleは4年間開発してたんだ
Avatar
iOSいくつの頃よ
2:37 AM
4とかか
Avatar
ARC無い頃から作ってたの?
Avatar
omochimetaru 6/21/2017 2:37 AM
3.2 Wildcat 2010年4月3日 iPad(第1世代)
Avatar
I started work on the Swift Programming Language (wikipedia) in July of 2010. I implemented much of the basic language structure, with only a few people knowing of its existence. A few other (amazing) people started contributing in earnest late in 2011, and it became a major focus for the Apple Developer Tools group in July 2013.
Avatar
omochimetaru 6/21/2017 2:37 AM
iOS3.2が2010年に出てる
Avatar
2010 ってまだ iOS そんな化石みたいなバージョンだったのか…
Avatar
omochimetaru 6/21/2017 2:38 AM
ARCがiOS4からだから
Avatar
これswiftに合わせてObjCにARC作られた説、割と罷り通る
Avatar
omochimetaru 6/21/2017 2:38 AM
MRCのときからやってたのか
2:38 AM
あ〜〜〜
Avatar
ありえますね
Avatar
omochimetaru 6/21/2017 2:38 AM
LLVM側の改修が並行してObjCにおすそ分けされていたのか
Avatar
おお
2:39 AM
納得感あるなたしかに
Avatar
norio_nomura 6/21/2017 3:12 AM
"Automatic Reference Counting" という文字列が含まれる swift と clang の最初のコミット。 2011年4月15日 7:05:07 JST https://github.com/apple/swift/commit/3cce5623cb84cb839923ae4ac579ae50d18a0740 2011年6月16日 6:21:53 JST https://github.com/apple/swift-clang/commit/8246702d0cbecc3fd5748b58614ffed7ad9e04a5 (edited)
3:14 AM
この時のSwiftのリポジトリにARCの実装が含まれているかどうかはよくわからないな。
3:17 AM
clangにARCの実装が入った時のコミット 2011年6月16日 8:02:42 JST https://github.com/apple/swift-clang/commit/f85e193739c953358c865005855253af4f68a497
Language-design credit goes to a lot of people, but I particularly want to single out Blaine Garst and Patrick Beard for their contributions. Compiler implementation credit goes to Argyrios, Doug,...
Avatar
norio_nomura 6/21/2017 3:28 AM
この時のSwiftのリポジトリにARCの実装が含まれているかどうかはよくわからないな。
その時点のSwift Language Referenceを見るとARCの実装とか影も形もなさげ。 https://github.com/apple/swift/blob/3cce5623cb84cb839923ae4ac579ae50d18a0740/docs/LangRef.html
swift - The Swift Programming Language
Avatar
omochimetaru 6/21/2017 3:30 AM
typealias DataSearchFlags : oneof { None, Backward, Anchored }
3:30 AM
enumもどきみたいなやつおる
Avatar
norio_nomura 6/21/2017 3:41 AM
SwiftKickoff.rtf https://github.com/apple/swift/blob/3cce5623cb84cb839923ae4ac579ae50d18a0740/docs/SwiftKickoff.rtf
More Open Discussion
More concrete goals, plans, schedule through WWDC, etc.
How/when to engage with the rest of the company, when to go more public.
(edited)
swift - The Swift Programming Language
3:43 AM
この時点ではApple社内でもSwiftの存在は知られていなかったぽいね。 (edited)
Avatar
omochimetaru 6/21/2017 3:43 AM
ほお〜〜
Avatar
norio_nomura 6/21/2017 3:44 AM
ARCがSwift発祥というのは無理がありそう。
Avatar
違ったか~
Avatar
omochimetaru 6/21/2017 3:44 AM
あーなるほど。
Avatar
Tesla's autopilot software head quits in less than six months https://t.co/B8qvSrWDnS Via @Reuters #companynews
4:49 AM
確定っぽい。
Avatar
omochimetaru 6/21/2017 4:50 AM
Tesla Inc (TSLA.O) said the head of its autopilot software, Chris Lattner, left the company in less than six months since joining the electric carmaker.
4:50 AM
head of って、リーダーだったのかな?
Avatar
VPじゃなかったけ
4:50 AM
VP of Autopilotみたいなんだったきがする
Avatar
omochimetaru 6/21/2017 4:51 AM
ほー
Avatar
Teslaは自動運転の取り組みを率いる新しい副社長を獲得した。Chris Lattnerだ。そのAppleからの離職は本日(米国時間10日)の早い時間に発表されたばかりだ。LattnerはAppleで11年働いた。その主な貢献はAppleの最新のプログラミング言語であるSwiftの開発である。Swiftは初心者がm..
Avatar
omochimetaru 6/26/2017 4:13 AM
この新しいsubscriptめちゃくちゃ便利そう。 https://t.co/mN88tMyEoq
4:14 AM
@omochimetaru @koher いや、それはそうだけど、dictionary[$0]が値の存在が保証されてるならdefaultは0じゃなくてNeverが妥当じゃない?って話
4:14 AM
@tarunon [default: ] を指定するのは、値の存在が保証されてない場面では??
Avatar
Non Optionalにするための用法だから
4:14 AM
+=するなら値保証されててもdefault要るっしょ
4:15 AM
dict[key]! += 1 ってできたっけ?
Avatar
omochimetaru 6/26/2017 4:16 AM
それじゃあ意味が違ってない?
4:16 AM
というか、値保証されてるときはむしろdefault使っちゃだめでしょ
4:17 AM
値が無いかもしれない => なかった時に使うデフォルト値を指定したい => 今回の dict[key, default: d] を使うべき 値があるはず => なかったときはクラッシュさせたい => dict[key]! を使うべき (edited)
Avatar
dict[key]!で+=使えるならそれはそう
Avatar
omochimetaru 6/26/2017 4:18 AM
dict[key] += 1 ができるかどうかはわからないけど、 それができないからといって
Avatar
使った記憶がないから使えるか解っていない
Avatar
omochimetaru 6/26/2017 4:18 AM
default: を使っちゃたら
4:18 AM
値がない場合のエラーを握りつぶすパターンに書き換えていてよろしくないと思う。
Avatar
だから、0じゃなくてNeverいれようぜって話
Avatar
omochimetaru 6/26/2017 4:19 AM
あ〜
4:19 AM
dict[key, default: never()] += 1 こう?
Avatar
なおdict["key"]! += 1はSwift3時点で無理
4:19 AM
そう
Avatar
omochimetaru 6/26/2017 4:19 AM
@koher デフォルト値が絶対ある場合はundefined<T>とか使えば良さそう。
4:19 AM
dict[key, default: undefined()] += 1
4:19 AM
こう書くと良さそうですね、って言ってるのか。
Avatar
Optional, throwsで値が返ってくる系の問題は、返り値に対してvar structなパターンが使えないという点だな
4:20 AM
それを克服できるので、しかし
4:20 AM
デフォルト値に適当な数値を入れてしまうと
Avatar
omochimetaru 6/26/2017 4:20 AM
「めちゃくちゃ便利そう」に対して、「undefined()で代用できるから不要」って反対してるのかとおもった。
Avatar
1. エラーが握りつぶされる 2. そこだけ読んで0が妥当かわからない
Avatar
omochimetaru 6/26/2017 4:20 AM
他の応用方法を提示していたのか。誤読した。
Avatar
という問題を孕むので
4:21 AM
最初から一貫してそう主張してるぞなw
Avatar
omochimetaru 6/26/2017 4:21 AM
なるほど
4:21 AM
いや、undefinedを「default: のところに指定する」っていうのがわかってなかった (edited)
Avatar
Neverがボトムになれba
4:21 AM
まどろっこしい関数用意しなくて良くなるんだがな
Avatar
omochimetaru 6/26/2017 4:23 AM
var x: [String: Int] = [:] x["aaa"] = 3 x["aaa"]! += 1 print(x["aaa"])
4:23 AM
コンパイルできた。 出力 Optional(4)
Avatar
あれ、まじ?
Avatar
omochimetaru 6/26/2017 4:23 AM
マジ
4:24 AM
Version 8.3.3 (8E3004b)
4:24 AM
これ不思議だね
Avatar
あーいけた
4:24 AM
なんかミスってたっぽいな
Avatar
omochimetaru 6/26/2017 4:24 AM
! 演算子はオペランドが左辺値の場合、左辺値のままにしてくれるのか。
4:25 AM
そうすると話が巻き戻って dict[key]! += 1 で良いってことになるのか・・・?
Avatar
せやね
Avatar
omochimetaru 6/26/2017 4:26 AM
てかそれだったら
4:26 AM
dict[key] ?? defaultValue += 1
4:26 AM
これがかけたら良かったような・・・?
4:26 AM
これは厳しいか。 ?? の右側は別のストレージだもんな
Avatar
それどうやってdict[key]見つけんの
Avatar
omochimetaru 6/26/2017 4:27 AM
一応できると思うんだよな
Avatar
まあそもそもDictionaryをガチャガチャ操作するのをやめろって話ではある
Avatar
omochimetaru 6/26/2017 4:28 AM
readとwriteで別のストレージを見るアクセサになればいいから
4:29 AM
なやましい
4:29 AM
dict[key] ||= 3 rubyだとこういうのよく見る (edited)
Avatar
dict[key] ?? dict[key2] ?? default += 2
4:29 AM
これとかどうすんのっていう
Avatar
omochimetaru 6/26/2017 4:32 AM
同じようにできると思う イメージ的には func doubleQuestion( left: (read: ()->T?, write: (T)->Void), right: (read: ()->T, write: (T)->Void) ) -> (read: () -> T, write: (T) -> Void) (edited)
4:33 AM
実際には auto closure 的に read / write それぞれを取り出すことができないから無理だけど。
Avatar
結果の値を左辺の全ストレージにぶっこむってことね
Avatar
omochimetaru 6/26/2017 4:34 AM
そだね、でもたしかに、2個めのdict[key2]にwriteするのかどうかとかわかりにくいな
Avatar
素直に理解できる構文ではなさそうだ
Avatar
完全に乗り遅れたけど、 Neverがボトムになれba まどろっこしい関数用意しなくて良くなるんだがな これおもしろいですね。
8:20 AM
dict[key, default: fatalError()] += 1 (edited)
8:20 AM
ってできるのか。
Avatar
出来ますね、fatalErrorを使う優位性はメッセージ付きにできるところかな。
Avatar
Never がボトムタイプでない現状だと、 func never<T>(_ message: String = "") -> T { fatalError(message) } みたいなのがいると。
Avatar
ですです
Avatar
Never がボトムタイプにならないのって誰も Proposal 書かないから?
8:23 AM
なんか前スレッドありましたよね。どうなったんだろ。
8:24 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
8:26 AM
An uninhabited type can be seen as a subtype of any other type ... This can be considered as a separate proposal.
Avatar
はやいとこMLじゃないところに出てきてほしい、Thumbs upとか使いたい
Avatar
omochimetaru 6/26/2017 8:41 AM
わかりすぎる
Avatar
議論しないと同意できないフローかなり辛い。Neverがボトムタイプになるべきなんて、議論する余地無いんじゃねっていうのが伸び悩むのが本当に良くない
Avatar
特に反対意見でなければ Proposal 作るフェーズに進んじゃってもいいのかも?でもスレ主的にはやりづらそうだけど。
Avatar
omochimetaru 6/26/2017 8:48 AM
githubとかだと 👍 の絵文字が連打されたりするけどMLでそういうの無いしね
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
8:49 AM
今は "Socialize the idea" のフェーズだから
8:49 AM
"Develop the proposal" に進んじゃうという手もある。
8:49 AM
"Request a review" まで行けば Core Team も判断せざるを得ない。
8:51 AM
ただ、これって元々の Proposal が Joe Groff だし、 Core Team が認識してないわけはないから
8:51 AM
型システムに影響与えそうだし、 enum Never {} がボトムってどうなの?とか、他の enum Foo {} はどうなるの?とか、色々ややこしいから後回しにされてるのでは。
8:52 AM
それとは別に↓には強く賛成です。
はやいとこMLじゃないところに出てきてほしい、Thumbs upとか使いたい
8:53 AM
今も ML で +1 みたいなリプライあるけどw
Avatar
omochimetaru 6/26/2017 8:53 AM
あるけどMLでやると迷惑じゃないですか?
8:53 AM
と思って、やらない人と、気にせずやる人にわかれそう
8:54 AM
ていうか僕だったらスレッド一覧で見ていざ中身みたら +1 しか書いてなかったりして、そういうところもMLはだるい
Avatar
まあそもそも議論は多数決じゃないから +1 に本質的な意味はないのかもしれないけど、提案社的には賛同者がいることがわかればやりやすいかも。
Avatar
特に問題がないから議論が起きないのか、誰も興味が無いのかの判別がつかないのが辛い
Avatar
omochimetaru 6/26/2017 8:56 AM
そうそう。
Avatar
ML からの移行は早くしてほしいし、 Core Team もやると言ってるし、でも急にはできないし、気長に待つしかなさそう・・・。
Avatar
グローバル関数使うライブラリってSwifty的にNGですかね?
3:03 AM
someFunc(AnyProtocol, parameter...) 的なのを考えてたんですが型で判別できるから、ありかどうかで迷ってる感じです
Avatar
Alamofireはdownloadとかあった気が
Avatar
Alamofire - Elegant HTTP Networking in Swift
Avatar
型で分かるなら十分じゃないですか?
😀 1
Avatar
ありがとうございます、ちょっと思いつめてたので助かりましたw
Avatar
omochimetaru 6/27/2017 3:09 AM
というか
3:09 AM
パッケージでネームスペースが切れているのでは?
3:10 AM
さっきの downloadAlamofire.download ですよね 正式には
3:10 AM
ちなみに min とかの組み込みも Swift.min です
Avatar
そういう意味だとグローバル関数とは?という話に
Avatar
確かに、downloadで衝突してたらAlamofire.downloadで呼ぶしか無いのはあります
3:11 AM
なんというか命名モラル的に行儀が良いのかって所がどうなのかなーと
Avatar
ネームスペースが切れててもdownloadでアクセスできるので 結局そこがどうなのかって話なわけですよね
Avatar
omochimetaru 6/27/2017 3:12 AM
別に困らないし良いのでは
🙃 1
😂 1
Avatar
気にしすぎだった説
Avatar
omochimetaru 6/27/2017 3:14 AM
Javaだといざ衝突したときに com.omochimetaru.Alamofire.download とかなってシンドイけど Alamofire.download ならまあ別に平気だし、だいたいは引数の型でも区別可能だし。
3:14 AM
もし複数のライブラリから download が出てきてごちゃごちゃしてきたときは
3:14 AM
func alamofireDownload() { .. } とかを自作してラップするのが良いんじゃないでしょうか
3:14 AM
本当は別名インポートの言語機能がほしいけど無いので。
Avatar
import ... as ... 的なやつですか
Avatar
omochimetaru 6/27/2017 3:15 AM
そうです
Avatar
それほしいですね
Avatar
omochimetaru 6/27/2017 3:15 AM
ただ、グローバル関数って、ある意味シングルトンに対するメソッド呼び出しなので
3:15 AM
シングルトンの問題と同じで、なんらかのレシーバにぶら下げて挙動を変えたいように
3:15 AM
今後変更がかかりそうなら注意したほうが良さそう
Avatar
@tarunon なるほど、確かにそこも組み替えできるようにした方が可動域的な部分で良さそうです、もう少しいじって見ます😀 レビューありがとうございます、まさか誰か見てくれるとは思わずw
3:16 AM
文脈はここだと思うんですが(具体的なアプローチを提案できて無くて申し訳なく...
Avatar
いえいえ、レビュー嬉しかったです どういう風に直そうかなーって考えてました
Avatar
APIClient.init(URLSession)な実装にしておいて、シングルトンを避けて任意のAPIClientをinitするのが良いと考えていて
3:18 AM
そもそもAPIClientのベースをfunc loadを持つprotocolとして定義しておけば、MockClientの実装をサクッと作れるよ、という感じでした
Avatar
protocol APIRequestable { func load<R: Request>(request: R) -> R.Response } って感じですかね?
Avatar
そうですね。僕が最近書いたコードは大体そんな感じになってます
Avatar
なるほど、確かにそれぞれ用途ごとに準拠したものを用意すれば済みますね
3:25 AM
自分が言われてからぼんやり考えてたのは requests<R: Request>(adapter: RequestAdapter=DefaultRequestAdapter()) -> (request: R) -> R.Response みたいにしようかで悩んでました (edited)
3:25 AM
結局どこに状態持たせるかって話になっちゃいますかね
Avatar
↑ありがとうございます、とりあえずまた直してみます。 また何かあれば相談させてください🙂
Avatar
omochimetaru 6/28/2017 1:25 AM
@norio_nomura > emscriptenちょっと試してみたけど「クロスコンパイルターゲットをどの様に用意するか?」な問題に移ってる様に見える。 どのように用意するか、とはどういうことですか?
1:26 AM
emscriptenのコンパイルターゲットって宛先がJSかwasmかぐらいしか無いのかと思っていました
Avatar
norio_nomura 6/28/2017 1:28 AM
エラーを見ると
warning: Linking two modules of different target triples: /Users/norio/.emscripten_cache/asmjs/libc.bc' is 'asmjs-unknown-emscripten' whereas 'hello_world.bc' is 'x86_64-apple-macosx10.9'
swiftcが生成したhello_world.bcのターゲットがx86_64-apple-macosx10.9になってるからダメだよ、となってる。
1:29 AM
swiftctargetasmjs-unknown-emscripten.bcを生成できないとダメなんじゃないかな。
Avatar
omochimetaru 6/28/2017 1:33 AM
Swift -> LLVMIR のコンパイル時点でemscripten環境をターゲットにするのか。そういうアーキテクチャなんですね
Avatar
norio_nomura 6/28/2017 1:49 AM
あまりよくわかっていないのだけど、たぶんクロスコンパイル用のtoolchainを用意しなければいけないのと同じなんだと思ってる。 https://github.com/apple/swift-package-manager/pull/1098
General This adds experimental support for cross compilation or more precisely configurable destinations for binaries to SwiftPM. The basic idea is that you hand a JSON file in the format described...
Avatar
omochimetaru 6/28/2017 2:00 AM
なるほど
2:01 AM
emscriptenの時点で darwin-x64環境とかを抽象化するわけじゃないんですねえ
Avatar
norio_nomura 6/28/2017 2:02 AM
emscriptenのissueには「asmjs-unknown-emscriptenWebAssembly(wasm32)とほぼ同じだよね?」って話してる人がいて、同じ人がSwiftをWebAssemblyへクロスコンパイルする話題をswift-devに投げてる。 https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20170626/004860.html (edited)
Avatar
omochimetaru 6/28/2017 2:08 AM
おおアツい
2:08 AM
For example, the Clang that ships with Xcode 9 includes support for wasm32 as a compilation target.
2:09 AM
なるほど
3:04 AM
ぼんやり考えていて、コールバック時の結果にErrorが入ってるときに、(T?, Error?)やResult<T>を使うのは辛いなと思っていたのが解決するなと。
Avatar
そうですね。僕は JS の Promise みたいに非同期処理とエラー処理をまとめて扱うような設計が嫌いで、非同期処理なら非同期処理、エラー処理ならエラー処理と責務を分解しておくべきだと考えて、エラー処理を含まない Promise ↓を作ってました。 https://github.com/koher/PromiseK/tree/dev-3.0
PromiseK - The Promise class designed as a Monad for Swift.
3:07 AM
で、そうすると、この PromiseResult が対応してるなと思って、それらを throws, try (edited)
3:08 AM
async, await に対応させれば、自由にまぜて使えるよなぁと考えたものです。
Avatar
今でもやろうと思えば、コールバックの値を() throws -> Tにすればイケると思うんですが
3:09 AM
あまりやってるのは見ないですね
Avatar
ですねー。できるけど面倒ですしね。
3:10 AM
せっかく安全なエラー処理機構を持っているのに、Promise にエラー処理を担当させちゃうと、 catch 忘れがおこっちゃうんですよねぇ。
Avatar
純正だとT?, Error?、Resultの民はResult<T>だ
Avatar
PromiseResult を一緒に使うとモナドパズルになっちゃうんですよねぇ。
3:11 AM
Result<Promise<Result<Foo>>>Promise<Result<Foo>> にしたいとか。
Avatar
最近それやってて、windows版はasync+throwでできて良かった
Avatar
C#ですか?
Avatar
はい。
Avatar
omochimetaru 6/30/2017 3:12 AM
C#はasync-awaitは明示的だけどthrowが・・・
Avatar
Array<Promise<Result<Foo>>>Primise<Result<Array<Foo>>> にしたいとか。
Avatar
その移し替えはめんどくさそうだ
Avatar
その辺のメリットも明記したら伝わりやすいのかな、というのと
Avatar
jsだとPromise.allとかあったけどエラーハンドリングが分離してるから純粋にはできないのか。
Avatar
そうですねぇ。あまり詳細まで書くと長くなって読まれないんじゃないかという心配もあって、議論の中で説明できればいいかなと。英語で議論についていけるのかあやしいですが。
3:16 AM
ちなみに、 PromiseK 3.0 では let a: Promise<Int> = ... let b: Promise<() throws -> Int> = a.map { try foo($0) } みたいに、 map 等の中で throw される場合は戻り値の型パラメータを () throws -> Foo に変換する API を考えてます。
3:17 AM
async, await ができれば無用の長物ですが。
Avatar
ambiguous出そうw
Avatar
あと、おもしろいかなと思って、 typealias Promise<Value> = (@escaping (Value) -> ()) -> () とする Promisure (= Promise + Closure) というライブラリも作ってましたw
3:19 AM
// 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) } // apply
Avatar
omochimetaru 6/30/2017 3:19 AM
Promiseの型パラに関数型入っとる・・・
Avatar
関数型は non-nominal なので extension が生やせないので、メソッド代わりに全部演算子になってます。
3:24 AM
@tarunon Rx の Observable にエラーが組み込まれてるのも僕は好みじゃないんですが、どうにかならないものでしょうか。
Avatar
omochimetaru 6/30/2017 3:24 AM
あ〜 > extension
Avatar
僕も全く同じ気持ちで
3:26 AM
あーでも
3:26 AM
ObservableはErrorは停止なので、色々厳しそう
Avatar
Error排除できるタイプのもあるしそういう方向で対応しようってことになってるんじゃないですか?
Avatar
SharedSequenceですね
Avatar
その場合って、 failable な型が重複して似た仕組みを持つことになるけど、それは仕方ないか・・・。
Avatar
Observableになんとか、throws-rethrowsの機構を組み込みたい
Avatar
やっぱ、 throws, try みたいな特殊構文用意するよりも、モナドに対して do 記法用意するとかの方が汎用性はありますよねぇ。
3:29 AM
入れ子モナドのパズルを解決するいい方法が必要だけど・・・。
Avatar
さっきのPromiseの例は上手い解決かもしれなくって
3:30 AM
ちょっと後で考えてみよう
Avatar
あれって、 ResultPromise なら Promise が外側にいてほしいとか、モナド感での precedence みたいなものが考えられる気がして、
3:31 AM
その順に全部いいように組み替えてね関数が一つあればうまくいきそうな気も?
Avatar
物凄い筋肉質なオーバーロードした関数が存在しそう
Avatar
omochimetaru 6/30/2017 3:31 AM
筋肉質なオーバーロードw
Avatar
いや、オーバーロードじゃなくて
3:32 AM
Monad 型に対して演算子みたいな precedence を指定できて
3:32 AM
sort 関数みたいに、それを使って入れ子を関数が解決する。
Avatar
高階型ないからオーバーロード必須ですよ多分
Avatar
ああ、高階型あり前提です。
Avatar
omochimetaru 6/30/2017 3:34 AM
型同士の合成規則を2つの型の優先度の2項関係を表す型の集合で記述して
3:34 AM
型解決の枠組みで静的に決定
3:34 AM
みたいな・・・
Avatar
で、後はネストモナドまとめてアンラップもできれば。↓みたいな? let a: Result<Promise<Int>> = ... let b: Promise<Result<Int>> = magic(a) do { let c: Int <-- b // 多段アンラップ let d: Result<Int> <- b // 一段アンラップ }
3:37 AM
そしたらモナドのネストも恐れる必要がない(組み換え問題とアンラップ問題を同時に解決できる)気がするし、いちいち try とかキーワード足さなくても自作モナドを組み込みモナドと同じように便利に使える。
Avatar
うーん
3:42 AM
殊、asyncとthrowsに関しては汎用性云々というより (edited)
3:42 AM
あまりにも出現頻度が多すぎるので言語仕様でサポートしたほうが平和なのでは?という気がしている
Avatar
そうですねぇ。特殊構文はそれはそれで見やすいんですよね。
3:43 AM
PromiseK では thenmapflatMap になってるんですけど、ネストしてくると読みづらいんですよねぇ・・・。
Avatar
then、Swiftコンパイラには荷が重いのでmap/flatMapにしたほうが良いよ派の人間です
Avatar
omochimetaru 6/30/2017 3:44 AM
人間にも重いと思う派
Avatar
コンパイラが理解できないのは人間にも理解できないよ
3:45 AM
大体の場合ね
Avatar
omochimetaru 6/30/2017 3:45 AM
じゃあ同じ意見だった
Avatar
ただ、 Swift は Result を作らなかったから thorws, try を別の型でラップしたい場合に Promise<() throws -> Int> とかなるのはちょっとつらいですよね。
Avatar
Promiseがasyncに昇格されれば辛さは消えますよ
Avatar
はい、それはそうです。けど、 Observable とかでやろうとしたらできないですよね?
Avatar
そうなんですよねぇ
Avatar
結局別のエラー処理機構を導入せざるを得ない。
Avatar
omochimetaru 6/30/2017 3:46 AM
ですね
Avatar
throws () -> Tにしなきゃいけないのがしんどいので
Avatar
omochimetaru 6/30/2017 3:47 AM
async / awaitが言語に入ったときに
Avatar
throws Tがあれば
Avatar
omochimetaru 6/30/2017 3:47 AM
言語サポートがあるけど非同期としては貧弱なPromiseと
3:47 AM
言語サポートが無いけど非同期機構としてはリッチなObservableが
3:47 AM
存在する環境になって
3:47 AM
甲乙つけがたくなりそうでそこはちょっとナーバスになっている
Avatar
Observable相当のものが言語機能に降りてこないかな~というのを考えてるけど
Avatar
omochimetaru 6/30/2017 3:48 AM
それはなあ・・・
Avatar
これは前おもちくんと話したな
Avatar
omochimetaru 6/30/2017 3:48 AM
細かい設計に柔軟性がありすぎてコンセンサスも取れなさそう。
3:48 AM
RACだと Signal / SignalProducer で Hot / Cold を型付けしたりしてるし
Avatar
シンプルな Promise であれば議論の余地がほぼなさそうだけど、 Observable レベルになると枯れてなくて言語機能にするにはつらそう・・・
Avatar
omochimetaru 6/30/2017 3:49 AM
そうなんですよねえ
Avatar
だから、ライブラリでも組み込み構文に近い便利さを享受できる言語仕様になってればいいなぁと思うんですけどねぇ。
Avatar
治安は悪化しそう
Avatar
それはそうですねw
3:51 AM
文化が断裂してお互いに理解できないコードの世界が出来上がりそうw
3:51 AM
まあ、でも Rx はすでにそうなってるような気も。
Avatar
omochimetaru 6/30/2017 3:53 AM
Rxはそうなんですけど
3:53 AM
言語をまたいだ世界だから
3:54 AM
まあいっかって気持ちになる
3:54 AM
(RxSwiftの呪文を覚えるとJavaでも使える
Avatar
まだ関数呼び出しの範疇に収まってるから平気だけど
3:54 AM
構文拡張とかやっていったら人死にが出る
3:54 AM
オレオレoperatorですら結構辛いのに
Avatar
omochimetaru 6/30/2017 3:54 AM
ですね
Avatar
構文拡張というか、汎用的に使える構文って意味ですね。
Avatar
Javaのアノテーションもしんどい
Avatar
RxSwiftのSwift2の頃のオペレータは結構好きでした
3:55 AM
>-
Avatar
omochimetaru 6/30/2017 3:56 AM
マジすかあ
Avatar
隣の同僚がオレオレオペレーターてんこ盛りプロジェクト引き継いでブチ切れながら消していってて、まぁそうっすね…みたいな感じ
Avatar
omochimetaru 6/30/2017 3:57 AM
最初ひょえ〜っとなって、やっていくうちに、あれ、これメソッドでいいのでは?となって、Swift側の制約でできないからやってるとわかって、Swift3でメソッドになって気持ちが落ち着いた (edited)
Avatar
他のライブラリ含めてオレオレoperator廃止されていってるのを見て、これあかんやつなのかってなったのは記憶にあります
Avatar
omochimetaru 6/30/2017 3:58 AM
たしかジェネリック型に対するextensionメソッドがまだショボくって
3:58 AM
でも演算子ならいけるみたいな
3:58 AM
状態だったんですよね。
Avatar
あったあった
3:58 AM
オレオレオペレータ廃止の流れは
Avatar
今でも、 non-nominal の extension 書けないから
Avatar
そもそも言語機能としてオレオレオペレータの何かが削られたからっていうのが
Avatar
omochimetaru 6/30/2017 3:58 AM
Swift3の仕様強化でだいぶオペレータが排除できた
Avatar
オペレータならできる状態が終わってない・・・
Avatar
大きかった気がする
3:58 AM
non-nominalはありますね
Avatar
例の => も。
Avatar
omochimetaru 6/30/2017 3:59 AM
そうですねえ そして関数型が non-nominal である影響がでかい。
3:59 AM
=> が演算子にしかできないのも Any型がnon-nominalだからだっけ (edited)
Avatar
まあ、 => レベルだと演算子の方が可読性高そうだけど。
3:59 AM
Any でもダメで、任意の型パラじゃないといけないから辛い・・・
Avatar
omochimetaru 6/30/2017 4:00 AM
ん?とは?
4:00 AM
もしAnyに対するextension methodで書けたとして、それでも 拾えないパターンってどういうのがあるんでしょうか (edited)
Avatar
extension Any { func `let`<T>(_ f: (Any) -> (T)) -> T { ... } }
4:00 AM
だったら、クロージャの引数が Any になっちゃって
4:01 AM
ダウンキャストしないといけなくて面倒。
Avatar
omochimetaru 6/30/2017 4:01 AM
そこは Self では
Avatar
そこ Self にする extension ってできるんだっけ?
Avatar
omochimetaru 6/30/2017 4:01 AM
わからないw
Avatar
えーっと
4:01 AM
Anyはprotocolなんでいけます
4:02 AM
are
Avatar
↓演算子実装 public func =><T, U>(lhs: T, rhs: (T) throws -> U) rethrows -> U { return try rhs(lhs) }
Avatar
omochimetaru 6/30/2017 4:03 AM
classだとできないな 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() } ^~ ~~~
Avatar
classはですね
4:03 AM
extension SomeProtocol where Self: SomeClass {} (edited)
4:04 AM
これでSelfが使えるようになる
4:04 AM
Anyがextensionできるなら、
4:04 AM
extension Any where Self: SomeClass {}
4:04 AM
これでよさ
Avatar
お、できた
4:06 AM
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 }
Avatar
omochimetaru 6/30/2017 4:06 AM
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() }
4:06 AM
できた
4:06 AM
@tarunon whereなしでかけた
Avatar
いやいや
4:07 AM
それだとCatのメソッド使えなくなるぞ
Avatar
omochimetaru 6/30/2017 4:07 AM
exec2のなかで nya() が呼べたよ。
Avatar
exec2自体の実装の中でnya()呼べないという意味
Avatar
omochimetaru 6/30/2017 4:07 AM
今の => の議論からするとそれは問題ないのでは
Avatar
用途をletに限るならまあそう
Avatar
omochimetaru 6/30/2017 4:08 AM
=> の実装をオペレータからメソッドにできるかどうかだけを今考えていて
Avatar
これで問題なのは Any が nominal でないってことだけなわけだ。
Avatar
omochimetaru 6/30/2017 4:09 AM
現状は Any に対する extensionが書けないからできない、
4:10 AM
もし書けるのであれば Selff に渡す形で実装はできる。
4:10 AM
@koher 現状でも
Avatar
うん
Avatar
omochimetaru 6/30/2017 4:10 AM
Any じゃなくてLettable という protocol のメソッドとして作って
4:10 AM
.let を使いたい型については extension Cat : Lettable {}
4:10 AM
と、1つずつユーザーが書いていけばできそう。
Avatar
面倒すぎでしょw
Avatar
omochimetaru 6/30/2017 4:10 AM
はい・・・
😕 1
Avatar
そして可読性の観点でも => の方がいいと思う。
Avatar
omochimetaru 6/30/2017 4:11 AM
let束縛感がありますね
Avatar
可読性はちょっと疑問があって
4:11 AM
広く知られてればまあそれはそう
4:12 AM
1 + 1 と 1.add(1) だと俄然前者のほうが良い
4:12 AM
f <$> [1] と [1].map(f) はさてどうだろう、という (edited)
4:12 AM
広く知られればいいけど。
Avatar
<$> は順番が逆転しちゃう問題もありますしねぇ・・・
4:13 AM
さっきの Promise のチェーンは
Avatar
あー逆だったか
Avatar
promise.flatMap { ... }.flatMap { ... }.flatMap { ... }
4:13 AM
よりも
Avatar
omochimetaru 6/30/2017 4:14 AM
なんじゃこれって思ったときに調べにくいという問題はあるね
Avatar
primise >>- { ... } >>- { ... } >>- { ... }
4:14 AM
のようが見やすい
4:14 AM
ググラビリティ低い問題はある。
4:14 AM
記号検索させてほしい。
4:14 AM
記号検索エンジンにニーズある気がする。
Avatar
omochimetaru 6/30/2017 4:14 AM
あとはxcodeがもっとキビキビ動けば Cmd + Click できるんだが
4:15 AM
だいたい indexing... 😴 だからな
😂 1
4:15 AM
定義にも飛べないしググることもできなくておわり
4:16 AM
http://blog.fkoji.com/2017/03052055.html Google 検索ではすでに記号1文字の検索はできるようになっていましたが、新たにプログラミングでよく使われる「===」や「+=」といった、複数の記号が連なる演算子などの特殊記号の検索ができるようになったそうです。
Google 検索ではすでに記号1文字の検索はできるようになっていましたが、新たにプログラミングでよく使われる「===」や「+=」といった、複数の記号が連なる演算子などの特殊記号の検索ができるようにな…
Avatar
=> は標準ライブラリに入れてほしい・・・。
4:16 AM
え、できるの?
Avatar
omochimetaru 6/30/2017 4:16 AM
最近グーグルが強化されたらしいけどさっきpythonの r''' 出せなかったし嘘だと思う
Avatar
正規表現ですか?
Avatar
omochimetaru 6/30/2017 4:17 AM
r''' は正規表現じゃなくて生マルチライン文字列
Avatar
知らないのだ
Avatar
omochimetaru 6/30/2017 4:17 AM
swift - The Swift Programming Language
Avatar
ああ、rってregexのことかとおもってたらrawなのか
4:19 AM
正規表現でしか使ったことなかったから完全に勘違いしてた
Avatar
omochimetaru 6/30/2017 4:19 AM
pythonは正規表現リテラルは存在しない
Avatar
うーん、なんとなく動いてそう? Swift >>- で検索したら、一つ目は https://www.apple.com/jp/swift/ だけど、二つ目は typelift/Operadics で、三つ目は thoughtbot/Runes だった。
4:20 AM
以前よりはずっとマシな気が。
Avatar
<$> はないよ
Avatar
できない
Avatar
<^> にマッピングされてる。
Avatar
omochimetaru 6/30/2017 4:21 AM
ああそっか。 でも <^> も駄目っぽいですよ
Avatar
>>= は重複してるから >>- に、 <$> は言語仕様上の制約で <^> になってる。
Avatar
haskell <$>でもいまいちヒットしてない感
Avatar
omochimetaru 6/30/2017 4:22 AM
What does <$> mean in Haskell? - Stack Overflow https://stackoverflow.com/questions/.../what-does-mean-in-haskell このページを訳す 2016/05/17 - Google is not the best search engine for Haskell. Try Hoogle or Hayoo, both will point you right away to this ...
4:22 AM
最初に出た!
Avatar
While reading a piece of Haskell code I came upon this: <$>. What does it mean in Haskell? After some google searches I remain in the dark.
Avatar
omochimetaru 6/30/2017 4:22 AM
いけてそう
Avatar
公式じゃないけど
4:22 AM
まあないよりマシそう。
4:23 AM
swift <^> は出ないなぁ。
Avatar
要約のほうがぜんぜんでないだけかな
Avatar
普通の Google 検索と比べると、 10% くらいの精度で一応動いてそう・・・。
😅 1
Avatar
普通のGoogle検索もSEO頑張る人間に潰されててなんか辛い。最近動きありましたっけ。
Avatar
|>は出た
Avatar
SEO は辛いですが、 Google ないよりはるかにいいですからねぇ。
4:26 AM
この前、 Google を初めて知ったときのことを思い出してたんですが、試しに何かの名称を検索してみたら公式サイトが一番上に出てきて感動したことを覚えてるんですよ。 (edited)
4:27 AM
つまり、 Google 以前の検索エンジンは、何かで検索してトップに公式サイトが出ることがなかったってことなんです。もうそんな世界で生きていけない・・・。
Avatar
associatedvalueを持ったenumの抽象化を書きたくて、
6:54 AM
結局具体型を作らざるを得ないのはわかったけど名前が困る
6:54 AM
2つならEither<L, R>でいいけど3つ以上(個数ごとに作る必要はある)の名前は何にするべきなのか
Avatar
omochimetaru 6/30/2017 6:54 AM
Either2<T1, T2> Either3<T1, T2, T3>
Avatar
それ割とやるんだけど
Avatar
Either<T, Either<U, V>>
Avatar
他の言語とか見てもEither型はL,Rしかない
Avatar
そもeitherという語から二者択一感を感じる
Avatar
omochimetaru 6/30/2017 6:56 AM
じゃあN者択一型はなんて名前になってるん?
Avatar
either a, b or c って言えないんだっけ?
Avatar
@koher ネストさせるとツリー構造に対して無限の分岐を埋めなきゃいけなくなるんでちょっと
Avatar
3者以上からの選択1の用法では, ⦅まれ⦆に3者以上からの択一の際にeitherを用いることがあるが, any (one)の方が普通
🙃 1
Avatar
Whichなのかなーとか
6:57 AM
思ったけど型名であると考えるとEither型の方が認知は絶対高くて、しかしEither3,4,5のような用法は
6:58 AM
ググった感じそんなになさそう
Avatar
多分 Tagged Union で Untagged 的な振る舞いをさせるのがあまりよくないような・・・
Avatar
ほしいのはenumの抽象化
6:59 AM
ケースが幾つあって型がそれぞれあってswitchで保証される
Avatar
omochimetaru 6/30/2017 6:59 AM
僕は C++ で Tagged Union が使いたくてシコシコ実装中
Avatar
気になって見ててもAnyで使ってる人が多そうな雰囲気 > 複数形 https://english.stackexchange.com/questions/129288/words-similar-to-either-and-neither-for-3-items
Given two options, we can use 'either and 'neither' to show no preference. Do you want to watch A or B Neither, I don't like either. The only option I can see for more than two options is:...
Avatar
AnyOf とか OneOf とか?
Avatar
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 } }
7:01 AM
↑こういうのを、あと3,4,5くらいまで作っておくとして
7:01 AM
Either3…ん?となった
Avatar
enum の抽象化ってことは、 Either2<Int, String>Either2<String, Int> は区別したいってことですよね?
Avatar
それはしますね
7:04 AM
enumの抽象化、いい加減方方で使いすぎてるんで、マイクロフレームワークで作りおきしておこうというモチベになった
Avatar
うーん、このレベルで抽象化したいことがあまりなさそうで、それをしたくなったときは諦めて複数書くとか?
7:04 AM
使いまくってるのか・・・
Avatar
任意のenumを引数に取る関数、が必要になることが多くて
7:05 AM
そのたびに作ってますね
7:05 AM
ん?
Avatar
たとえばどんな関数ですか?
Avatar
enum Enum2, protocol Enum2Convertible
7:05 AM
これでいいんじゃないかな
7:06 AM
直近で言うと
Avatar
Enum2, Enum2Convertible は良さそう
Avatar
RxDataSourcesのdataSource作るのが面倒くさいので
7:07 AM
型を食わせてprotocol orientedに半自動生成させていて
Avatar
Enum1Enum0 もいらないですか? BoxNever
Avatar
Cell型が複数の時に必要になる
7:07 AM
作っちゃおう
7:08 AM
個数ごとにコードを書く必要はあるんですが、1~5個作っておけば5個まではもう、DataSourcesを生成するコードを書かなくて良くなるんで
Avatar
Enum3 とかだと CaseA より Case1 とかの方がよさそう
Avatar
ですね
Avatar
0 から始めるか少し迷うけど 1 からかなぁ。
7:09 AM
でもタプルは 0 からか
7:09 AM
それなら 0 からかなぁ
Avatar
Tuple 0はVoidなんで
7:09 AM
Enum 0はNever
Avatar
あ、ではなくて
Avatar
まあそこはそう、美しいと思う
Avatar
enum Enum2<T0, T1> { case Case0(T0) case Case1(T1) }
Avatar
あw
7:10 AM
そういうことか
Avatar
にするかです。
Avatar
まあ0でいいんじゃないですかね
Avatar
そのほうが一貫性はありますよね
7:11 AM
パッケージ名は EnumN とか?
Avatar
EnumConvertibleかなんかにしようかと思っていた
7:11 AM
Convertible大好き人間
Avatar
なるほど
Avatar
ここで言うところのenum CellModelがさらにEnum2的な型で抽象化されるイメージです? https://twitter.com/tarunon/status/854349403322175489
@moaible つまり、enum CellModel { case cellType1, .... }と enum SectionModel { case section1([CellModel]), ... }
Avatar
あとはリポジトリ名を UpperCamelCase するか小文字ハイフンつなぎにするかも迷いどころw
Avatar
あーですね
7:14 AM
UpperCamelCase vs chain-caseは宗教戦争っぽい
7:14 AM
どっちがどうなんだ
Avatar
enum絡むライブラリ作ったら名前これにしようと思ってた http://ejje.weblio.jp/content/Houyhnhnm
Avatar
GitHub の主流はハイフンつなぎだけど Swift のライブラリは UpperCamelCase が多かったけど
7:15 AM
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
omochimetaru 6/30/2017 7:16 AM
Houyhnhnm 音節Hou・yhn・hnm 発音記号/hwínəm|húːɪ‐/ 名詞可算名詞 フーイナム 《Swift 作 Gulliver's Travels (ガリバー旅行記)の中の人間的な理性が徹底している馬; 人間の形をした Yahooを支配する》. [馬の鳴き声からのSwiftの造語]
Avatar
これのサンプルが https://github.com/apple/example-package-fisheryates なのを見て以来、やがてハイフン区切りの波に抗えなくなるんじゃないかという気がして、最近僕はハイフンばっかです。
example-package-fisheryates - Example package for use with the Swift Package Manager
Avatar
omochimetaru 6/30/2017 7:16 AM
????
7:16 AM
Swiftとは クイック再生 プレーヤー再生 ピン留め 単語を追加 主な意味 スウィフト 《1667‐1745; 英国の文人; Gulliver's Travels の作者》 音節 swift 発音記号・読み方 /swíft(米国英語)/
Avatar
ガリヴァー旅行記はスウィフト作
Avatar
なるほどー
Avatar
omochimetaru 6/30/2017 7:16 AM
Swiftって名前の人いたのか
Avatar
ガリバー旅行記から名前取るのオシャンティー過ぎて僕にはちょっと
Avatar
@omochimetaru テイラー・スウィフトもいるでしょ?
Avatar
omochimetaru 6/30/2017 7:17 AM
swift-package-manager - The Package Manager for the Swift Programming Language
7:17 AM
SPMそれじたいもハイフンですね
Avatar
うん
7:17 AM
Apple がそのスタイルとってる以上、やがて抗えなくなると思うんよね
7:18 AM
パッケージ名は UpperCamel 、リポジトリ名はハイフンかなぁと。でも、ディレクトリは UpperCamel にしとかないと、 swift package init したときに面倒😅
Avatar
ローカルではUpperCamelで作ってリポジトリはハイフンつなぎが一番楽そう
Avatar
コマンド引数で渡せたら楽なのにとは思いますね
Avatar
ですねー。渡せないですよね?何かあるのかなと思ってたんですが見つけられず。
Avatar
$ swift package init --help OVERVIEW: Initialize a new package OPTIONS: --type empty|library|executable|system-module
Avatar
ここの文化的な不整合、Apple製APIがchain-caseなのにCodableでスッとできないのは草っていう話題
Avatar
enum絡むライブラリ作ったら名前これにしようと思ってた フーイナム 《Swift 作 Gulliver's Travels (ガリバー旅行記)の中の人間的な理性が徹底している馬; 人間の形をした Yahooを支配する》.
これは Swift 絡みなのはいいとして、なんで enum なの?
7:21 AM
chain-case って言うんだ。
Avatar
発音から。ネイティブだったらどう発音するのかわかんないですが
Avatar
ああ、そういうことか < 発音
Avatar
swift-package-manager - The Package Manager for the Swift Programming Language
Avatar
Yahoo もガリバー由来なんだ・・・ Yahoo!の名前の由来は英語の「Yet Another Hierarchical Officious Oracle」(さらにもう一つの階層的でお節介な神託)の略だといわれている[57]。また、ファイロとヤンは自分たちのことを「ならずもの」だと考えているので、「粗野な人」という意味がある「Yahoo」(『ガリヴァー旅行記』に登場する野獣の名前が由来)という言葉を選んだと主張している[10]。さらに感嘆符が付いていることに関しては「ヤッホー!」「やったー!」を意味する英語の感動詞「yahoo」と掛けているとも考えられる。
Avatar
Package.swiftでの指定はURLなのでハイフンつなぎにしといても問題ないかなぁと思っている。
Avatar
別にConvertするわけじゃないからConvertibleは不適切な気がしてきた
Avatar
ほんとだ・・・ < 現状はディレクトリ名
Avatar
abstract-enumとかかなぁ (edited)
Avatar
え? EnumNConvertibleEnumN に convert するんじゃないんですか?
Avatar
いやそれはその通りなんですが
Avatar
abstract-enum 長いから abstenum とか?
7:27 AM
CustomStringConvertible とかを考えても EnumNConvertible とかならおかしくない気も。
Avatar
なるほど
Avatar
N がなかったらどうだろう
Avatar
別にライブラリ名だし良さそう?
Avatar
がちゃっと書いたけど、これgyb使ってビルド時にOption渡して任意個のEnumサポートできるようにしたいな
Avatar
gyb、 実行時に $ gyb -D Key=Value でパラメータ渡せるから、できるよ
Avatar
おお
Avatar
cpp-rhetoric - small fundamental library for modern C++ programming.
cpp-rhetoric - small fundamental library for modern C++ programming.
10:57 AM
OptionalとResultがEither2実装になった。
Avatar
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] { 使う側がこんな感じの地獄じみた形相になってるから、任意個数サポートできるのはもはや必須の感じがする
Avatar
www
11:06 AM
cpp-rhetoric - small fundamental library for modern C++ programming.
11:06 AM
指定のディレクトリ配下から *.gybを探して 変換するラッパー。参考にどうぞ。
Avatar
あざます
11:07 AM
これUI{Table, Collection}Viewの{Animated, Reload}DataSourceに対応しなきゃいけないから
11:07 AM
Enum5でも5x4で20個関数用意していてバカじゃないのって感じがする
Avatar
要素全部型定義してるんですね😱
Avatar
これがあると
Avatar
自動生成の機運
Avatar
dataSourceObservable .bind(to: tableView.rx.animatedItems(for: MyCell1.self, MyCell2.self)) .disposed(by: disposeBag)
11:12 AM
こんな感じのコードを、ちょっとだけ型定義するだけで書けるようになる
Avatar
なるほど
Avatar
定義側がしんどいのは自動生成でカバーできれば完全勝利だから
Avatar
curry は昔ジェネリック引数14個(?)でコンパイル終わらなくなる問題がありましたが大丈夫そうですか?
Avatar
1TableViewに14種類Cell使う人が居たら大丈夫じゃないかもですねw
Avatar
ww
Avatar
多分、1-14までオーバーロードさせるとそうなるんで、連番で作るのとピンポイントで作れるのを用意しておけば良い気がします
Avatar
gyb環境構築微妙にハマった... --line-directive= 入れないと ###sourceLocation が各行入るからなんなのかと思った
Avatar
omochimetaru 6/30/2017 1:12 PM
そうですねw
1:13 PM
cpp-rhetoric - small fundamental library for modern C++ programming.
1:13 PM
わざわざ空にしないといけない
😰 1
Avatar
Swift gybの環境構築 ふとSwiftのgybが気になったので環境構築を試して見ました gybとは Swift言語開発の副産物のメタプログラミングツールgybがとても良い— おもちメタル (@omochimetaru) 2017年6月30日 gybは「Generate Your Boilerplate」の略称みたいです(gyb --helpより) 具体的に何かと言うと、Swiftの公式リポジトリの中でSwiftコードの自動生成に使われているPython製のテンプレートエンジンになります gybを導入する qiita.com というわけで、こちらを参考に環境構築して見ました まずgyb自体…
Avatar
omochimetaru 6/30/2017 3:39 PM
###sourceLocationというgyb側のログ?も一緒に出力されてしまうので必須で追加した方が良いです
3:39 PM
これは多分、Swiftコンパイラに対して、ソースコードの本当の位置を教えるための仕組みですね
3:40 PM
gybから生成された.swiftにおける行数を表示したところで
3:40 PM
ほんとうの意味でのソースコードは.swift.gybだから
3:40 PM
それの場所をデバッガに伝えるためのやつ
Avatar
なるほど、修正しときます🙏
Avatar
omochimetaru 6/30/2017 4:20 PM
typescriptとかESJSでやるsourcemapがソース自体に埋め込まれてるようなもんですね
4:10 AM
このメールで提案されてるのってここでも何度かでた話を全く同じ提案じゃない?
4:11 AM
右辺値に説明文を書かないといけない !! オペレータ。機能は ! と同じ。
4:13 AM
never型ちゃんとやって preconditionFailure を ?? に並べたらええってレスもついてるな
4:14 AM
スレが70投稿ぐらい伸びてて読みきれん
Avatar
norio_nomura 7/10/2017 4:24 AM
2017/06/28にkoherさんが #swift にそのリンクを投げて盛り上がってましたよ。
Avatar
omochimetaru 7/10/2017 4:26 AM
ああ話題自体がここソースだったのか
Avatar
norio_nomura 7/10/2017 4:37 AM
そのスレッド、僕のメールボックスでは100件になってる。
Avatar
omochimetaru 7/10/2017 4:54 AM
ブラウザ1ページしか見なかったので全部だとそのくらいありそうです
Avatar
omochimetaru 7/11/2017 2:18 AM
Swift4のCodableが内部で何をやっているか確認する by @kenmaz on @Qiita http://qiita.com/kenmaz/items/8bfd386ad4a978b6ed6d
ほんの小ネタです。 Swift4から導入されるCodableですが、どういう仕組で実現されているんでしょうか。WWDCのプレゼンによるとCodableを適用すると、encode/decodeを実現するための実装をコンパイラーが生...
2:19 AM
ASTフェーズですでに自動生成コードが展開されてるってことは、ちゃんとSwiftのソースコードとしてコンパイルされてそう
Avatar
あれ、Xcode9 beta3、se0110はRevokeされてるけどRxSwiftのテストケースは死屍累々のままだ
5:07 AM
Overloadとの兼ね合いで何か壊れている気がするな…
5:10 AM
理解した、クロージャがOptionalだとぶっ壊れるw
5:15 AM
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 // 死ーん })
Avatar
Bダメなんですね、見たところ問題なさそうに見える
Avatar
後でbugsに上げとこう
5:18 AM
RxSwiftはどうするかな、まだ待った方が良いか…
Avatar
これって問題なのは一度型変数に入れたタプルをタプルとして解釈できないのが問題なんでしたっけ? (edited)
Avatar
タプルを複数引数に分解できないようにするのがse0110、rollbackしたけど、Optionalなクロージャは判定されてないのでse0110の影響が生きている
😇 2
Avatar
なるほど
Avatar
ということだと思います、確かにse0110ロールバックのPRは、Optional考慮してなかったような気がする
5:30 AM
swiftコンパイルできる環境あればこういうの直にpr投げれるな、早く環境作ろう
Avatar
omochimetaru 7/11/2017 5:47 AM
[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.9
👏 3
5:47 AM
ちょうどいまできた
Avatar
どのぐらいビルドかかりました?
Avatar
はやくMacPro回収しないと
Avatar
omochimetaru 7/11/2017 5:47 AM
本当はplaygroundでやりたいからtool-chain全部いりにしたいんだけどこの前やった結果それはとてもつらい
5:48 AM
うーん お昼ごはんたべにいってたから
5:48 AM
12:30 〜 14:30 ぐらいかな?
Avatar
あ、そんなもんなんや
Avatar
omochimetaru 7/11/2017 5:48 AM
もうちょっと速いかも
5:49 AM
飯に行ってたから終わった時刻が正確にわからない(飯に2時間いっていたという意味ではないw
Avatar
ww なるほど、ありがとうございます
Avatar
omochimetaru 7/11/2017 5:50 AM
iMac Corei7 3.6GHz / memory 16GB / SSD
🙇 1
Avatar
omochimetaru 7/11/2017 6:01 AM
xcode9.3betaに同梱されてるやつとswift-4.0-branchって何が違うんだろう
6:01 AM
githubでコミットの差分みたらええんか
Avatar
swift - The Swift Programming Language
Avatar
omochimetaru 7/11/2017 6:02 AM
ありがとうございます
6:02 AM
ディスクは19Gつかった
6:02 AM
これtimemachineはずしとこ
6:04 AM
ちょうどrintaroさんのコミットからだw
Avatar
norio_nomura 7/11/2017 9:34 AM
そうか、Xcode 9 beta 3はCodableの実装がまだ古いのか。
😳 1
Avatar
例のOptionalですかね
Avatar
https://github.com/apple/swift/pull/10881 Optionalのclosureでtupleが分解できない問題治してもらえた。はやいw (edited)
…jection. There was an oversight in the exception that was added to SE-0110 to maintain compatibility for closure arguments. We were not allowing optional injection to happen for the closure being ...
❤ 4
Avatar
なんかbugs.swift.orgのチケットのステータス、今どうなってるのか不明でレポートしてもそれが解決したのかわかりにくいw
6:08 AM
昨日報告したこれ https://bugs.swift.org/browse/SR-5433 は、もうPRがマージされてて見た感じ解決済みなんだけど、チケットは相変わらず未解決だし。
Avatar
ひそかに(?) @rintaro さんの第二弾が投稿されてる。前回のと合わせてビルドしてテストできるようになるので、これに従えば swift リポジトリに PR 出せそう。 http://qiita.com/rintaro/items/2f84776cf1629150b312
この記事は、 Swift.org のオープンソース Swift の開発に参加してみたい方のためのものです。普通にSwiftでアプリの開発をするのにはまったく役立たない知識です。 Swift コンパイラのテスト環境は普通のプロジェクト...
😀 1
Avatar
Twitterでpublishしてたからひっそりではないですねw
Avatar
お、 Twitter みてませんでした😅
Avatar
norio_nomura 7/12/2017 9:04 AM
XCTestXFAIL欲しい
9:11 AM
litはテキストファイルならなんでも良いので、.mdにテストを書いたりできるのが面白いと思った。 https://github.com/apple/swift-integration-tests/blob/master/swift-package-init-exec.md
swift-integration-tests - Automated tests for validating the generated Swift snapshots behave correctly
Avatar
swift-integration-tests - Automated tests for validating the generated Swift snapshots behave correctly
Avatar
norio_nomura 7/12/2017 9:28 AM
あ、そうですね。
Avatar
↓なるほどー、改行をエスケープしたくなるのか。 https://github.com/apple/swift-evolution/blob/master/proposals/0182-newline-escape-in-strings.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
XCTestといえばAssert系の関数を自前実装できるようにしてほしい。 特にXCTAssertEqualWithAcuracyはフィールドごとに確認するので増えるほど書くのがきつくなる stcuct Hoge { val a: Float } let x = Hoge(a: 0) let y = Hoge(a: 0) XCTAssertEqualWithAcuracy(x, y, accuracy: 1e-10) かといって関数に切り出すとXCodeで停止地点が分かりづらくなる。 XCTAsserEqualEquatableを実装するだけで使えるので 同様にNealyEquatableみたいなプロトコルを切ってXCTestがそれを使うXCTAssertEqualWithAcuracyを用意してくれるのがベストかな。
Avatar
omochimetaru 7/13/2017 1:46 AM
XCTestを捨てたら良いのでは
1:47 AM
その問題はXCTestとか昔のJUnitとかのテストフレームワークがずっと抱えてきた問題で
1:47 AM
最近のだとそういうオペレータをユーザ定義できるのが主流だと思う
Avatar
なるほど。 といってswiftの場合swift testとかで結構密接に結びついてるのでこちらからどうこうもしにくい気が。
1:48 AM
XCTest上で動く別のテストフレームワークを用意する?とかができるのかな
Avatar
omochimetaru 7/13/2017 1:49 AM
詳しくは知らないけど誰かが知ってそう・・・
Avatar
Carthage - A simple, decentralized dependency manager for Cocoa
1:53 AM
あ、 Carthage を SwiftPM でビルドする話。
Avatar
norio_nomura 7/13/2017 1:53 AM
かといって関数に切り出すとXCodeで停止地点が分かりづらくなる。 切り出した関数に…file: StaticString = #file, line: UInt = #line)とかつけると良いのでは。
Avatar
それでもいいですけど標準だと視覚的にぱっとわかりますからね……
Avatar
Quick - The Swift (and Objective-C) testing framework.
Avatar
どうやってXCode上で色々出来てるんだろうと思ったらXCTestにつながってるわけですか。 swift testもできるのかな?
Avatar
そりゃ継承してるんだからできるんじゃない?< swift test
Avatar
norio_nomura 7/13/2017 1:57 AM
個人的な意見としては、SwiftPMを使うならQuickとNimbleは使いたくないな。
Avatar
omochimetaru 7/13/2017 1:57 AM
Avatar
carthageのPackage.swiftはdependenciesがなんか複雑になってますね……
Avatar
omochimetaru 7/13/2017 1:57 AM
なんかトレンドとかあったらしりたいです
Avatar
テストのときだけ Quick を使いたいからじゃない? < 複雑
Avatar
そうですね。 https://github.com/Carthage/Carthage/blob/master/Package.swift#L4-L6 このへん何なんだろうってなる
Carthage - A simple, decentralized dependency manager for Cocoa
1:59 AM
ただの環境変数か
Avatar
Quick - The Swift (and Objective-C) testing framework.
2:01 AM
We still run swift test on CI using separated .Package.test.swift. This is the same as Carthage/Commandant#83.
Avatar
omochimetaru 7/13/2017 2:01 AM
script: + - mv .Package.test.swift Package.swift
2:01 AM
これがあるし
2:01 AM
すり替えるんじゃないかな、自力で
Avatar
norio_nomura 7/13/2017 2:02 AM
Swift 3 では結局testDependenciesがなかったので、テストの時だけ使う依存を実現してる。
Avatar
Currently "Test-only dependencies" feature is disabled in the Swift Package Manager. It was implemented initially, but was removed in this commit.
https://stackoverflow.com/a/41407032
I've seen mentions of test-only dependencies when using the Swift package manager but haven't been able to get them to work. For example: https://lists.swift.org/pipermail/swift-evolution/Week-of-...
2:03 AM
おおお、初期に testDependencies 見た気がしてたんだけど使えなくなってるのか・・・
2:04 AM
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/34b7826cb586b0769ea5f60a7718d7de599ce27f
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 va...
2:05 AM
それだと Quick とか使いたくないですね・・・。
Avatar
swift evolutionのほうは誰も出して無いのかな……
Avatar
norio_nomura 7/13/2017 2:05 AM
テスト用のPackage.swiftを用意してたけど、環境変数で切り替えられることをikesyoさんに伝えたら使ってくれた。 (edited)
2:06 AM
Swift 4のPackage ManifestでQuick, Nimbleがどの様に使えるかは、僕は知らない。
Avatar
omochimetaru 7/13/2017 2:07 AM
SWIFTPM_TEST_Carthage
ああこれはSPMが定義してくれるのか。
2:07 AM
なんか若干矛盾を感じるな・・・ SPMが定義するならSPM上のSwift APIで良いのでは・・・
Avatar
改めて考えると、テストって本体と別パッケージだと思うんですけど、本体用に作った Packagedependencies がテストからも使えるのなんか変な気も。
Avatar
そこはテストが間接的に依存してるからいいのでは?
Avatar
omochimetaru 7/13/2017 2:08 AM
@koher 使えないとメソッド引数の型とかに依存ライブラリの型が使われてたらテストできなくないですか?
Avatar
まあ実用面で考えるとテスト用のパッケージは本体に付随して生まれるものということでいいのかなぁ。
Avatar
omochimetaru 7/13/2017 2:10 AM
てか本来的には
2:10 AM
アプリターゲットとテストターゲットをわけて、テストターゲットがアプリターゲットに依存
Avatar
norio_nomura 7/13/2017 2:10 AM
> SWIFTPM_TEST_Carthage ああこれはSPMが定義してくれるのか。 Makefileで実行するときに設定してます。 https://github.com/Carthage/Carthage/blob/master/Makefile#L82
Carthage - A simple, decentralized dependency manager for Cocoa
Avatar
omochimetaru 7/13/2017 2:10 AM
っていう構造が自然な気がするけど
2:11 AM
Carthageの構造はあくまで Carthageパッケージがテスト用の状態に変化するっていう
2:11 AM
作りなんですね
2:11 AM
@norio_nomura ああ、なるほど、自前でタスクランナーかましてるなら納得です。最初分岐みたときそれを想像しました。
2:12 AM
環境変数で切り替えられることをikesyoさんに伝えたら使ってくれた。(
これを誤読しました。
Avatar
norio_nomura 7/13/2017 2:14 AM
Package.swiftがサンドボックス内で解釈される際に、SwiftPMがあえて環境変数を引き継ぐ様にしてるので、あながち間違いでもない。
2:15 AM
最初、環境変数を処理分岐に使えたのは意図せぬ挙動だったけど、サンドボックス化の際にサポートされた挙動になった、という感じ。
Avatar
omochimetaru 7/13/2017 2:16 AM
ふむふむ。
2:19 AM
「サンドボックス」ってここらへんの話ですか?
Avatar
norio_nomura 7/13/2017 2:19 AM
そう。
Avatar
omochimetaru 7/13/2017 2:19 AM
$ which -a sandbox-exec /usr/bin/sandbox-exec
2:19 AM
なんかはいってた
2:20 AM
DESCRIPTION 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.
2:20 AM
man引いたらいきなりDEPRECATEDって書いてあったw
2:21 AM
macになんかあった仕組みかあ
Avatar
norio_nomura 7/13/2017 2:22 AM
SwiftPMのSlackでその辺りが話されてたのを読んでました。
Avatar
omochimetaru 7/13/2017 2:22 AM
なるほど
Avatar
norio_nomura 7/13/2017 2:26 AM
sandbox-execを使う様にしたコミットには環境変数がらみが特に書かれてないぽいから「環境変数をあえて渡す」というのは、チャットの中だけの話だったかも。
Avatar
omochimetaru 7/13/2017 2:28 AM
なるほど。
Avatar
norio_nomura 7/13/2017 2:34 AM
そういえば、Xcode 9のXCTestに追加されたAPIって、もうswift-corelibs-xctestに移植されたのかな?
2:38 AM
なさげ…
Avatar
@norio_nomura 先程の#lineを使うってこれのことですか。 http://masilotti.com/xctest-helpers/ そもそもrecordFailureの存在を知らなくてログに行番号出るだけじゃ分かりにくいとか思っていました。
How to extract XCTest helper methods and keep sane failure messages.
Avatar
norio_nomura 7/13/2017 2:54 AM
そそ。XCTAssert*()シリーズにも渡せます。
Avatar
テストフレームワークが欲しいとかいうわけじゃないので僕の問題はこれで解決しそうです。 ありがとうございます!
3:00 AM
XCTAssert*()シリーズに渡せるってのは何でしょう? recordFailureXCTestCaseのメソッドなのでXCTAssert*()のようにトップレベルのを定義するにはデフォルト引数で呼び出し元のselfを渡すとかするのかなぁと思ったのですが。
3:01 AM
以前ここで話されたデフォルト引数にselfを渡す話をよく覚えていない……
Avatar
omochimetaru 7/13/2017 3:01 AM
XCTAssertEqualにline引数があるんじゃ? (edited)
Avatar
ありますね。 XCTestCaseは引数にないのでどこから渡っているのか謎。 別の仕組みになっているんだろうか。
Avatar
omochimetaru 7/13/2017 3:05 AM
XCTestCaseは関数じゃなくてクラスでは??
Avatar
recordFailureXCTestCaseのメソッドなんですよ。 で、XCTAssert*()はトップレベルなのでrecordFailureが使えない(はず)
3:08 AM
まぁ新しいのをXCTestCaseのextensionにすればいいんですが XCTAssert*()と同名を用いると例のバグ?でトップレベルのほうが見えなくなる。 (edited)
Avatar
omochimetaru 7/13/2017 3:11 AM
APIの外側にあるランナーが「現在のTestCase」を保持していて、XCAssertEqualは内部でそれを拾ってる気がする
Avatar
norio_nomura 7/13/2017 3:15 AM
SwiftLintで、SwiftLintのソースコード自体をlintしてviolationがあったらテストの失敗として記録する仕組みを作りました。そこではrecordFailure() ではなく XCTFail() を使ってました。 https://github.com/realm/SwiftLint/blob/master/Tests/SwiftLintFrameworkTests/IntegrationTests.swift#L35
SwiftLint - A tool to enforce Swift style and conventions.
Avatar
ああ、recordFailureを使うんじゃなくて内部でfile, line指定付きのXCTAssert*()を使えってことですね。 間違った方向に進んでました。
Avatar
#swift の array[...]ハック、引数を@autoclosure () -> Tで表現すれば割と何でも出来るな、ということに気がついた
5:41 AM
関数である必要もなくなる
Avatar
omochimetaru 7/13/2017 5:42 AM
ふむ
Avatar
そうするとつまり
5:44 AM
enum Foo { static var foo: Foo { fatalError() } } func bar(_ foo: @autoclosure () -> Foo, ....) { ... } bar(.foo, ....) これが可能になる
5:45 AM
何やりたいのか理解するのが非常に難しいw
5:45 AM
第一引数に与える型でオーバーロードを実現したいって話なんだけどね
Avatar
omochimetaru 7/13/2017 5:45 AM
Foo.foo が実際には生成されないのがポイント?
Avatar
Foo.fooの評価は、bar内でfoo()をするまで実行されない。したがってbarの中で使っていなければ…というのがポイント
Avatar
delegate.scrollView(scrollView, .didScroll) とかにいいかも (edited)
Avatar
omochimetaru 7/13/2017 5:47 AM
struct Foo {} let foo = Foo() func bar(foo: Foo, ....) { ... } bar(foo, ....) そもそもこれじゃ駄目な理由は?
Avatar
グローバルfooは少なくともなし
5:49 AM
struct Foo { static var foo = Foo() } ならまあ差はそれほど無いのかもしれない。
5:49 AM
実態渡してるから都度コピー出るけど最適化で消えるんですかね
Avatar
omochimetaru 7/13/2017 5:49 AM
それだと .foo で書けるね
5:49 AM
そもそも0バイトの型になって消えてそう。
Avatar
最適化で無になるなら、差は無いと言い切って良さそうだ
Avatar
omochimetaru 7/13/2017 5:52 AM
struct BarOverloads { static let foo = BarFoo() static let poo = BarPoo() } func bar(_ overload: BarFoo, ...) func bar(_ overload: BarPoo, ...) bar(.foo, ...) // できない bar(.poo, ...) (edited)
5:52 AM
あ、だめだな
5:53 AM
うまく定義をまとめられないかとおもったけどダメだった
Avatar
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)
5:53 AM
これならおk
Avatar
omochimetaru 7/13/2017 5:54 AM
なるほどw
Avatar
朝ラトナーがメーリスに投げてましたけど、Multi-line Stringのリファイメントが始まったみたいですね。改行に \ を使う感じで。 https://github.com/apple/swift-evolution/blob/master/proposals/0182-newline-escape-in-strings.md (edited)
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 7/13/2017 6:19 AM
これはうれしい気がする
Avatar
これいいですよね。
Avatar
いいですよね。メーリスみてても評判よさそう
Avatar
swift-evolution で、↑の改行エスケープを認めると↓が思いがけないバグになるって意見が出てる。なるほど。 let s = """ ... In Windows you have paths like C:\ ... """
Avatar
omochimetaru 7/13/2017 3:21 PM
Windowsの民はパス文字列にバックスラッシュがあって思わぬことが起きるのに慣れてて警戒するから大丈夫
Avatar
現仕様だと↑はコンパイルエラーになって \\\ に直さないといけないけど、新使用だとコンパイルエラーにならないから問題だと。特に """ だからといって文字列コピペしてきたときとかに問題起こりそう。
Avatar
それ言い出しちゃうと c:\news とかもそうなんで。ちょっと弱い。
Avatar
それはコンパイルエラーになるから直せるけど、たまたま行末に紛れてたら見過ごしそうじゃないですか?
Avatar
omochimetaru 7/13/2017 3:30 PM
nがにくっついて\nになるからコンパイルエラーにならないという意味では?
Avatar
ああ、そういうことか。
Avatar
omochimetaru 7/13/2017 3:31 PM
つまり現状でもコンパイルエラーにならないが意図せず出現した \ などによって思わぬ変化は起きるのだから同じだよと
Avatar
なるほど、たしかに。
Avatar
norio_nomura 7/15/2017 1:23 AM
Optionalのclosureでtupleが分解できない問題治してもらえた。はやいw swift-4.0-DEVELOPMENT-SNAPSHOT-2017-07-11-a以降で直ってるぽいですね。
💞 1
Avatar
WWDC の "What's New in Swift" で COW Existential Buffers について触れられてますが、 Existential じゃない普通の struct でもサイズが大きいと勝手に最適化されたりするんでしょうか?どこかで触れられてましたっけ? https://developer.apple.com/videos/play/wwdc2017/402/
Swift 4 continues the evolution of the safe, fast, and expressive language, with better performance and new features. Learn about the new...
Avatar
omochimetaru 7/20/2017 1:02 PM
自分が調べた限りではstructについては大きくなってもヒープ化はされなかったですよ
1:02 PM
その話なのかはわからないですが
Avatar
↑の COW Existential Buffer は Swift 4 からの話なので、新しく何かあるのかも?
Avatar
omochimetaru 7/20/2017 1:03 PM
あと、ヒープ化が標準で、小さい時のスタック化の方が最適化だと思う
1:03 PM
なるほど
Avatar
(興味があれば)↑のビデオの15:30あたりから話してる。
Avatar
omochimetaru 7/20/2017 1:07 PM
興味アリアリ
Avatar
https://github.com/apple/swift/pull/8909 これの話かと思ったら違った。
radar rdar://problem/28680453 Reduce the size of the text area (code size of the compiled output) by changing the way we generate LLVM IR for loadable types: We do a SIL level transformation, durin...
1:23 PM
https://github.com/apple/swift/pull/9142 こっちか。大きい値型を自動的にアドレス渡しにしてコードサイズを減らそうっていう件。
radar rdar://problem/28680453 This is an updated version of #8909 It addresses the code review comments and splits the PR into multiple commits Reduce the size of the text area (code size of the co...
1:24 PM
が実装されたんだけど、問題起きて disable されちゃいました。4.0 には入らないと思います。 https://github.com/apple/swift/pull/9452
radar rdar://problem/32064645 Disable large types irgen pass (for now) Swift 4.0 PR #9447
😂 1
Avatar
we'll get back to this transformation at some point, making sure it is truly great, but it is not going to be re-enabled on the 4.0 branch.
1:27 PM
残念・・・。
Avatar
https://teratail.com/questions/13866 ここで岸川さんが言ってる、
structは24バイトを越えるとheapに追い出されます。
とは別の話ですか?
Swiftのstructはclassとよく似ているところがありますが、どのように使い分けるのでしょうか。structの性質を使った、実際の実装パターンなどありましたらご教授をお願いできればと思います。
Avatar
omochimetaru 7/20/2017 1:29 PM
32バイトのstructでも、スタックに置かれていることが分かります。
どんなコードを書いたらstructはヒープに置かれるんですか? また、あたなのSwiftのバージョンはいくつですか?(ちなみに上記の結果はSwift1.2です。) 仮にstructがヒープに置かれた場合、CやObjective-Cとの互換性はどうなりますか?
1:29 PM
レスで反論されてるね
Avatar
お、ほんとだ
Avatar
omochimetaru 7/20/2017 1:29 PM
俺もおかしいと思った
Avatar
岸川さんの情報源は何だったのか気になる・・・
Avatar
Existential に入れたときの挙動とごっちゃになったのかな?
Avatar
omochimetaru 7/20/2017 1:31 PM
Existentialのときはヒープ退避しますね、24で
1:31 PM
24までは収まるから25以上で、か
Avatar
そのヒープ退避されたバッファの扱いがSwift4でCOWになる? (edited)
1:36 PM
これまでは代入の度にヒープに新しい領域確保してコピーしてたってこと??
Avatar
omochimetaru 7/20/2017 1:37 PM
僕がLLVM読んだときはそんなふうに見えた
1:37 PM
C++のstd::stringみたいな感じで。
Avatar
std::string は確か COW だったけど COW 止めたんよね?
Avatar
omochimetaru 7/20/2017 1:39 PM
ポインタを持った外側の構造体(existential)がコピーされるときに、その参照先の実態をヒープ上で複製する
1:39 PM
そうですね。
1:39 PM
24バイトまでのSSO (Small String Optimization)っていって
1:39 PM
それは残ってる
1:40 PM
全く同じですね
Avatar
マルチスレッドでリファレンスカウント操作するところで同期しないといけなくてパフォーマンス上の問題があったって聞いたんだけど、 Swift の Array 等の場合はマルチスレッドをサポートしないことで問題を回避している??
Avatar
omochimetaru 7/20/2017 1:41 PM
Swiftの参照カウンタもスレッドセーフっぽかったですよ
1:41 PM
atomicなんたらとか出てきた
Avatar
うーん、昔はアプリレベルだと問題ないんじゃない?と思ったけど、Swiftをあらゆる用途で使おうとすると同じ問題にひっかかりそうな気がするんだけどどういう判断なんだろう?
Avatar
omochimetaru 7/20/2017 1:45 PM
僕はそもそも参照カウンタ操作が遅いっていうのがあんまり信じられない
1:45 PM
atomic操作になるんで
Avatar
インクリメントやデクリメントはatomicにできても
1:46 PM
COWの参照カウントチェックの部分は同期しないといけないのでは?
Avatar
omochimetaru 7/20/2017 1:46 PM
1:47 PM
インクリメントして、結果をもらうところまでがアトミックです
1:47 PM
デクリメントして0になるスレッドはひとつだけだから
1:47 PM
0かどうか観察する分岐はロックしない
Avatar
Arrayの要素を変更しようとしてバッファの参照カウントを確認した結果1だったからコピーしなくていいやとなったけど、それと同時に別スレッドで代入されて参照カウントが2になったらバグらない? (edited)
Avatar
https://github.com/apple/swift/pull/7557 非アトミック版の参照カウンタを使うっていうオプションがあります。興味あれば。
Avatar
おお、そんなものが・・・😶
Avatar
omochimetaru 7/20/2017 1:54 PM
ソースレイアウトが結構変わってて探し中
Avatar
うーん、単に代入前に変更されたように見えるだけか?
Avatar
omochimetaru 7/20/2017 1:54 PM
Arrayの要素を変更しようとしてバッファの参照カウントを確認した結果1だったからコピーしなくていいやとなったけど、それと同時に別スレッドで代入されて参照カウントが2になったらバグらない?
これはデクリメントじゃなくてコピーするときの話ですよね
1:55 PM
えーっと・・・
1:55 PM
1だったときは
1:55 PM
そもそも1つのスレッドからしか参照されてないのでは
Avatar
同じ変数が複数スレッドから参照されることはあるのでは?
Avatar
omochimetaru 7/20/2017 1:57 PM
そのためにはカウンタが2になりません?
Avatar
↓のようにしても参照カウントは 1 のままじゃないの? var a = [2, 3, 5, 7] // スレッドA a[2] = 4 print(a) // スレッドB a[3] = 8 print(a) (edited)
Avatar
omochimetaru 7/20/2017 1:59 PM
ちょっと僕も考えながらなので不正確かもしれないですが (edited)
1:59 PM
まずスレッドっていうのは
1:59 PM
関数ポインタと任意ポインタのペアでエントリするのが一番ローレイヤにあって
1:59 PM
Swift上で考えると
1:59 PM
startThread( closure: () -> Void )
1:59 PM
な処理を呼び出すことになって
1:59 PM
そのコードだと
2:00 PM
var a = [2, 3, 5, 7] a[2] = 4 startThread { a[3] = 8 }
2:03 PM
Swiftって参照キャプチャなんだっけ・・・
2:04 PM
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()
Avatar
今ってバッファは struct である Array に包まれてるから
2:05 PM
バッファがキャプチャされるわけではなくない?
2:06 PM
var a = 2 let foo: () -> () = { a += 1 } foo() print(a) // 3
2:06 PM
↑から、値がキャプチャされるときにコピーされてるわけではないことがわかる。
Avatar
omochimetaru 7/20/2017 2:07 PM
えーっとそうか思い出した
2:08 PM
キャプチャがおきるときは、キャプチャされてる変数をフィールドにもつスコープオブジェクトが作られていて
2:08 PM
クロージャがエスケープするときはそのスコープオブジェクト自体がヒープにいるんだ (edited)
2:09 PM
バッファがキャプチャされるわけではなくない?
それはそうですね
2:09 PM
ラッパーstructのArrayがコピーされるときに
Avatar
そうなんだ。それって実行時に決まるの?
Avatar
omochimetaru 7/20/2017 2:09 PM
いや
2:09 PM
@escaping
2:10 PM
あるなしでわかる
2:10 PM
@nonescaping なときはキャプチャされていても
2:10 PM
スタックメモリをポインタ参照させればいいから
2:10 PM
早くなる
Avatar
↓みたいなケースでは、極稀なケースのために毎回ヒープにスコープオブジェクトが確保される?? var a = 42 if random() < 0.0001 { foo = { print(a) } }
Avatar
omochimetaru 7/20/2017 2:11 PM
それだけなら foo がエスケープしてないからならない (edited)
Avatar
foo はグローバル変数かなにか
Avatar
omochimetaru 7/20/2017 2:12 PM
毎回、じゃ、無い気がする。その5行について1個
2:13 PM
ん?ループもないからそもそも1回か (edited)
2:13 PM
とりあえず、aはスタック上には無いと思います
Avatar
var foo: () -> () = {} func bar() { var a = 42 if random() < 0.0001 { foo = { print(a) } } } for _ in 1...10000000 { bar() }
2:14 PM
↑みたいなイメージ。
Avatar
omochimetaru 7/20/2017 2:14 PM
はい、その場合、ヒープにアロケート/でアロケートしまくると思ってます。
Avatar
bar のコールのほとんどではスタックで済ませられるはずだけど、
2:15 PM
毎回ヒープになるのか・・・。
Avatar
omochimetaru 7/20/2017 2:15 PM
ArrayのCOWは、mutatingなメソッドを呼び出すとき(たとえば、 a[0] = 99 に、バッファストレージインスタンスの参照カウンタを見て、1ならそのまま書き換える、2以上ならディープコピーする、だから・・・
Avatar
ディープコピーするの?シャローでは?
Avatar
omochimetaru 7/20/2017 2:16 PM
ストレージの先の参照型はクローンしないという意味ではシャローですね
2:16 PM
ストレージ自体をクローンする、っていいたかった
Avatar
さっきの話だと、↓みたいにしても a のスコープ自体がヒープに確保されてるから a のバッファへの参照カウントは常に 1 になりそう。 var a = [2, 3, 5, 7] // スレッドA startThread { a[2] = 4 print(a) } // スレッドB startThread { a[3] = 8 print(a) }
Avatar
omochimetaru 7/20/2017 2:19 PM
えーっと・・・そうですね、ヒープ上にあるスタックオブジェクトのカウントが最大3になって、
2:19 PM
スタックオブジェクトのフィールドに a の実体が1つだけあって
2:19 PM
その内部のストレージのカウントもずっと1ですね (edited)
2:19 PM
そのコード、 a[2] = 4 とかを、ユーザ側で ロックしないとバグりそう?
2:20 PM
スレッドが終了するタイミングでスタックオブジェクトのカウンタが減っていって、スレッドA,B、メインが終わった時点で0になってヒープから a の実体が消えて、その先のストレージも消える。
Avatar
問題は参照カウントのインクリメント/デクリメント自体が atomic だったとしても、参照カウントチェック→更新までの間に参照カウントが変化するとCOWが壊れて値型としての挙動がおかしくなることがあり得るか (edited)
Avatar
omochimetaru 7/20/2017 2:21 PM
えっとつまり、ランタイムの参照カウンタレベルでは壊れないけど、それよりうえのArray自体がスレッドアンセーフなのでそのコードはバグってる、
Avatar
Array がスレッドアンセーフなのと、 COW がスレッドセーフかどうかと、参照カウンタがスレッドセーフなことは独立な気がする。
Avatar
omochimetaru 7/20/2017 2:23 PM
そうですね
2:23 PM
僕が最初から言いたいのは
Avatar
それとも、 Array がスレッドアンセーフな時点で Array の COW もスレッドセーフである必要はない?
Avatar
omochimetaru 7/20/2017 2:23 PM
参照カウンタがスレッドセーフって話
2:23 PM
で、 それとも、 Array がスレッドアンセーフな時点で Array の COW もスレッドセーフである必要はない? これがYESだと思います。
2:23 PM
あ、イエスとかいうとわかりにくいな
Avatar
英語と日本語でひっくりかえるやつだw
Avatar
omochimetaru 7/20/2017 2:24 PM
Array 自体がスレッドアンセーフな時点で、 ArrayのCOWだけのスレッドセーフティーを考える意味がなくて、それもアンセーフ
Avatar
それなら参照カウンタはatomicでオーバーヘッドのない1命令で済ませられるなら、 Array のCOWに同期のオーバーヘッドはないと。
2:25 PM
C++ のかつての std::string はスレッドセーフにしようとしたから問題があったってこと?
Avatar
omochimetaru 7/20/2017 2:25 PM
COW特有の、1かどうかみる、というところのややこしい話はArrayをロックして使ってね、という範疇で解決する?
2:26 PM
std::string 自体はスレッドセーフじゃないと思うんだよなあ
Avatar
Array をロックして使ってれっば問題は起こらない気がする。
2:26 PM
そうすると std::string が COW でなくなったのは別の理由なのかな?
Avatar
omochimetaru 7/20/2017 2:27 PM
この記事はC++ Advent Calendar 2013の15日目にエントリしています。 内容はC++標準ライブラリとスレッドセーフに関する解説になります。 flickr / rennasverden もくじ What's スレッドセーフ? スレッドセーフという幻想 基本型とデータ競合 C++標準ライブラリとデータ競合 C++標準ライブラリ:シーケンスコンテナ編 C++標準ライブラリ:連想コンテナ編 スレッドセーフ RELOADED 基本的なスレッドセーフ保証 std::shared_ptr std::rand() std::cout (本文のみ約9000字) はじめに マルチスレッド…
2:28 PM
Q3. std::stringクラスはスレッドセーフですか? Q3. 「同時アクセスが全て読み込み操作(constメンバ関数相当呼び出し)であれば安全」というスレッドセーフ性レベルが保証される。
2:28 PM
この人はC++界隈で強くて有名な人
2:28 PM
「readonlyならば安全」という「レベル」 というのが答えらしい
Avatar
今の std::string と COW だった頃の std::string はまた別かもしれない・・・
Avatar
omochimetaru 7/20/2017 2:28 PM
readonlyならば、ってことは、COWは関係ないですね
2:29 PM
そうなんですけど、
2:29 PM
C++11になるまで
Avatar
COW じゃなくなった経緯がわからないと何とも言えなさそう。
Avatar
omochimetaru 7/20/2017 2:29 PM
C++11スレッドサポートの文脈では新規クラス追加ばかりが注目されています。このような華やかな表舞台の裏側では、以前からあるstd::stringやstd::vectorといったクラス群に対して、スレッドサポートに関連する重要なルールが明確化されたことは知っていますか?
2:29 PM
C++11で std::thread が入るときにこの規格がちゃんと整理されたって話がこの記事に同時に書いてあるので
2:30 PM
C++03以前でもしスレッドセーフだったとしたら、ライブラリが善意でがんばってた、だけの話が気がする
2:30 PM
C++11標準ライブラリのスレッド安全性Add Star
C++ C++11標準ライブラリが提供する機能とスレッド安全性(thread safety)についてのメモ*1。C++03以前では処理系依存。 http://d.hatena.ne.jp/yohhoy/20120513/p1
2:30 PM
処理系依存だったそうな
Avatar
このようなCOWによる文字列クラスの実装は、30年前はともかく、今となってはとても効率が悪い。なぜならば、マルチコア、マルチスレッドが当たり前になってしまったからだ。今は文字列クラスをCOWで実装すべきパフォーマンス上の理由がないので、C++11では、COWで実装することは規格で禁止された。
https://cpplover.blogspot.jp/2013/12/c03c11_29.html
今日も今日とて、C++03とC++11の違いを解説する。今回は、文字列ライブラリー編だ。 変更: basic_stringをリファレンスカウントで実装することを禁止 C++が設計中の時代は、文字列を保持するストレージを文字列クラスで共有して、参照数を記録しておき、変...
Avatar
omochimetaru 7/20/2017 2:31 PM
あー僕が最初にこの話題みたのこの記事かも。
2:32 PM
なぜならば、マルチコア、マルチスレッドが当たり前になってしまったからだ。今は文字列クラスをCOWで実装すべきパフォーマンス上の理由がないので、C++11では、COWで実装することは規格で禁止された。
このロジックも逆によくわからないですね
2:32 PM
あ、いや、いいのか
2:33 PM
COW自体はシングルスレッドでも効果があるから。
Avatar
シングルスレッド前提なら同期コストがいらなかったけど、スレッドセーフにしようとすると同期コストがネックになるって話じゃないかな?
Avatar
omochimetaru 7/20/2017 2:33 PM
あれ?でもマルチスレッドでもstd::string自体はreadonly thread safeなのであれば、COWを搭載する意味はあるような・・・
2:33 PM
いや、ないのか
2:33 PM
readonlyなときにはWがないから
Avatar
WがなくてもCOWじゃなかったらコピーが走っちゃうのでは?readonlyでも。
Avatar
omochimetaru 7/20/2017 2:36 PM
あーそうか、readonlyでコピーするときに共有ですませるのがCOWの意義か
2:36 PM
あーーわかったわかった
2:36 PM
COWで共有したときは
2:36 PM
std::string としては、2つに見えてるんだ。ユーザには。
2:37 PM
でも、ユーザからしたら、 std::string 一個単位で readonly safe ってことしか聞いてないから (というかコピーをまたいだグループでロックを取るなんで不可能)
2:37 PM
COWを意味のある形で実装するならスレッドセーフじゃないとだめか
Avatar
え?なんで?それってさっきの Array の COW はスレッドアンセーフでいい話と矛盾してない?
Avatar
omochimetaru 7/20/2017 2:38 PM
SwiftのArrayの話のときそのパターン考えてなかった
Avatar
あー、そういうことか
Avatar
omochimetaru 7/20/2017 2:39 PM
SwiftのArrayがコピーされるときは、そのとき内部でストレージへの参照がコピーされて、そのときそこだけatomicにちゃんと2になる
Avatar
var a = [2, 3, 5] // スレッドA a[2] = 4 // スレッドB var b = a b[2] = 999
2:39 PM
みたいなときに、 ab で同期とるとか無理でしょってことか。
Avatar
omochimetaru 7/20/2017 2:39 PM
そうそう
2:40 PM
var a = [2, 3, 5] // スレッドA startThread { a[2] = 4 } // スレッドB startThread { var b = a b[2] = 999 }
Avatar
そうすると Array 自体はスレッドアンセーフでも COW はスレッドセーフでないといけないってこと?
Avatar
omochimetaru 7/20/2017 2:41 PM
んー・・・? ↑のコードなら、 a[2] = 4var b = a の2行を、ユーザがロックすべきだと思う。
2:42 PM
b = a の代入の最中に、 a[2] = 4 の処理が走り始めて内部状態が壊れる可能性があるはず。
2:42 PM
じゃあstd::stringの話も一緒か。
2:43 PM
C++11で a[2] = 4 が書き込み操作で、 b = a の右辺はreadだから、競合してるのでロックが要るって事になるはず (edited)
Avatar
そこが最初に考えてたところで、仮に COW の参照カウントチェックから変更までが atomic じゃないとして
Avatar
omochimetaru 7/20/2017 2:43 PM
はい
Avatar
Array のスレッドアンセーフに関係ないところで
2:44 PM
COW をぶっ壊して値型としての振る舞いを壊す例ってどういうのだろう?
2:45 PM
Array はスレッドアンセーフなまま COW の部分だけスレッドセーフにして防げる事例。 (edited)
Avatar
omochimetaru 7/20/2017 2:45 PM
ありえない気がするんだよなあ Arrayの内部ストレージに触れるのはArrayのメソッド実装部分だけだから
Avatar
それがないなら Array の COW はやっぱりスレッドアンセーフでいいということになるのかなぁ・・・。
2:45 PM
話が堂々巡りしてる・・・
Avatar
昨日の↓これ本当? int の書き込みは atomic で同時なんてないんじゃないの? Q4. 基本型intはスレッドセーフですか? A4. 「同時アクセスが全て読み込み操作であれば安全」というスレッドセーフ性レベルが保証される。 http://yohhoy.hatenablog.jp/entry/2013/12/15/204116
この記事はC++ Advent Calendar 2013の15日目にエントリしています。 内容はC++標準ライブラリとスレッドセーフに関する解説になります。 flickr / rennasverden もくじ What's スレッドセーフ? スレッドセーフという幻想 基本型とデータ競合 C++標準ライブラリとデータ競合 C++標準ライブラリ:シーケンスコンテナ編 C++標準ライブラリ:連想コンテナ編 スレッドセーフ RELOADED 基本的なスレッドセーフ保証 std::shared_ptr std::rand() std::cout (本文のみ約9000字) はじめに マルチスレッド…
Avatar
int一般がatomicなんて言ってないです
12:53 AM
CPUにそういう機能があって
12:54 AM
APIがあいてたり
12:54 AM
I have googled for atomic increment and decrement operators on Mac OS X and found "OSAtomic.h", but it seems you can only use this in kernel space. Jeremy Friesner pointed me at a cross-platform a...
12:55 AM
cppではさらにそれを標準化したりしてる
12:55 AM
cppの方はCPUに機能が無ければロックになってる可能性もあるけど
Avatar
インクリメントは特殊な命令じゃないとatomicにならないのはわかるけど、ただの代入でもatomicになるとは限らない??
Avatar
もちろん
12:56 AM
というかそうじゃなくて
12:56 AM
命令が一単位かどうかは関係なくて
12:56 AM
コンパイラがその理論的仮定に基づいた最適化をするんで (edited)
12:56 AM
仮にCPUレベルで分解不能なコードであっても
12:57 AM
マルチスレッドセーフにはならないです
12:57 AM
順番入れ替え最適化があって
12:58 AM
シングルスレッドなら最終的に同じ結果になるけど
12:58 AM
コードの実行順が変わるとかあるので
Avatar
atomicだけどスレッドセーフでないと言っている?
1:05 AM
それともintの代入自体がatomicであることも保証されていない?
Avatar
omochimetaru 7/21/2017 1:11 AM
intへの代入のatomic性が保証されているかどうかは知らないです。 ただもしatomicだったとしても、複数のスレッドから同じ変数を見ていて、 ライターとリーダーがいるとき、 順序性の保証が無いから、だいたいバグるので、 なんらかの同期機構を使わずに生のintを共有すること自体がナンセンスだと言ってます (edited)
1:12 AM
ただし昨日の話とも絡むけどリードオンリーなら生のintで共有しても大丈夫なはず。 (edited)
Avatar
ロックフリーのアルゴリズムとかってatomic性に依存してる気がするんだけど、順序が入れ替わることを考慮しても大丈夫なのかな?
Avatar
omochimetaru 7/21/2017 1:13 AM
そのアトミックな命令に依存する箇所は順序性の保護が伝搬するはず
1:13 AM
あーちょっとそこはわかんないな
1:14 AM
でも、少なくともCAS命令の単位ではアトミックで
1:14 AM
スレッド同士が同じところを見るのがCASだけになってれば
1:14 AM
その前後は入れ替わってても、シングルスレッドの範疇で同じ結果に観測される
Avatar
CASでもインクリメントでも代入でも↓については同じ話じゃない?
命令が一単位かどうかは関係なくて
Avatar
omochimetaru 7/21/2017 1:15 AM
同じ話じゃないです
1:15 AM
えっとたしかに、代入だけを議論すれば
1:15 AM
アトミックだったかもしれないけど
1:15 AM
代入だけで役に立たないでしょう
1:15 AM
そのあと読まないと。
1:16 AM
もしくは、読んだ後に代入とか
1:16 AM
なにかしら代入とはアトミック性が連結しない、その変数のリードや、他の変数のリードライトが
1:16 AM
一緒に存在しないと、そのそもそもの代入を副作用とするロジックが書けない
Avatar
代入とreadがatomicだとして、元のブログの↓のコードはどんな問題が起こる? // 同一変数に対して片方が変更操作 int y = 2; void th1() { int r2 = y; // NG: データ競合 } void th2() { y = 42; // NG: データ競合 }
Avatar
omochimetaru 7/21/2017 1:19 AM
r2が2か42か不定ですね
1:19 AM
この例だとグローバル変数だから無さそうだけど、例えば、th2の中身が丸ごと最適化で消えて、42の可能性が0%になる、とか、
Avatar
それはたとえ th1th2 の中でロックしてても不定じゃない?
Avatar
omochimetaru 7/21/2017 1:20 AM
ちょっと書き加えていく仮定でどんどん変な事が起こり得る状態になります
1:20 AM
ロックしてても不定だけど、
1:20 AM
どっちになるか不定なコードとしてはそっちが正しい
Avatar
↓であったとしてもロックが必要ってこと? struct Counter { var count = 0 mutating func countUp() { count += 1 } mutating func reset() { count = 0 } } (edited)
1:22 AM
あー、インクリメントは
1:22 AM
atomic なインクリメントをするとして
Avatar
mutatingじゃないとじゃ
Avatar
ホントだ。修正しました。
Avatar
話よく分かってないですけどstructの場合CoWで実体分かれて問題ないんでは
Avatar
omochimetaru 7/21/2017 1:24 AM
atomicなインクリメントと、生のリードを一緒に使っていいかはわかんないです
Avatar
readじゃなくてreset の write の方
Avatar
omochimetaru 7/21/2017 1:25 AM
それもわかんないです。
1:26 AM
同じ仲間の命令の書き込み命令を使うべきか、普通の書き込みと協調するのか知らないです
1:26 AM
std::atomic<int>なら、リードもライトもインクリメントも専用メソッドがあるので
1:26 AM
僕がcppで書くときはそこを気にしない
Avatar
@t.ae まず、 struct だからといって CoW は自動的には起こりません。
1:28 AM
std::atomic<int>なら、リードもライトもインクリメントも専用メソッドがあるので
それはまた別の話じゃない?今atomicityを仮定しているので。
1:29 AM
readもwriteもincrementも。
Avatar
omochimetaru 7/21/2017 1:30 AM
全部仮定してるならそのクラスは問題なさそうだけど
1:30 AM
incrementメソッドが実質的に役に立たないと思う
Avatar
↓が問題なのは、readやwriteのatomicityが保証されてないからなのか、それとも「順序」の問題なのか。 // 同一変数に対して片方が変更操作 int y = 2; void th1() { int r2 = y; // NG: データ競合 } void th2() { y = 42; // NG: データ競合 }
Avatar
omochimetaru 7/21/2017 1:31 AM
その結果を見ようとしてresetに割り込まれるかも。
1:32 AM
外部で同期して同時にincrementしまくってから外部で同期したあとに読む、とかなら
1:32 AM
意味あるか。
1:32 AM
えーと
1:33 AM
最大の問題は、規格上明確にデータ競合であることですね
1:33 AM
データ競合→未定義動作→全て消していい
1:33 AM
みたいな、全く斜め上の結果とか
1:34 AM
ありえるかも。
1:34 AM
てか実際そういう話があって江副さんのブログで読んだ事がある
Avatar
それって↑の代入やインクリメントの代わりに CAS でも同じことが言えて、ロックフリーなプログラムとか書けなくならない? (edited)
Avatar
omochimetaru 7/21/2017 1:36 AM
少なくともCAS命令同士はデータ競合を起こさないので
1:36 AM
同じ変数を読むスレッド、書くスレッド両方が、CASだけでアクセスすれば大丈夫です
1:36 AM
読む方はCASだと困るか
1:37 AM
まあそのCASと一緒にやっていいと規定された操作
Avatar
それだと、 int y = 2; void th1() { y = 99; } void th2() { y = 42; } の代入が atomic なら↑も OK となりそうだけど・・・。
Avatar
omochimetaru 7/21/2017 1:37 AM
アトミックな型はC++においてデータ競合の問題が発生しない唯一の型です。
って書いてあるし
1:38 AM
それはデータ競合でヤバそう
1:38 AM
たとえば
1:38 AM
std::atomic<int>::load() と std::atomic<int>::compare_exchange_strong() を使って
1:38 AM
プログラムをかけば
1:38 AM
データ競合は起こらないからちゃんとロックフリーアルゴリズムがかけます
Avatar
代入自体が atomic でないってこと?
Avatar
omochimetaru 7/21/2017 1:39 AM
話が2つあって
Avatar
疑問は二つで、
  • C++ において int の代入は atomic なのか
  • atomic だと仮定して↑はスレッドセーフなのか
1:39 AM
後者は成り立つ気がしてるんだけど。
Avatar
omochimetaru 7/21/2017 1:41 AM
・実際のある特定のCPUにおいてある種の操作がCPU命令としてatomicかどうか ・そのようなCPU特性を前提に書いたC++コードがスレッドセーフかどうか
1:41 AM
で、現実的には2の問題でだいたい壊滅する
1:41 AM
でもそういう話がしたいわけじゃなさそうなので
1:41 AM
そこを巻き戻すと
Avatar
あらゆるCPU命令を考えたら前者が成り立たないからスレッドセーフと言えないということでいいのかな?
Avatar
omochimetaru 7/21/2017 1:42 AM
違います
1:42 AM
仮にコンパイルターゲットが前者に一致して、うまくいきそうにみえても
1:42 AM
「C++規格上で」やっちゃいけないことをやっている場合
1:43 AM
積極的に破壊される可能性があります。
1:43 AM
つまり、実際には、「C++規格」っていう実際のCPUとは関係ないルール(実際のCPUよりも厳しい)
1:43 AM
のもとで正しいコードを書かないといけない。
Avatar
それはC++の規格上で int の代入がatomicでないから、ってことやんね?
Avatar
omochimetaru 7/21/2017 1:43 AM
そこはまだまって
1:44 AM
疑問は二つで、 - C++ において int の代入は atomic なのか - atomic だと仮定して↑はスレッドセーフなのか
1:44 AM
「intの代入はatomicなのか」って質問がすごく難しくて
1:44 AM
少なくとも
1:44 AM
アトミックな型はC++においてデータ競合の問題が発生しない唯一の型です。つまり、あるスレッドがアトミックなオブジェクトに書き込んでいる間に他のスレッドがそれを読み込んだ時、その動作はうまく定義され、未定義動作とはなりません。
なので
1:44 AM
C++規格上、intは、「同時に読み書きするとデータ競合を引き起こす型」なので
1:44 AM
未定義動作とされて
1:44 AM
ぶっ壊れる可能性がある
1:45 AM
でもそれが
1:45 AM
「atomicでない」
1:45 AM
と言えるのかよくわからないです。
1:45 AM
C++だとatomicにも4段階ぐらいのレベルがあって (edited)
1:47 AM
(調べ中
Avatar
C++でなくて、intの読み書きがatomicであることが保証されている言語なら↑のコードも問題がないよね?
Avatar
omochimetaru 7/21/2017 1:48 AM
以下の列挙値はatomic変数への操作に指定可能な順序付けの種類を表す。
https://cpprefjp.github.io/reference/atomic/memory_order.html
コンパイラに許可されている最適化の一つに、「プログラムの意味を変えない限りにおいて、メモリアクセスの順番を変えたり、省略したりしてもよい」というものがある。また、マルチコアCPUにおいては、あるCPUコアによるメモリアクセスの順序が他のコアからも同じように見えるとは限らない。このような挙動はマルチスレッドプログラミングにおいて問題になることがある。
1:48 AM
これだ、なんか6通りぐらい概念があって
1:49 AM
int にたいしてどれが適用されるかよくわからない。
1:49 AM
- atomic だと仮定して↑はスレッドセーフなのか
で、これは、スレッドセーフだと思います。
1:49 AM
ただもちろん
1:49 AM
代入だけじゃなくて
1:49 AM
リードも
1:49 AM
その代入と対でみてアトミックならって話ですが。
Avatar
はい。そのつもりです。 < read も atomic (edited)
Avatar
omochimetaru 7/21/2017 1:50 AM
それならこれ自体はある時刻でyが2か42か99のどれかになるプログラム。 どれになるかはわからないけど、安全にどれかにはなる (edited)
1:51 AM
スレッド2つとも終了時点では42か99の2択。
Avatar
Java だと longdouble 以外のプリミティブや参照の読み書きは 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.html
Avatar
int の読み書きが atomic かどうかを調べて atomic だと知って安心した記憶があるんだけど、 Java の話だったのかなぁ。その感覚で int の読み書きを atomic だと思っていたから↓がおかしいんじゃないかと思ったけど、 // 同一変数に対して片方が変更操作 int y = 2; void th1() { int r2 = y; // NG: データ競合 } void th2() { y = 42; // NG: データ競合 } C++ では規格上 atomic でないからたとえそれを atomic に行う CPU 向けにコンパイルしたとしてもどのように最適化されるかわからず未定義動作なので↑は正しい、と。
Avatar
omochimetaru 7/21/2017 2:01 AM
はい。C++の話をするなら、「規格上atomicでないからどのようになるかわからないからバグ」は結構大事です、素朴な知識だと踏み抜くので
Avatar
Swift はどうなってるんだろう?
Avatar
omochimetaru 7/21/2017 2:02 AM
例のごとく規定されてないのでは・・・
😂 1
Avatar
少なくとも参照カウントは atomic にインクリメント/デクリメントされてるだろうけど。
Avatar
omochimetaru 7/21/2017 2:03 AM
それはそうで、内部をみたときに、Atomicなんたらとか使われてた。
2:04 AM
問題はSwiftのコードとして、 var a = 3 var b = 2 a = 4 b = 1 print("a=\(a), b=\(b)") (edited)
2:05 AM
とかなってたときに、 a= 3, b = 2, a = 4, b = 1 って順序で必ず変化するか、代入がatomicか、などが不明ってことですね
Avatar
Int 等の代入や、参照型のアドレスの代入が atomic なのか気になる。
Avatar
omochimetaru 7/21/2017 2:05 AM
実際、 a = 3b = 2 の時間帯は削除されるんじゃないかなあ。
Avatar
アドレスの代入が atomic じゃなかったらヤバイ動作しそうだな・・・
Avatar
omochimetaru 7/21/2017 2:06 AM
LLVMのオプティマイザが賢そうなので。
Avatar
同時に代入したらアドレスの上位4バイトと下位4バイトが合成されたものができあがったとか・・・
Avatar
omochimetaru 7/21/2017 2:07 AM
そうですねえ。まあ、実際64bit CPUならそういうのは大丈夫そうですが。
2:08 AM
個人的には
2:08 AM
実際c++と同程度に過激な最適化が
2:08 AM
されるんじゃないかと思ってる
2:08 AM
UnsafePointer<T>のヤバイ話とか見ても(前削除されたAPI
2:08 AM
LLVMから先で同じ事やってそう
Avatar
Int やアドレスの代入が atomic でないなら、結構気を付けてプログラム書かないといけないなぁ
2:15 AM
Swift Programming Language を "atomic" で検索してみたけど何もなかった。
Avatar
omochimetaru 7/21/2017 2:16 AM
2:17 AM
わざわざこれをやってるということは Int の read / write ですら atomic ではない?
Avatar
omochimetaru 7/21/2017 2:17 AM
あ、これ .swift か。
2:18 AM
これがあるってことはそんな感じがしますね > ただの Int じゃ駄目 (edited)
2:18 AM
あ、あと、普通の変数って、 Int であっても
2:18 AM
メモリ上の8バイトの値と
2:19 AM
CPUで計算する前にレジスタにコピーして
Avatar
↓できた。 let a = _stdlib_AtomicInt(42)
Avatar
omochimetaru 7/21/2017 2:19 AM
レジスタで計算してからメモリに書き戻したりするので
2:19 AM
で、関数のコンパイル時にローカル変数とかをできるだけレジスタで済ませようとしたりするので
2:19 AM
「Intの代入がatomic」だとしても
2:19 AM
なんかもっと計算手順とかの関係で
2:19 AM
競合が起きるシナリオとかがあるかもしれない。
Avatar
let a = _stdlib_AtomicInt(42) print(a.load()) // 42 a.store(999) print(a.load()) // 999
Avatar
omochimetaru 7/21/2017 2:20 AM
少なくともレジスタで弄ってる間、メモリの値を他のスレッドからみたら、何の変化も起きてない、とかがあるし。
Avatar
C++ の std::atomic とか↑の _stdlib_AtomicInt とかも atomic であるところまでの保証であって「「Intの代入がatomic」だとしても」は同じじゃないの?
Avatar
omochimetaru 7/21/2017 2:24 AM
あー 違う意味で使ってた
2:24 AM
例えば
2:24 AM
var x = 3 x = 2
2:24 AM
こういうコードがあったとして
2:25 AM
func a() -> Int { var a = 3 a = 2 return a }
2:25 AM
上で「Intの代入がatomic」って言ったのは、「 Int に代入するとき、その操作がCPUにおいて不可分」
2:25 AM
って事ですけど
2:25 AM
func a の例で言うなら、これって
2:26 AM
func a() -> Int { return 2 } と最適化されるかもしれない
2:26 AM
あーこれだとスレッド間共有が不可能だから微妙だな
2:26 AM
func a(x: inout Int) -> Int { x = 3 x = 2 return x } (edited)
2:26 AM
これで。
2:27 AM
で、これが、1スレッドだけ考えれば func a(x: inout Int) -> Int { return 2 } (edited)
2:27 AM
に最適化される可能性があると思ってて
2:27 AM
その場合
2:27 AM
aが3になる時間や、2になる時間はなくなる。
2:27 AM
でも、 std::atomic<int> に対しては
Avatar
a はどこから来たの?
Avatar
omochimetaru 7/21/2017 2:27 AM
このような store 命令の削除も禁止されるはず。
Avatar
引数の xa の間違い??
Avatar
omochimetaru 7/21/2017 2:28 AM
間違えた
2:28 AM
@koher が最初から話してる「atomic」は
Avatar
もし xa だったら inout だから x への代入は必須じゃない?
Avatar
omochimetaru 7/21/2017 2:28 AM
「その操作がCPUにおいて不可分」のことを指してると思ってるので。
2:29 AM
あーじゃあ
2:29 AM
func a(x: inout Int) -> Int { x = 2 return 2 } (edited)
2:29 AM
こうですね。
2:29 AM
またまちがえた
2:29 AM
x = 3 の瞬間が削除されていることと
2:29 AM
return x じゃなくて return 2 になっていることがポイント
2:30 AM
マルチスレッドでみると、 x=3 が観測できないし、 どんだけ x に書き込んでも、 固定で 2 が返ってくる
2:31 AM
たとえば、別のスレッドで、「読み取った瞬間に3ならあたり、2ならハズレ」みたいなくじ引きロジックを実装していた場合
2:31 AM
x = 3 が削除されるのは問題になりうる。
Avatar
うーん・・・
2:31 AM
それは atomic でない a が atomic な挙動をしているだけだと思うんだけど、 (edited)
2:31 AM
それは問題ないんじゃないかな?
Avatar
omochimetaru 7/21/2017 2:33 AM
そうですかねえ
2:33 AM
この記事に出てくる
2:33 AM
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)
2:34 AM
みたいな例とかは
2:34 AM
わりとやっちゃう気がしますけど
2:35 AM
「代入がatomicだから」とかで自分で考えてスレッド同期しようとすると。
Avatar
↑は A と B が最適化で順序が入れ替わるかもしれないってこと?
Avatar
omochimetaru 7/21/2017 2:37 AM
実行順[A], [B]、実行順[B], [A]の両者とも同じ結果をもたらすため、実行順の入れ替えが生じうる。同様の観点で、コンパイラは[C]と[D]の実行順も入れ替え可能であると判断する。
2:37 AM
[C] と [D] が入れ替わるから、いきなりassertでコケて死ぬ
Avatar
言いたいのは、 func a() { lock.sync { atomicFoo(42) } } func b() { lock.sync { atomicFoo(999) } }lock はいらないよね?ということで
Avatar
omochimetaru 7/21/2017 2:38 AM
[a] と [b] が入れ替わることで、 [c] をすりぬけて [d]で死ぬってのもありますね
Avatar
↑の [A] と [B] はそもそも atomic じゃないからなぁ。
Avatar
omochimetaru 7/21/2017 2:40 AM
仮に @koher のいう、「代入がatomic」だったとしても 入れ替えの問題は起きるのでは (edited)
2:41 AM
つまり、 data を読んだ時に、0か42以外の中途半端にビットが書き換わった変な数字になったり、CPUがぶっ壊れたりしない、としても
2:42 AM
Int やアドレスの代入が atomic でないなら、結構気を付けてプログラム書かないといけないなぁ
2:42 AM
この発言のレベルだと、
2:42 AM
かりに、「Intへの代入がatomicだったとしても」
2:43 AM
↑の順序入れ替えとかに起因するバグを避けるのは難しいのではってことです
2:43 AM
func a() { lock.sync { atomicFoo(42) } } func b() { lock.sync { atomicFoo(999) } } これ自体はlockはいらない。
Avatar
はい、複数の命令で同期をとるのは当然として
2:45 AM
Int を同時に更新する(だけ)みたいなのでも同期が必要となると想定していないケースが多そうということです。
2:48 AM
つまり、↓の lock が不要だったらうれしい。 var x: Int = 42 func a() { lock.sync { x = 999 } } func b() { lock.sync { x = 888 } } (edited)
Avatar
omochimetaru 7/21/2017 2:50 AM
それは必要な気がする。文書上の根拠は無いけど、LLVMのオプティマイザを使うところで、C++並のアグレッシブな事がおきて、データ競合とみなされる可能性がありそう。
Avatar
うん、それが
Int やアドレスの代入が atomic でないなら、結構気を付けてプログラム書かないといけないなぁ
という気持ちです。
Avatar
omochimetaru 7/21/2017 2:51 AM
LLVMアーキテクチャだと、そういうデータ依存関係の解析はLLVM-IRの上で行われるけど、それをやるかどうかは、コンパイラフロントエンドを実装する時に選択的に適用できるので
2:51 AM
やる余地はあるけど、Swiftコンパイラが選択的に適用している/していない どちらもありえる。
2:52 AM
なるほど > 気持ち
Avatar
結局のところ Swift4 の Existential CoW はヒープに 25 バイト以上のデカい構造体を alloc/initialize/dealloc するより参照カウンタ操作の方が速いってだけなのかな?
Avatar
代入時に不要なコピーをしなくていいところが大きいんじゃないでしょうか?
Avatar
omochimetaru 7/21/2017 3:11 AM
alloc/initialize/dealloc
initializeがアロケートしたメモリにコピーを焼き込む操作なので
3:11 AM
同じことを言っていますね
3:11 AM
initialize が 不要なコピーのこと。
Avatar
Swift3 のときは、Existential のヒープストレージには参照カウンタついてなかったのだろうか?
Avatar
omochimetaru 7/21/2017 3:13 AM
僕が調べたときにはそれらしいことは無かったですよ
3:13 AM
Swift2かもしれないけど
3:13 AM
Existentialがコピーされるたびに、alloc/init されてた
3:13 AM
というか、24バイト以下の場合とほぼおなじで、それがその場のメモリか、用意したヒープか、みたいな。
3:14 AM
Existential自体がヒープ上に追加領域をもつ可変長データ構造、みたいなイメージです
Avatar
では Exsitential 自体のメモリ使用量は参照カウンタの分増えたってことなんですね。
Avatar
omochimetaru 7/21/2017 3:14 AM
そうですね。Existential1個で見ると増えると思います。
3:14 AM
1回でもコピーして共有が生成されれば、25バイト以上あるときのはなしだから、 (edited)
3:15 AM
25 - 8で17バイト以上得しそう
Avatar
大きい構造体をfunc間で取り回すときに、Exsitential に入れて取り回したほうが速い可能性を考えています。
Avatar
omochimetaru 7/21/2017 3:26 AM
あ〜そうか・・・
3:27 AM
いや!
3:27 AM
クロージャでキャプチャしている場合は
3:27 AM
そのクロージャがキャプチャするスコープのオブジェクトがヒープにできていて
3:29 AM
一緒にキャプチャしている同士ではただのヒープの共有だから
3:29 AM
あ、「func間で取り回すとき」って単に関数に引数として渡すとかも考慮しているんですかね。 (edited)
Avatar
引数として渡すならCOWの方がコピーが発生しなくて速いんじゃないですか?
Avatar
omochimetaru 7/21/2017 3:30 AM
let x = LargeSizeValue() f1(x) f2(x) f3(x)
3:30 AM
呼び出しのたびにコピーが生じるから、これがExistential渡しのほうが速いことがありそうだ
Avatar
あー、引数は必ず let だからそのまま渡せるのか
Avatar
omochimetaru 7/21/2017 3:31 AM
いや、スタック上にコピーすると思います
Avatar
コピーするのは Existential への参照?
Avatar
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)
Avatar
omochimetaru 7/21/2017 3:33 AM
コピーするのは Existential への参照?
BigStructが関数呼び出しのたびにスタックにコピーされると思う
3:34 AM
@rintaro そのコードならExistential化されてるとCOWが効いて早くなりそうに思います (edited)
Avatar
今プロトコル型で受けるときの話じゃないの?
Avatar
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 {} こうしたほうが速そう。
Avatar
omochimetaru 7/21/2017 3:34 AM
@koher はい、そうです、だから前提として遅いパターンを考えています
Avatar
COW があるとき( Swift 4 )とないとき (Swift 3 )での比較をしているわけではない?
Avatar
omochimetaru 7/21/2017 3:34 AM
@rintaro が言っているのは
3:34 AM
Swift3/4の比較じゃなくて
3:34 AM
Swift4において
3:35 AM
「あえて」Exitentialで渡されるトリッキーな書き方をすると
3:35 AM
動作速度で有利になるっていう変なことがおきるのでは、ってことだと思います
Avatar
結局のところ Swift4 の Existential CoW はヒープに 25 バイト以上のデカい構造体を alloc/initialize/dealloc するより参照カウンタ操作の方が速いってだけなのかな? は Swift 3 vs Swift 4 の話ではない??
Avatar
omochimetaru 7/21/2017 3:35 AM
それは3 vs 4の話ですね
Avatar
あれ?途中で話が変わってたのか
Avatar
omochimetaru 7/21/2017 3:36 AM
@rintaro でも、結局それって、最適化で BigStructに特殊化された版になってしまいそう。
Avatar
はい、話かわってます😅
Avatar
おお、なるほど、話が続いてると勘違いしてた・・・
Avatar
omochimetaru 7/21/2017 3:37 AM
(僕の中ではつながって聞こえてるけど・・・
Avatar
最適化で BigStructに特殊化された版
プロトコル型で受けてても specialize ってされるのかな?
Avatar
omochimetaru 7/21/2017 3:37 AM
されますよ
3:38 AM
ジェネリックじゃなくてプロトコル型で受けられるのは、associated typeが無い時だから
Avatar
↓でないとスペシャライズされないと思ってた。 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 {}
Avatar
omochimetaru 7/21/2017 3:40 AM
http://qiita.com/omochimetaru/items/b41e7699ea25a324aefa // 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()))

導入

Swiftでは通常のプロトコルは変数の型として使用することができますが、 型パラメータ(associated type)を持つジェネリックなプロトコルの変数は作れません。 非ジェネリックな例 ```swift prot...
3:40 AM
callHogeableHoge no
Avatar
↓のようになるってこと? func foo(_ a: P, _ b: P) { ... } extension Int: P {} extension String: P {} foo(2, 3) // スペシャライズされる foo(2, "abc") // スペシャライズされない
Avatar
omochimetaru 7/21/2017 3:40 AM
のときも特殊化された気がするけど自信なくなってきた
3:40 AM
それは両方されそう
3:40 AM
foo(Int, Int) と foo (Int, STring) が生成される
3:41 AM
すぐ試せるから試すか
3:44 AM
おや、されないな
Avatar
どっちも?
3:46 AM
1個の場合もやってみる
Avatar
ジェネリックの場合も試してみないといけないかも。
3:47 AM
ってか、 @_specialize 付けなくてもスペシャライズって起こるんだっけ?
3:47 AM
ああ
3:47 AM
同一モジュールなら
3:47 AM
いいのか。
3:48 AM
更新した
3:48 AM
@koher があってた
3:48 AM
ジェネリック関数の形式でかいたやつしか特殊化されなかった。 (edited)
Avatar
お、よかった。明日の発表を修正しなくて済んだw
Avatar
omochimetaru 7/21/2017 3:49 AM
@rintaro 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 {} こうしたほうが速そう。 ↑これでいけそうです
Avatar
逆にジェネリックにしてしまうとスペシャライズされて遅くなると・・・
3:50 AM
悲しい
Avatar
omochimetaru 7/21/2017 3:50 AM
これでなおさらOwnershipが待ち遠しくなるな
3:50 AM
shared渡しができるから
3:51 AM
Existentialテクニックより早くできる
3:51 AM
func consume1(_ b: shared BigStruct) { }
3:51 AM
これでC++の void consume1(const BigStruct & b) と同じ意味
Avatar
今でも↓が最速? 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)
3:52 AM
ああ P じゃない→修正 (edited)
Avatar
omochimetaru 7/21/2017 3:52 AM
あ、そうですね、それは速いです。
3:54 AM
でも、こういうことができない var x = BigStruct() compose(consume1(&x), consume1(&x))
3:54 AM
Low of Exclusivity のおかげで、同時に writable 参照 を 2つ作ってはいけない
3:55 AM
まあconsume1なら返り値が無いから↑のような例はありえないけど、仮に返り値があるとしたら、です。
Avatar
omochimetaru 7/21/2017 4:31 AM
Swiftの参照カウンタは 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.h
swift - The Swift Programming Language
swift - The Swift Programming Language
Avatar
⚠️ DO NOT MERGE ⚠️ This is the bare minimum to get the frontend to accept shared and owned. @guaranteed semantics and inout-to-borrowed conversions are coming next.
Avatar
omochimetaru 7/21/2017 4:58 AM
おお。 なんでアンスコついてるんだろう
Avatar
まだ evolution 通ってないからでしょうね。コメントで アンスコいらなくね?って言われてるけど。
Avatar
omochimetaru 7/21/2017 5:00 AM
非公式だよ〜みたいな気持ちが込められてるってことですか
5:00 AM
あーでもたしかに微妙にマージされて、その部分に興味ない人が、うっかり使ったりするとメンドイからそのほうがいい気もします
Avatar
ブランチ名が the-sharing-economy w
Avatar
omochimetaru 7/21/2017 5:02 AM
Avatar
CodaFi のブランチ名はいっつもこんなですw
Avatar
いつもw
5:07 AM
Gmail になってるけど Apple の人なの? Swift Static Analysis@Apple Cupertino, CA https://twitter.com/CodaFi_
Desktop developer. Programming language enthusiast. reenignE. 20. Aspiring Type Theorist. λΠω Lover. Math@CMU 2019. Swift Static Analysis@Apple
Tweets
9274
Followers
1432
5:08 AM
Math@CMU 2019 どういうこと?未来人??
Avatar
omochimetaru 7/21/2017 5:22 AM
2020年オリンピック出場予定とかそういうの?
Avatar
CMUってカーネギーメロン大学だと思うんだけど、2019年に数学科を卒業ってこと??学生でインターン?
Avatar
インターン2回目中だったような。去年もインターンやってた。
6:13 AM
けどもう apple.com のメールアドレスで活動しているから、中の人になっているのかも。
6:19 AM
https://swiftcoders.podbean.com/e/54-robert-widmman-swift-compiler-intern-swift-open-source-contributor/ 発見した。やっぱり今年もインターンみたいです。
Follow The SwiftCoder Journey at WWDC 2017 via Instagram. I'll be posting a lot of Stories: https://www.instagram.com/swiftcoders/ Come to The SwiftCoders Meet & Greet at AltConf 2017. Find all the details here: https://swiftcoders.eventfarm.com In thi...
👀 1
Avatar
インターンでSwiftコンパイラできるとかいい環境だなぁ。
Avatar
omochimetaru 7/31/2017 3:22 AM
@omochimetaru @mitsuse_t letでも参照型だったらイミュータビリティを保証できないし、値型だったらreadonlyとの区別はないし、readonlyとimmutableという話とは違うんじゃないかな?それよりも参照型でイミュータブルを保証する言語機能がほしいと思ってたけど、値型中心ならいいやってなった。
3:22 AM
@koher @tsumineko こっちで書くけど、 参照型であっても「同じインスタンスが毎回返る」事に意味はあると思う。
Avatar
たしかに?
3:26 AM
Kotlin だと val ( Swift の let に相当)で interface のプロパティ宣言して、具象クラス側で Computed property にできるよね・・・。
3:27 AM
やっぱり参照型は値を返すときに考えるべき概念が複雑過ぎる気がする。
3:28 AM
単純に値を返すだけでも
  • 毎回同じインスタンスを返す
  • シャローコピーを返す
  • ディープコピーを返す
に加えて、処理結果だと
  • 毎回処理を実行する
  • キャッシュを返す
となって、後者がミュータブルだと↑の 3 通りがあり得る。
Avatar
omochimetaru 7/31/2017 3:28 AM
はい。だからkotlinのinterfaceのvalは嫌い。
3:30 AM
@koher そこらへんはプロジェクトやモジュール単位での規約付けと、場合によってはnaming conventionを持ち込むしかないですよね
Avatar
本当はそういうのを言語機能で区別して適切に制限を加えたりできるべきだと思うけど、初心者がその違いを常に意識するのはハードルが高いし、初心者でなくても厳密に区別できてないことは多そう・・・。
3:32 AM
せめてイミュータブルな世界だけを分離できるように、 Swift 以前は↓みたいなのがいいんじゃないかと思ってた。 mutating を一つももたないクラスはイミュータブルクラスになる。 mutable class Foo { func bar() -> Bar {} mutating func baz() -> Baz {} } (edited)
3:32 AM
イミュータブルクラスに mutating を作ろうとするとコンパイルエラー。
3:33 AM
↑ができるとコンパイラや処理系がイミュータブルな範囲を認識できるようになって、遅延評価とかもできるようになる。
Avatar
omochimetaru 7/31/2017 3:33 AM
C++のconst仕様をデフォルト逆側でやるかんじかな
3:34 AM
Swiftのstrcut func のmutating みたいに、C++はメソッドに const をつけられて、constなメソッドの中からはconstなメソッドしか呼べないし、 const T な型にたいしてはconstはメソッドしか呼べないから、 constな範囲を連鎖的に保証する
Avatar
だから最初 Swift の mutating みたときは、これはもしかして?と思ったけどちょっと違った。けど、結局値型中心で考える方がセンスがいいと思う。
Avatar
omochimetaru 7/31/2017 3:35 AM
Swiftのmutatingは struct ツリーにおいて同じように働くけど class 周りはそういうのは無いですね
3:46 AM
これかな?
3:46 AM
pure funcの話
Avatar
omochimetaru 7/31/2017 3:48 AM
let フィールドだけなら 引数のない純粋関数として一般化できるのか。
Avatar
↑ D 言語のpure について言及されてて、 D 言語はよく知らないですが、、 pure な方がデフォルトであるのがいいと思うのと、これを型にも広げられないんだったら効果半減だと思います。
Avatar
omochimetaru 7/31/2017 3:49 AM
あ〜そうか〜・・・ もし let なフィールドを許すとなると
3:50 AM
じゃあ、 get / set できて getter/ setter のアクセサがついてない、stored propertyである制約が欲しい (edited)
3:50 AM
とかもでてきちゃって
3:50 AM
でもSwiftだと、 stored property が いつのまにか computed property にかわっていたとしても (edited)
3:50 AM
呼び出し側に影響を与えないっていうのがこれまでの実態で
3:51 AM
let フィールドに関しても同じで、 もともと let な stored property だったものを、後から computed property の getter に差し替えても 呼び出し側はそのままのコードでコンパイルできるわけだから
3:51 AM
protocol だけ、そこが変更に敏感な仕様が入るのは不自然な場面が出てきそう
3:55 AM
いや、let から var get になる分には緩める側だから問題ないかな・・・?
Avatar
うーん、 let なプロパティを Computed Property としてオーバーライドできないという制約はあるから、「もともと let な stored property だったものを、後から computed property の getter に差し替えても」動くとはいえ意図的に区別して制約が課されてるんじゃないかな?
Avatar
omochimetaru 7/31/2017 3:56 AM
書き換えじゃなくてオーバーライドで考えるとたしかに。
Avatar
Kotlin だと val ( Swift の let に相当)で interface のプロパティ宣言して、具象クラス側で Computed property にできるよね・・・。
なるほど Kotlin 書いたことないのですが, こういうのがかけてしまうんですね... (これは嬉しくなさそう...) 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) }
Avatar
omochimetaru 7/31/2017 5:18 AM
@tsumineko そうなんですよね
5:21 AM
@norio_nomura この話題っぽいですね
Avatar
norio_nomura 7/31/2017 5:22 AM
スレッドを読んだ限り、initializer内でどう扱うか?に問題があるぽい。
Avatar
protocol で nested type 作れないのって何か理由があるんですっけ?名前空間的に、その protocol でしか使わない型をネストしたい・・・。
Avatar
omochimetaru 8/9/2017 3:15 AM
protocolの内側に型を定義する話ですか?
Avatar
はい
Avatar
omochimetaru 8/9/2017 3:15 AM
それともstructの内側にprotocolを定義する話?
3:15 AM
明確な1次情報は見つかってないけど、以前話題に出て
3:15 AM
もしそれができると
Avatar
protocol Foo { var bar: Bar { get } struct Bar { ... } } みたいな (edited)
Avatar
omochimetaru 8/9/2017 3:15 AM
nested typeを持つことを型の制約として表明するようにも見えて
3:15 AM
微妙そう。
3:16 AM
たとえば protocol の内側に static func をかいたとき、それは、 Foo.hoge() と呼び出せるわけじゃなくて
3:16 AM
Fooを満たす型が static func hoge を持たねばならない、っていう "制約" なので
3:17 AM
Fooを満たす型が struct Bar を持たなきゃならない、みたいに見える
3:17 AM
構文としては存在しないんで決めの問題ですけど。
Avatar
実質的にはassociatedtypeと同じなのでは
3:18 AM
エイリアス貼るのか実装を持つのかの差はあれど、動きを見た時にそこまで大きく変わるようには思えない
Avatar
omochimetaru 8/9/2017 3:18 AM
@tarunon associated type は、絞込条件として protocol をさらに付与できるけど、 struct の形式だからどうだろうね
Avatar
structに限定したいという意図があるのか (edited)
Avatar
はい。 Foo に関連したいくつかのパラメータをまとめた Bar を作りたいけど、 BarFoo から独立したら意味を持たない型なのでネストしたいって感じです。
Avatar
外側にstruct Bar<F: Foo> を作るのが筋良さそう
Avatar
protocol Foo { typealias Bar = FooBar var a: Bar { get } } struct FooBar { } struct FooImpl: Foo { var a: Foo.Bar }
Avatar
うーん、それだと Foo の異なる具象型間で Bar をやりとりできないですよね?
Avatar
解決はしてない
Avatar
@t.ae それは少し考えたけど、 _FooBar にしておけばありかもしれないなぁ。
Avatar
omochimetaru 8/9/2017 3:22 AM
うーん、それだと Foo の異なる具象型間で Bar をやりとりできないですよね?
その型ってやっぱり普通に可視なんじゃないですかね
Avatar
Fooに型パラが特になければ、別にBar<F:Foo>じゃなくて、initにFooを渡すだけでも良いはず
Avatar
omochimetaru 8/9/2017 3:22 AM
プロトコル固有の型、とかではなくて、名前がつけられれないですか?
Avatar
ダメだった・・・ 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() ~~~~~~~^~
Avatar
作成ができないのか。
Avatar
omochimetaru 8/9/2017 3:23 AM
Fooが具象化してない状態だとBarはエイリアス名で実際の型が不定でおかしそう?デフォルトの扱いがよくわからないけど
Avatar
typealias はデフォルトではないのでは?
Avatar
omochimetaru 8/9/2017 3:24 AM
2. typealias Bar = FooBar
これ。
Avatar
associatedtype にしてデフォルト設定するんじゃないっけ?
Avatar
omochimetaru 8/9/2017 3:25 AM
はい、なんで、 返り値の型とかで エイリアスのところから普通は推論されるけど、 その推論させるためのメソッドが全く定義されない場合に、 = で指定しておいた型になるんじゃなかったっけ
Avatar
Xcode9b5なら普通に通りますよ
Avatar
struct FooBar {} protocol Foo { associatedtype Bar } extension Foo { typealias Bar = FooBar }
Avatar
associatedtypeは不定になるから無理
Avatar
↑と struct FooBar {} protocol Foo { typealias Bar = FooBar }
Avatar
omochimetaru 8/9/2017 3:27 AM
あ、 associated type じゃなくて
3:27 AM
ただのtypealiasか
Avatar
は別で、
3:27 AM
多分 @omochimetaru が言ってたのは前者な気がする。
Avatar
omochimetaru 8/9/2017 3:27 AM
そうですね、見間違えた
3:27 AM
じゃあFoo自体はassociated typeを持っているわけではないのか
3:28 AM
struct P0Param {} protocol P0 { typealias Param = P0Param var a: Param { get set } } var a = P0.Param() print(a)
3:28 AM
うごきますね
Avatar
Xcode9b5なら普通に通りますよ
は、↓ですか? 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()
Avatar
omochimetaru 8/9/2017 3:28 AM
Xcode9.0 beta5で動いた
Avatar
なるほど。
Avatar
omochimetaru 8/9/2017 3:28 AM
protocolの中にtypealiasが書けるのはなぜなんだ・・・
3:29 AM
実装上楽できるように?
3:29 AM
本来はtypealiasの右辺にはジェネリックな型とassociated typeを組み合わせた式が来たりするのかな。 (edited)
Avatar
確かによく意味がわからないな < typealias in protocol
Avatar
omochimetaru 8/9/2017 3:30 AM
まあ結果的に目的は果たせていますね・・・
3:30 AM
struct in struct な nested struct とかも
3:30 AM
同じ方式で
3:30 AM
top level に名前持って定義させつつ、 typealias つかってnested name を別途与えることができそう。
3:31 AM
そのほうがファイルがわけられていいな。
3:31 AM
あ、outer struct に対する可視性が違うのか
Avatar
struct in structはextensionに定義できるのでファイル分けるのはできますね
Avatar
omochimetaru 8/9/2017 3:33 AM
stored propertyが出せない
Avatar
norio_nomura 8/9/2017 7:27 AM
Xcode 9 beta 4まではswift-4.0-branch-07-11-2017 https://github.com/apple/swift/tree/swift-4.0-branch-07-11-2017 みたいなブランチからビルドされてたぽいだけど、beta 5はどこからビルドされているのだろう? (edited)
swift - The Swift Programming Language
Avatar
omochimetaru 8/9/2017 7:36 AM
そう言えば今回はxcode前の @norio_nomura の予告が無かったですね
Avatar
norio_nomura 8/9/2017 7:38 AM
お?予告?
Avatar
omochimetaru 8/9/2017 7:43 AM
@norio_nomura が、 swift-4.0-branch-07-11-2017 みたいなスナップショットが出ると、discordで報告していて、
7:43 AM
その3日後とかにxcode betaの新しいのが出るのがパターンになっていたので
7:43 AM
xcode beta5 は急に来た感じがありました
Avatar
norio_nomura 8/9/2017 7:53 AM
ああ、僕はXcodeリリースとは無関係に気になったスナップショットを書いてました。
Avatar
omochimetaru 8/9/2017 7:54 AM
無関係に書いてたけどたまたまそうなってたので、ってことです
Avatar
norio_nomura 8/9/2017 7:55 AM
とりあえず挙動を確認したところ、 swift-4.0-DEVELOPMENT-SNAPSHOT-2017-08-02-a以降 swift-4.0-DEVELOPMENT-SNAPSHOT-2017-08-04-aより前 ぽい。 (edited)
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
❣ 1
Avatar
enumも自動生成してくれるのか。通って欲しいな
Avatar
omochimetaru 8/10/2017 3:05 AM
お、いいですね〜
Avatar
↑レビュー期間終わったけどどうなったやろか
Avatar
Acceptedだ。やった。
😍 3
🙂 1
10:31 PM
async/awaitとactorだ
Avatar
This implements parsing and semantic analysis support for the async/await proposal that @jckarter and I are cooking. It doesn't include SILGen support yet, so it isn't ready for merging.
✨ 4
Avatar
Copy-On-Write (🐮) types like Array and String are sharable リファレンスカウントとCOWはスレッドセーフだけど Array そのものの操作はスレッドセーフではない?
1:02 AM
まだ出だしだけどこの Menifesto の英語すごく読みやすい。
Avatar
omochimetaru 8/18/2017 1:02 AM
おおお、熱いのが来ましたね
Avatar
"Error Handling Rationale and Proposal" とは違う・・・。
Avatar
omochimetaru 8/18/2017 1:02 AM
ラトナー、がっつりやってたのか
Avatar
例の async, await 出す前に来てしまった・・・。
Avatar
omochimetaru 8/18/2017 1:03 AM
機械学習にお熱なのかと😂
Avatar
↓わかりやすい。 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).
Avatar
現状の非同期機構は辛すぎるから多くの API が同期の形で提供されている、という話の例として UIImage(named:) が挙げられてるんだけど、このレベルの API から非同期化するつもりなのかな? C# の世界みたいになりそう。
Avatar
根っこのmain関数がasyncならまあ成り立つしな…と言う気はする
1:19 AM
でもそれならasync基本でsync修飾の方が良いのかな?
Avatar
それは同期で良いものまで非同期になっちゃうから、必要なときだけ async が良さそう。
1:19 AM
デフォルト throws って言ってるのと同じ気がする。
Avatar
たしかに
Avatar
can of worms って出てきてなんだ?と思ったら↓のような意味の表現らしい。
複雑で解決困難な問題、ゴチャゴチャした状態
http://eow.alc.co.jp/search?q=%22can+of+worms%22
(edited)
can of worms 《a ~》複雑で解決困難な問題、ゴチャゴチャした状態・This proje... - アルクがお届けする進化するオンライン英和・和英辞書データベース。一般的な単語や連語から、イディオム、専門用語、スラングまで幅広く収録。
Avatar
omochimetaru 8/18/2017 1:28 AM
can って缶のほうか
Avatar
多分
Avatar
omochimetaru 8/18/2017 1:29 AM
Avatar
「釣り餌用の虫の入ったカン」のことで、それを開けると、虫がぞろぞろと出てくるので、すぐに蓋を閉めないと厄介なことになる。
Avatar
omochimetaru 8/18/2017 1:30 AM
かん1 缶 a can a canister (お茶の葉などを入れる). 缶切り 《主に米国で用いられる》 a can opener 《主に英国で用いられる》 a tin opener. 缶ビール canned beer a can of beer (1 個).
1:30 AM
缶って日本語だっけ英語だっけと思ったけどあった
Avatar
オランダ語由来っぽい
1:31 AM
じゃあカステラとかと同じ時期かな?
Avatar
「缶」と「できる」の他の "can" があるのかどうかを知らないから、おそらく "can of worms" の "can" は「缶」だけど自身はない。
1:32 AM
缶の漢字は当て字?
1:32 AM
↑ can of wormsの画像検索
Avatar
デジタル大辞泉 - 缶/罐/鑵の用語解説 - 《〈英〉canまたは〈オランダ〉kanから。「缶」「罐」「鑵」は当て字》1 金属の薄い板で作った容器。特に、ブリキ製のものをいう。「石油―」2 「缶詰」の略。「鮭(さけ)―」
Avatar
omochimetaru 8/18/2017 1:33 AM
オランダんだ
Avatar
日本古来のものは「ほとぎ」と言って
1:33 AM
同様の目的のものがあって漢字はそこから転用したのかな
Avatar
omochimetaru 8/18/2017 1:34 AM
やっとasyncのサンプルコードが出てきた
1:34 AM
(上から読んでるナウ
Avatar
まだそこまで行ってない。速いね。
Avatar
あんまり低レベルなAPIをasyncにされると、それを使うものは基本みんなasyncにする必要が出てきて困った世界になりそうなんですが。<C#の世界をちら見しながら
Avatar
omochimetaru 8/18/2017 1:38 AM
can of wormsとか無視してるんでw
😂 1
Avatar
try!よろしくawait!みたいなものがあれば、そこまで困らない気はしていて
1:39 AM
時間のかかるAPIがそれと解って取り回しが聞いて、同期化も楽ならそれはそれで良さそう
Avatar
そういう世界に振ってしまうのなら、基本がasyncでasyncの記述はいらなくて、awaitの記述も不要で代わりにnowait(asyncでも待たない)がある世界でもいいのかなと思ってしまう
Avatar
基本非同期で成り立つ世界はそれはそれでアリだとは思うンですよね
1:42 AM
まあ別言語でやった方が平和だとは思う
Avatar
それはそうですね。Swiftでやってほしくはないかも。
Avatar
UIImage(named:) にまで踏み込むなら、 pure Swift UI ライブラリもワンチャンあるかも?
Avatar
↓の🐟は何?🐮=COWはわかったけど。 you should only have to teach your types how to serialize/🐟 themselves
Avatar
omochimetaru 8/18/2017 1:53 AM
それ謎だった
1:53 AM
serialize/X だし deserializeかなあ?
🤔 1
1:54 AM
A fish emoji, swimming in a non-tropical climate. Fish was approved as part of Unicode 6.0 in 2010 …
1:55 AM
絵文字としては fish なんだよなあ
Avatar
お、 Unrecoverable なエラーからの回復の話をしてる。 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.
Avatar
やっと async / await まで来た。
Avatar
omochimetaru 8/18/2017 2:15 AM
なんかそこ記述量がすごいすくなくて
2:15 AM
throwsみたいな async と、呼び出しの await は
2:15 AM
提示されてるけど
Avatar
omochimetaru 8/18/2017 2:16 AM
それ以上の話は書いてない、もっと下の方に出てくるかもしれないけど Actor についての議論が長い。
Avatar
(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.
2:16 AM
reasync がなさそうだから swift-evolution に書いておくか。
2:16 AM
await! もほしいな。
2:17 AM
でも ! を使うのが良いのか自信がない。
Avatar
議論の種になればそれで良いのでは
Avatar
omochimetaru 8/18/2017 2:21 AM
ああ
2:22 AM
async/awaitの詳細は、この、プロポーザル下書きのほうにかいてあるわ。
2:22 AM
NOTE: This section is concrete enough to have a fully baked proposal.
2:22 AM
1行目に書いてあった。
2:23 AM
Part1がasync/await、Part2がactor 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)) } }
2:23 AM
Part3はなんかアクターとエラーについての話、reliability reliable actor Notifier { ... } reliable actor class Notifier { ... }
2:26 AM
Part4がネットワーク越しのactorとかの話 distributed actor MyDistributedCache { ... } distributed actor class MyDistributedCache { ... }
Avatar
omochimetaru 8/18/2017 2:39 AM
async/awaitのためにcoroutineの概念を導入して、generatorとかも整理しようって話の流れKotlinで見たな。
Avatar
Kotlin が残念なのは typed & marked propagation がないからせっかく非同期整えたのに、エラー処理がザルなんだよなぁ。 (edited)
Avatar
omochimetaru 8/18/2017 2:59 AM
func queueHopping() async -> Void { doSomeStuff() await DispatchQueue.main.syncCoroutine() doSomeStuffOnMainThread() await backgroundQueue.asyncCoroutine() doSomeStuffInBackground() }
Avatar
/// 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 じゃないの?
Avatar
omochimetaru 8/18/2017 2:59 AM
おもしろい。 doSomeStuffOnMainThread() は メインスレで同期的に実行されて
3:00 AM
doSomeStuffInBackground() はBGスレ
3:00 AM
@koher それは、同期コンテキストから、非同期コンテキストを開始して、投げっぱなしにするやつです
3:00 AM
@IBAction func buttonDidClick(sender:AnyObject) { // 1 beginAsync { // 2 let image = await processImage() imageView.image = image } // 3 }
Avatar
投げっぱなしだとこの rethrows はどこで活躍するの?
Avatar
omochimetaru 8/18/2017 3:01 AM
一緒に書いてるコメントにかいてあるけど
3:01 AM
beginAsyncで投げた処理が
3:02 AM
最初のawaitに到達するまえに
3:02 AM
例外を投げたときです
3:02 AM
beginAsyncの呼び出し時点で並列化するんじゃなくて
3:02 AM
beginASyncの出だしはbeginAsyncのcallerと同じスレッドで実行されて
3:02 AM
beginAsyncの中でawaitとともにasyncな関数を呼ぶところで
3:03 AM
beginAsyncがreturnするってかいてある
Avatar
ああ、ちゃんと読んでなかった。 (edited)
3:04 AM
確かに書いてあった・・・ If the async process completes by throwing an error before suspending itself, `beginAsync` rethrows the error.
Avatar
omochimetaru 8/18/2017 3:06 AM
そうですね。ちょうどIBActionの例なのも一緒。
Avatar
なんで suspendAsyncfunc suspendAsync<T>( _ body: (_ continuation: @escaping (T) throws -> ()) -> () ) async rethrows -> T じゃないんだ??
3:11 AM
そしたら二ついらなくない?
Avatar
omochimetaru 8/18/2017 3:12 AM
ん?違いますよ
3:12 AM
continuationは
3:12 AM
bodyの引数なんで
3:13 AM
suspendAsync自体の返り値をどうするかを決めるやつだから
3:13 AM
continuationを呼び出すことが、suspendAsyncの返り値のTを送信する処理です
3:13 AM
suspendAsync自体が失敗することを示すためには
3:13 AM
そのためのerror-continuationが必要
3:13 AM
↑のようなシグネチャの場合、「エラーだったよ」を送信できないです
3:14 AM
むしろ、送信しようとするとエラーが返ってくる可能性があるっていう
3:14 AM
よくわからないことになってる
Avatar
ああ、 throws の位置がおかしいか
Avatar
omochimetaru 8/18/2017 3:14 AM
continuationの実体を実装するのはユーザーじゃないです。
3:14 AM
ユーザーはconitnuationを呼び出すだけ。
Avatar
func suspendAsync<T>( _ body: (_ continuation: @escaping (T) -> ()) throws -> () ) async rethrows -> T
Avatar
omochimetaru 8/18/2017 3:15 AM
それでもやっぱりだめで
3:15 AM
bodyの中で非同期処理を発火したいから
3:15 AM
body自体のthrowsで表していても
3:15 AM
非同期処理が失敗するかどうかbodyでは待てない
3:15 AM
あれです、これ、HTML5/JSのPromiseのコンストラクタと同じ。 (edited)
Avatar
うん、それはわかってるんだけど
Avatar
omochimetaru 8/18/2017 3:16 AM
// Legacy callback-based API func getStuff(completion: (Stuff) -> Void) { ... } // Swift wrapper func getStuff() async -> Stuff { return await suspendAsync { continuation in getStuff(completion: continuation) } }
3:16 AM
↑この例がわかりやすい
Avatar
asynchronize が間違ってるっぽいな。
Avatar
omochimetaru 8/18/2017 3:16 AM
既存のコールバックベースのAPIを、suspendAsyncを使って、async/await化する例。
3:17 AM
async化してるわけじゃないな・・・
3:17 AM
asyncコンテキストの中から、既存のコールバックベースを呼び出す例でした。
3:17 AM
まあ、その、呼び出す瞬間に、ローカルにasync/await化しているとも言える。 (edited)
Avatar
まあ名前は良くてやりたいことは同じそう。
Avatar
omochimetaru 8/18/2017 3:19 AM
いや、 @koher のasynchronize は間違ってないと思う
3:19 AM
クロージャーのネスト数が違ってて
3:20 AM
あ、ちがうな
3:20 AM
まって、カッコが多すぎて見えない
Avatar
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)
Avatar
omochimetaru 8/18/2017 3:21 AM
なんかへんですね、 (T) throws -> () があるけど、
3:21 AM
() throws -> T じゃないと。
Avatar
throws は間違えてるね。
Avatar
omochimetaru 8/18/2017 3:22 AM
その上でもういっこ包めば正しくなるかな?
Avatar
かも
3:25 AM
↓ならいけるか? func asynchronize(_ operation: ((() throws -> T) -> ()) -> ()) async rethrows -> T
Avatar
omochimetaru 8/18/2017 3:25 AM
直感だけどそうw
3:25 AM
T | error を送信する代わりに、 () throws -> Tを送信する
Avatar
だから、↓か。 func suspendAsync<T>( _ body: (_ continuation: @escaping (() throws -> T) -> ()) -> ()) async -> T
Avatar
omochimetaru 8/18/2017 3:25 AM
Promiseモナドのclosureへのかきかえですね
3:26 AM
ですね
3:26 AM
でも個人的にはやっぱりクロージャーにしちゃうと型としては少しゆるくなってるんで
3:27 AM
成功とエラーでそれぞれコールバックがある形がマシに思う
3:27 AM
あと今あらためておもったけどネストカッコが多いと読みづらい。
Avatar
return 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 } } }) } になる。
Avatar
omochimetaru 8/18/2017 3:28 AM
ですね。
3:28 AM
あれ?てかそこbreakいらんのか
3:28 AM
関係ない話だけど。
Avatar
break は空のとき以外いらないはず。
3:29 AM
Python の pass みたい。
Avatar
omochimetaru 8/18/2017 3:29 AM
え!!!!!!!
3:29 AM
あ〜〜〜〜〜〜^
3:29 AM
書き始めると怒られるから最初にbreak書くから
3:29 AM
全く気がついてなかったw
Avatar
まじすかw
Avatar
omochimetaru 8/18/2017 3:29 AM
www
3:29 AM
case書く、xcode赤くなる、break書く、本文書く
3:29 AM
って誘導されてた
Avatar
omochimetaru 8/18/2017 3:53 AM
async await じゃなくて yieldsyield にするって選択肢についても書かれてますね
3:53 AM
非同期のための別スレへの投入とかはこの言語機能の外の話で、ものとしてはcoroutineにすぎないから、と。
Avatar
async / await は必ずしも意味が正しくないんよね。
3:54 AM
asynchronous とは限らないし。
Avatar
omochimetaru 8/18/2017 3:55 AM
async, throwsの直交をやめて、asyncならthrowsであることにするとシンプルだよねって話もでてきた
Avatar
うん、でもそれは微妙だと思う。
3:55 AM
すでに失敗しない前提の非同期 API とかあるし。
Avatar
omochimetaru 8/18/2017 3:55 AM
そう書かれてましたw
Avatar
なるほどw
Avatar
omochimetaru 8/18/2017 3:56 AM
Make async default to throws
3:56 AM
あ、これはおもしろいな
3:56 AM
asyncならthrowsが暗黙で、 一方で、 async(nonthrowing) を導入する
Avatar
あー、それは考えなかったな。
3:56 AM
確かにそれはあり得るな。
Avatar
omochimetaru 8/18/2017 3:57 AM
but in the opinion of the proposal authors, this is probably the right set of tradeoffs.
3:57 AM
ラトナ推し
Avatar
async(nonthrowing) より async nonthrows とかの方がいいな。 nonthrows は英語的におかしそうだけど。
Avatar
omochimetaru 8/18/2017 3:58 AM
C++は nothorw があるよ
Avatar
throws がよくなかった気がするな。 Java のせいだけど。
3:58 AM
throwing func とか async func とかの方が英語的によかったかも。 (edited)
3:58 AM
nonthrowing func だったら nonmutating func とかとも整合するし。
Avatar
omochimetaru 8/18/2017 4:00 AM
rethrows could be generalized to support potentially async operations
4:01 AM
It would be possible to define a similar mechanism to allow abstraction over async operations as well.
4:01 AM
reasyncかいてあった
Avatar
↓相当のものもほしいよね? do { let a = await foo() let b = await bar(a) ... } wait
4:01 AM
おお < reasync
Avatar
omochimetaru 8/18/2017 4:02 AM
うーん・・・
Avatar
同期化のための簡単な手段は必要だと思う。
4:02 AM
await! もいいけど、まとめてブロックも必要かと。
Avatar
omochimetaru 8/18/2017 4:03 AM
それって、ランタイムの仕様規定なしで実現できないですよね?
4:03 AM
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.
4:03 AM
↑proposalとして触れてはいますね
Avatar
なるほど。
Avatar
omochimetaru 8/18/2017 4:03 AM
この提案自体は、並列実行メカニズム自体からは分離して
4:04 AM
coroutineだけで議論できる範囲にとどめていて
4:04 AM
Potential Future Directions
の章でblockingについて書いてあった。
Avatar
let a = await foo() let b = await bar() のときに foobar を並列に走らせるのか直列に走らせるのかはどうだろう?
Avatar
omochimetaru 8/18/2017 4:05 AM
あ、それ自体は Futureとして出てきますよ
4:05 AM
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 }
4:05 AM
Futureのコンストラクタで beginAsync していて
4:06 AM
get() async throws -> T なので
4:06 AM
dataResourceとimageResourceの取得は並列に起動して
Avatar
じゃあトピックは網羅されてそうだ。
Avatar
omochimetaru 8/18/2017 4:06 AM
decodeImageの呼び出しのところで両方を待つ。
4:07 AM
Futureはproposalの中のただの話題なのか、std導入の話なのかは読み飛ばした
Avatar
ほぼ思い描いていた通りのもので満足だ。
Avatar
omochimetaru 8/18/2017 4:08 AM
同じく
4:09 AM
もともとの非同期manifesto側では、actorモデル導入の段階でランタイムの話が出てきて、既存のGCDにうまく乗っかれると思う、みたいなことが書いてあった。
Avatar
async/awai に続いて Typed throws も。
Typed throws is something we need to settle one way or the other, and I agree it would be nice to do that in the Swift 5 cycle.
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170814/038928.html
Avatar
omochimetaru 8/18/2017 6:50 AM
マジか
Avatar
ただ、こっちはどういう方向になるか未知数。
6:50 AM
↑に、 Error が existential だからパフォーマンスが、ってことが書かれていて興味深い。
Avatar
omochimetaru 8/18/2017 6:51 AM
パフォーマンスが、なんですか?
Avatar
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.
Avatar
omochimetaru 8/18/2017 6:53 AM
existentialにラップするためのヒープ確保がある限り、時間保証したいような場面で今のままじゃ全く使えん?
6:53 AM
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.
6:54 AM
それを解決するアイデアってなんだ・・・?TypedThrowsになれば型のサイズが固定されるから解決するという話とは別で、Errorに対してやりようがあるってことかな
Avatar
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 が返信してるから、それ見たらわかるかも。
Avatar
omochimetaru 8/18/2017 6:55 AM
なるほど
Avatar
@omochimetaru と Error Handling Rational and Proposal の英語は難しかった話をしたけど、今見てもやっぱり難しい。↓ Universal error についての一節。 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.
Avatar
↓モナド? 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-operations
Concrete proposal for async semantics in Swift
Avatar
omochimetaru 8/18/2017 7:37 AM
throws and async as effects on function types,
7:37 AM
effects ってのが専門用語を匂わせてる気がする
7:38 AM
eff言語では effect としてモナド変換を一級に扱える http://www.eff-lang.org
Avatar
うん、本質的には同じものだと思う。
Avatar
omochimetaru 8/18/2017 7:38 AM
あとハスケルにもEffectsって言葉があって、同じような領域の概念っぽいけどよくしらない http://konn-san.com/prog/haskell/extensible-effects.html
👀 1
Avatar
http://nineties.github.io/category-seminar/13.html#/55 この辺わかりやすいです。effect = 計算作用のことかと
Avatar
omochimetaru 8/18/2017 7:41 AM
おお、ありがとうございます
7:42 AM
2013年 圏論勉強会 資料
7:42 AM
良さそう
Avatar
スライドがめくれない・・・
Avatar
カーソル左右
Avatar
おお、ずっとマウスで操作してた。ありがとう。
7:49 AM
本当に圏論の話だった・・・ これは最初から丁寧に追わないとわからなさそうだ。
Avatar
omochimetaru 8/18/2017 9:08 AM
エラーのアロケーション回避は、Tagged Pointerにしたらいいよってやつだった。
9:08 AM
ポインタに直接整数いれたりするやつ。
Avatar
これまで await try と書いてたけど、プロポーザル通り try await じゃないといけない気がしてきた。
12:28 AM
tryawaitflatMap と等価でモナドを剥がすわけだけど、 async throwsPromise が外側だからまず Promise を剥がさないといけず、その後 Result を剥がすと考えると try await じゃないとおかしい。
Avatar
beginAsyncrethrowsbodythrows ってやっぱダメじゃない?
4:06 AM
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) -> Void
Avatar
bodyのsuspend後に発生するthrowについては、beginAsyncのrethrowsとは関係ないですね
10:52 AM
/// If the async process completes by /// throwing an error before suspending itself, beginAsync rethrows the error.
10:53 AM
beginAsyncのドキュメントには、suspend後の再開後についてのエラーがどうなるか書いてないですね
10:55 AM
今の状態は、 suspend前のthrowをrethrowsして、suspend後については書いてない @koher の案は、 suspend後も前もthrow禁止にして、ユーザ側の昇格に任せる
Avatar
うん、それがまずい気がする。別に再開後のエラーで universal error 化したければ明示的に catch して fataError 呼べばいいだけだし、 await 前については beginAsync のクロージャの外に出せるはず。せっかく型安全な typed propagation を選択したのに、型チェックが働かなくなってる。
Avatar
await 前については beginAsync のクロージャの外に出せるはず。
あ~そっか、それはたしかに。
Avatar
だから beginAsync のbody に throws を許してうれしい理由がない気がする。
Avatar
await! についても違う方向で話されてたから blocking のことに言及してみた。 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170814/039096.html
Avatar
throwsと対称性のある形になってくると嬉しいですね、do構文の取り回しとしても
🙂 1
Avatar
async(nonthrowing) おもしろいけど、それをやっちゃうと throws, async に続く第三のエフェクトを導入したときに整合性をとるのに困ると思う。
Avatar
omochimetaru 8/22/2017 8:11 AM
たしかに。
Avatar
昔の SwiftJP Slack のログをサルベージしてみたんだけど、 2016-03-28 時点で今の Chris Lattner の async/await の Proposal と同じような内容が話されてる。 https://gist.github.com/koher/5cd16adac7a62b6d3eb0b910ccc13534
1:24 AM
出て来るメンバーが今と変わってないw
Avatar
omochimetaru 8/23/2017 1:28 AM
Swift3の間は細かい事しか変わってないから知見のレベルに変化が無い・・・
Avatar
import 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)
Avatar
@_specialize ってそのメソッドや関数の型パラメータに利くんじゃないっけ?
2:06 AM
メソッドをジェネリックな private func 化して
2:06 AM
それに @_specialize 付けるとか?
2:06 AM
ダメか
Avatar
omochimetaru 8/23/2017 2:06 AM
protocol ArrayClippable を用意して
Avatar
自分自身の型パラには効かないんでしたっけ?
2:06 AM
ちょっと試してみます
Avatar
呼び出し元で existential になってる?
Avatar
omochimetaru 8/23/2017 2:06 AM
Arrayのメソッドはそれを呼ぶだけにするとかでできないかな
2:08 AM
あとで読もう・・・。
Avatar
omochimetaru 8/23/2017 2:10 AM
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) } }
Avatar
conditional conformanceが必要な気がしますがどうですかね?
Avatar
omochimetaru 8/23/2017 2:12 AM
extension Comparable : ArrayClippable { static func clipArray(_ array: inout Array<Self>, min: Self, max: Self) { // ... } }
Avatar
@t.ae どうやってスペシャライズされてないことを確認したの?
Avatar
omochimetaru 8/23/2017 2:12 AM
@koher printでは?
Avatar
呼び出ししか見てないです
Avatar
omochimetaru 8/23/2017 2:12 AM
print("accelerate version")
2:13 AM
@t.ae ↑の Comaprable : ArrayClippable も置いとけばいけるきがするけど駄目かな
Avatar
のでspecializeされてないのか、specializeされてるけど言語機能的に呼び出しがやってほしいほうに向かないのかは不明です
Avatar
omochimetaru 8/23/2017 2:13 AM
vDSP_vclipが呼ばれるときは printが走るからわかるんじゃ?
Avatar
あーArrayClippableってエレメントのほうにつけるやつなんですね
Avatar
omochimetaru 8/23/2017 2:13 AM
そうそう。
Avatar
あー、そういうことか。色々勘違いしてた。
2:14 AM
@_specialize で呼び分けるのは無理なんじゃないかな?
Avatar
Playground execution failed: error: MyPlayground.playground:10:1: error: extension of protocol 'Comparable' cannot have an inheritance clause extension Comparable: ArrayClippable { ^ ~~~~~~~~~~~~~~ つけられない?
Avatar
omochimetaru 8/23/2017 2:21 AM
あ、ほんとだ
Avatar
これってなんの制限なんですっけ
Avatar
omochimetaru 8/23/2017 2:22 AM
プロトコルにはプロトコルを後付できない?
Avatar
できないね。 < 後付 (edited)
Avatar
omochimetaru 8/23/2017 2:22 AM
じゃあComparable向けに実装が必要になっちゃうなあ
Avatar
extensionで追加ができないだけなのか。
Avatar
ところでSwift4でspecializeの文法変わるんですね。 https://github.com/apple/swift/blob/master/docs/Generics.rst#specialization
swift - The Swift Programming Language
2:32 AM
ドキュメント読んで書いて実行できなくて気づいたんですが
2:34 AM
ん?exportedとかいうのが追加されててそれが関係ある気が
Avatar
omochimetaru 8/23/2017 2:34 AM
If 'exported' is set, the corresponding specialization would have a public visibility and can be used by clients. If 'exported' is omitted, it's value is assumed to be 'false'.
2:34 AM
外から呼べるみたいだね
Avatar
実質多重実装をしてくれることになるのかな?
Avatar
@t.ae @_specialize について、 _ で始まるものは本当に使わないほうがいいです。意図的にやっているのかっていうくらい頻繁に仕様が変わります。 by @rintaro
Avatar
omochimetaru 8/23/2017 2:36 AM
struct 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) } }
2:36 AM
多分外から見ると
Avatar
まあでも Swift では _ に限らず破壊的変更がどのみち入るから(😭 )ついでに直せばいいだけな気も。 (edited)
Avatar
不安定感を込めて_付きなんでしょうかね
2:37 AM
@koher 機能自体が無くなるとかがなければそうですね (edited)
Avatar
omochimetaru 8/23/2017 2:38 AM
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) } }
2:38 AM
こうみえるんじゃないかな
Avatar
betaでexported試してみたけど変わらず。。。
Avatar
omochimetaru 8/23/2017 2:39 AM
今のケースはそもそも
2:39 AM
特殊化の話とは関係ないと思うよ
Avatar
@t.ae 機能がなくなっても最悪 @_specialize をなくせば動きはするしね。
Avatar
omochimetaru 8/23/2017 2:40 AM
このspecializeは
2:40 AM
どのwhereが該当するか決まった上で
2:41 AM
substituteされた実際のconcrete typeのバージョンがオーバーロードとして生成される話だから (edited)
2:41 AM
where Element : Comparable のセクションをコンパイルしている時点では
2:41 AM
Element == Float へのディスパッチは考慮されないと思う
2:42 AM
specialize過程での改めてのwhere選択はされないんじゃないかなあ
Avatar
うん。なので当初の問題を解決するのは @_specialize では無理だと思う。
Avatar
omochimetaru 8/23/2017 2:42 AM
specializeはあくまで最適化過程の話であって、
Avatar
そこのディスパッチを考慮してくれるんじゃないかなと思ってたんですよね。 specializeは単純にオーバーロードを自前実装するのと同じだという認識でした。
Avatar
omochimetaru 8/23/2017 2:43 AM
それが無かった場合と同じ結果にならないといけない
2:43 AM
と考えると
2:43 AM
where Element : Comparable の時点で、本当はFloatであるっていう意味情報は
2:43 AM
Swiftレベルでは失われるから。
2:44 AM
最適化してはじめてわかる「今はFloat」ってことに基づいて動作が変わっちゃうと
Avatar
それが無かった場合と同じ結果にならないといけない
これは納得。
Avatar
omochimetaru 8/23/2017 2:44 AM
最適化によって結果が変わる(今回ならprint副作用が生じる)
2:44 AM
ことになるからそれはやらなそう。
Avatar
なるほど。ありがとうございます。
Avatar
https://github.com/t-ae/SeveralPerformanceChecks/blob/master/Tests/SeveralPerformanceChecksTests/ManagedBufferArrayTests.swift#L18-L38 同一の実装のMyArrayMyArray2なんですが、同じテストコードでモジュール外にあるMyArrayの方が数百倍遅くて原因が分かりません。 モジュールまたぐ時ってwhole module optimization以外何かありましたっけ?
Contribute to SeveralPerformanceChecks development by creating an account on GitHub.
Avatar
specialization が効かないです。
Avatar
ジェネリクスのですよね? それだけでここまで変わるかなあと思うんですが
8:29 AM
非ジェネリックなのを書いてみればいいか。
Avatar
omochimetaru 8/25/2017 8:29 AM
ジェネリックなコードは遅いゾイ
8:29 AM
time profiling してみたら?
8:29 AM
xcodeのやつ
Avatar
spmでつくってるとそれを実行するまでが面倒くさいんですよねぇ
Avatar
omochimetaru 8/25/2017 8:31 AM
generate-xcodeprojでmac向けならうまくいかん?
Avatar
command line toolのスキーム追加するのが一番簡単そうですかね
Avatar
omochimetaru 8/25/2017 8:32 AM
勝手にできないのか・・・
Avatar
確かに非ジェネリックと比べると300倍以上遅いっぽい……
8:38 AM
MyArrayみたいなのは作らないのが良いのかなぁ
Avatar
omochimetaru 8/25/2017 8:38 AM
MyArray何?
Avatar
ManagedBufferを使って作った初期化しないイニシャライザ持ちのstructです
Avatar
omochimetaru 8/25/2017 8:40 AM
遅かったのは度のテスト?
8:40 AM
あー
8:40 AM
MyArray2はテストコードに書いてあるのか。
Avatar
はい。
Avatar
omochimetaru 8/25/2017 8:41 AM
これって
8:41 AM
filterは
8:42 AM
extension Collectionから来てる?
Avatar
はい。
8:42 AM
というかmakeIteratorからですね
Avatar
omochimetaru 8/25/2017 8:42 AM
えーっと、自作したのは
8:43 AM
startIndex, indexofafter, subscriptだよね
Avatar
です。それだけあればmakeIteratorCollectionに生えているのが使えるので
Avatar
omochimetaru 8/25/2017 8:44 AM
非ジェネリックと比べると
これは
8:44 AM
テストとは別のモジュールでも
8:44 AM
型パラ取らないやつにしたら早かったってこと?
Avatar
そうです。
8:44 AM
MyArrayとおなじところにMyFloatArrayを作ってためしました
Avatar
omochimetaru 8/25/2017 8:45 AM
あーなるほど・・・・
8:45 AM
subscript使って要素を読み書きするところで
8:45 AM
毎回boxingされてそうだね
Avatar
ですねぇ
Avatar
omochimetaru 8/25/2017 8:46 AM
たぶんsilみると
8:46 AM
alloc_box とか
8:46 AM
めっちゃ出てくるんじゃないかな
8:47 AM
せっかくManagerBufferでストレージは生のレイアウトなのに
8:47 AM
subscript が getter / setter だから
8:47 AM
遅くなっちゃうってのもありそうだな
Avatar
自前Iterator用意したら少しは早くなるかな
Avatar
omochimetaru 8/25/2017 8:48 AM
いや、変わらんと思う
Avatar
あ、subscriptじゃなくて直接メモリ見に行くIteratorですよ
Avatar
omochimetaru 8/25/2017 8:49 AM
SwiftのIteratorじゃなくてってこと?
Avatar
IteratorProtocolに従う別のIterator
Avatar
omochimetaru 8/25/2017 8:50 AM
いまいちわからんけど UnsafeMutablePointer<T>.pointee を介した読み書きなら早いと思う
8:51 AM
IteartorProtocolに従う限り
8:51 AM
Collectionのfilterが
8:51 AM
結果をコンストラクトして
8:51 AM
つめるところで
8:51 AM
subscriptへのgetter/setterが走りまくって
8:51 AM
そこのboxingで重くなると思う。
Avatar
やってみましたけど遅いままですねぇ
8:56 AM
素直にArrayに詰めたいけれど型が不定だと初期値をどうするのやら
Avatar
omochimetaru 8/25/2017 8:56 AM
あれ?っていうか
8:56 AM
現状のコードはあってるの?
8:56 AM
uninitializedなメモリに対して
8:57 AM
assignされちゃうのでは
8:58 AM
a-
8:59 AM
countで確保するとこに問題あるのか。
Avatar
omochimetaru 8/25/2017 9:00 AM
あーこうなってんのか
9:00 AM
init(count: Int) でコンストラクトしたとき
9:00 AM
メモリがuninitializedになっていて
9:00 AM
その状態でsubscript setとかすると
9:00 AM
バグだね
9:00 AM
未定義動作しうる。
Avatar
@t.ae ちなみにこの airspeedswift さんは今 Apple の Swift Core Team になったよ。
Avatar
何かのPRで見ましたね。
Avatar
omochimetaru 8/25/2017 9:06 AM
ジェネリックなArrayが高速に実現できないの微妙だなあ
9:06 AM
それこそ、魔法の specialize 指定したら
9:06 AM
どうなん
Avatar
specializeをどこにつければいいのやら
Avatar
全メソッドに Float に対して付けるんじゃないの?
Avatar
getの前につければいいのか
Avatar
SwiftPM だったらソースあるんだからスペシャライズしてくれたらいいのに・・・
Avatar
spm外から使う時のことを考えると早期に遅い部分が見つかるとも言える
Avatar
omochimetaru 8/25/2017 9:10 AM
ArrayとArrayBufferみたけどよくわからんな
9:10 AM
@_semantics("array.init")
Avatar
そのへん入り組んでて何がどうなってんのかわからないんですよね
Avatar
omochimetaru 8/25/2017 9:10 AM
めっちゃ専用の最適化マークみたいなのついとるし。
9:11 AM
これってfilterの結果を構築する部分はどれを使ってるんだろう
Avatar
とりあえずspecialize付けるくらいだと早くならなそうでした
Avatar
omochimetaru 8/25/2017 9:11 AM
init(repeatedValue) で初期化した後に、subscriptで0から埋めてるのかな
Avatar
arrayでreserveCapacityかと
Avatar
omochimetaru 8/25/2017 9:11 AM
reserveCapacity実装してある?
Avatar
中身見てないです
Avatar
omochimetaru 8/25/2017 9:12 AM
あ、filterは
9:12 AM
これArrayが返るのか
9:12 AM
MyArrayが返ると思ってた
9:12 AM
じゃあgetしてるだけか
Avatar
そうですね
9:12 AM
filterというかイテレートの速度を見たかったので
Avatar
omochimetaru 8/25/2017 9:13 AM
なるほど
Avatar
(for だと基準になるやつが速すぎて最適化で消えてる疑惑があったので)
Avatar
norio_nomura 9/1/2017 2:00 AM
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)
Avatar
omochimetaru 9/1/2017 2:01 AM
Swift3.1だと詰めなおしてたけどSwift4はstartIndexをずらすだけの効率的な実装になった?
Avatar
norio_nomura 9/1/2017 2:02 AM
そう。
Avatar
omochimetaru 9/1/2017 2:02 AM
お〜 いいね おしゃれ
2:02 AM
customMirrorがクラッシュするのは何w
Avatar
norio_nomura 9/1/2017 2:03 AM
swift - The Swift Programming Language
Avatar
omochimetaru 9/1/2017 2:03 AM
0が範囲チェックされて死ぬのかw
Avatar
↑の 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) 0
Avatar
omochimetaru 9/1/2017 7:20 AM
startIndexが0であるかどうかとかは前提にしないべきなのでは?
7:21 AM
Arrayにおいては前提なのかな?
Avatar
でも subscriptindexstartIndex が最初の要素を指すよ。
Avatar
omochimetaru 9/1/2017 7:22 AM
DataのIndexがInt互換なのがまずい気がしてきた
7:23 AM
UTF8Viewとか使うときは、IndexがIntとは違う専用の抽象的な型になってるから
Avatar
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)
Avatar
omochimetaru 9/1/2017 7:23 AM
雑に 0 とかそもそもかけなくて
7:23 AM
startIndex と advance で書いていくことになって安全
Avatar
えー
7:23 AM
String と違って普通にランダムアクセスしたいでしょ?
7:24 AM
i バイト目なんだから Int で適切だと思うけど。
Avatar
omochimetaru 9/1/2017 7:25 AM
いまはadvanceじゃないんだった
7:25 AM
index(_:offsetBy:)
7:25 AM
ランダムアクセス自体はCollection protocolならできるから
Avatar
Array は必ず startIndex0endIndexcount - 1 として、わざわざ ArraySlice という型を設けて分離しているのに対して Data は一つの型でやってしまっていることと
Avatar
omochimetaru 9/1/2017 7:26 AM
collection.index(collection.startIndex, offsetBy: 6) -> 6番目の要素のIndexが返る
7:26 AM
collection [ collection.index(collection.startIndex, offsetBy: 6) ] -> 6番目の要素を取得
Avatar
removeFirststartIndex に影響を及ぼすのか及ぼさないのかという仕様の違いをどっちも混ぜてしまったのが問題では。
7:27 AM
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) 1
7:27 AM
ArraySlice とは一貫してるのか
7:27 AM
じゃあ Data は最初からスライスだと考えれば良いのか。
7:28 AM
String.UTF8Viewはデータ構造上O(1)ランダムアクセスができないからCollectionにはなってなくて
7:28 AM
index(_: offsetBy) はつかえないから、 index(after: ) で、+1ずつすすめていかないといけないことが
7:28 AM
型で表現されてる
Avatar
うん、 Data はそういうのとは違うから
7:29 AM
Int で適切だと思う。
7:29 AM
ちなみに EasyText なら O(1) ランダムアクセスできるよ。
Avatar
omochimetaru 9/1/2017 7:30 AM
それは一回全部書記素クラスタの配列にしてるからですよね (edited)
Avatar
うん、なので初期化は普通の String より遅いけど、計算量のオーダーは同じ。
7:31 AM
UTF-8 バイト列から String インスタンスを作るのと大して変わらない。
Avatar
omochimetaru 9/1/2017 7:32 AM
書記素クラスタ一つ一つは可変長データ構造だから
Avatar
うん
7:32 AM
ヒープにいっぱい
Avatar
omochimetaru 9/1/2017 7:32 AM
ヒープ上の構造としては2次元になっちゃうんじゃないですか
Avatar
領域を確保しなきゃいけないというのはある。
Avatar
omochimetaru 9/1/2017 7:32 AM
データ構造としては絶対そっちのほうが取り扱いやすいけど
Avatar
いや、でも
7:32 AM
String から構築してるから
7:33 AM
String がヒープに確保してるでっかい領域を
7:33 AM
Character が参照してるだけになるのでは?
Avatar
omochimetaru 9/1/2017 7:33 AM
あー SubStringのチャンク共有でうまくいくのかな
Avatar
String から characters を取り出したときに内部的にどうなってるか詳しいことはしらない。
7:35 AM
ランダムアクセスが多発する処理をするなら String より EasyText の Text の方が速そう。
Avatar
omochimetaru 9/1/2017 7:35 AM
ランダムアクセスのやり方にもいろいろあって
7:36 AM
先読みパーサーみたいなものを実装する場合は
7:36 AM
すでに訪問したIndexに戻る場合に限っては
7:36 AM
O(1)で飛べるんですよね
Avatar
そうだね。
7:37 AM
まあ、主な用途はパフォーマンスそんなに気にせずに簡単な API で雑に文字列を扱いたいときだね。
Avatar
omochimetaru 9/1/2017 7:38 AM
(C++とかで)パーサー書こうとして、マルチバイト文字めんどくさいのでuint32_tの配列とかにしようとおもいつつ
7:39 AM
utf8一個ずつ読んで、戻るときはindexに戻るだけで済ませられることがまれによくある
Avatar
それは書記素クラスタではなくコードポイントになってるのでは?
Avatar
omochimetaru 9/1/2017 7:40 AM
はい
Avatar
マルチバイト文字めんどくさいのでuint32_tの配列
7:41 AM
Swift の String がややこしいこと考えずに書記素クラスタで扱えるのはとても良いと思う。
Avatar
async/actorの議論でReactiveStreamなるスレッドが立ち上がってるけどあんまり追えてない
Avatar
!! $ 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] >>>
Avatar
omochimetaru 9/7/2017 6:53 AM
え・・・
6:53 AM
内包表記・・・
Avatar
pythonw
Avatar
omochimetaru 9/7/2017 6:53 AM
夢では
Avatar
Swift の REPL 上で Python の REPL を立ち上げられる?
Avatar
omochimetaru 9/7/2017 6:53 AM
ん???
Avatar
: が何かわかってない。
Avatar
omochimetaru 9/7/2017 6:53 AM
pythonに切り変わってるのかwww (edited)
Avatar
なんか Swift の ML に↑みたいなのが流れてたのを見かけて真似したらできた。
Avatar
:でlldbにスイッチして
6:54 AM
lldbはpythonだから〜ってことかしら
Avatar
omochimetaru 9/7/2017 6:54 AM
さらに script ってこまんどで
6:54 AM
lldb shellのなかでpython環境に入る気がする
6:55 AM
[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
6:55 AM
3層 in / in / in / out /out /out
Avatar
なるほど
Avatar
>>> ^D (lldb) ^D 1> ^D $
6:56 AM
ワロタ
Avatar
omochimetaru 9/7/2017 6:56 AM
pythonもC-Dで抜けられるのねw
Avatar
せやで
Avatar
抜けられない REPL って何かあるっけ?
Avatar
omochimetaru 9/7/2017 6:57 AM
swift
6:57 AM
あ、逆か
Avatar
抜けれるでは
Avatar
omochimetaru 9/7/2017 6:57 AM
exitで抜けられない
6:57 AM
exit派だった
Avatar
node も抜けられた
Avatar
なら :exit
Avatar
omochimetaru 9/7/2017 6:58 AM
oh
Avatar
irb も OK
Avatar
var exit: Never みたいなの生やせばexitで抜けれるようになるかしら
Avatar
omochimetaru 9/7/2017 6:58 AM
なるほど C-D 派のほうが暮らしやすいのか
Avatar
ghci (Haskell) も OK
6:59 AM
kotlinc もいけた。大体いけそう。
Avatar
$ 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)
Avatar
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)
8:13 AM
とかすると、二回didSetされちゃうのを避けるために、
8:13 AM
_ = { $0.foo = 12 $0.bar = 13 }(&hoge) っていう方法よりシンプルでわかりやすいのってありますか?
8:17 AM
(hoge.foo, hoge.bar) = (12, 13) これもだめ 😢
Avatar
hoge.mutateメソッドを生やしたら少し分かりやすいかも?
8:18 AM
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)
Avatar
hoge.mutate { $0.foo = 12 $0.bar = 13 } いいかも、使わせていただきまっす!
Avatar
Mutableプロトコルは名前が不自然なのでそこだけ変えて下さいw
Avatar
実際には RxSwift.Variable に使いたかっただけなのでこんな感じにしました。 extension RxSwift.Variable { func mutateValue(fn: (inout Element) -> Void) { fn(&value) } }
Avatar
あーーー
8:32 AM
ある
8:32 AM
わかる
8:32 AM
RxSwift.Variable
8:32 AM
setとgetそれぞれ単体ではlockされてるけど、通しでlockはできない問題がアッて
8:33 AM
variable.value.foo = xxx をマルチスレッドでやらかすと死ねる
Avatar
didSetの場合もですけど冪等に作っておいて多重実行は気にしないのが良いんですかね……
Avatar
Variable使わないほうがいいねっていう雰囲気はある
8:34 AM
mutateでgetからsetまで通しでLockかければ死ぬ問題は回避できるので
8:34 AM
extension RxSwift.Variable { func mutateValue(fn: (inout Element) -> Void) { _lock.lock() fn(&value) _lock.unlock() } } できるかな?こんな感じが良さそう。
Avatar
なるほどー
Avatar
Variable周り、初期値なしのVariableも欲しいよねとか色々欲求はあって
8:38 AM
前提案してみたんですがVariable自体をmain repoから切り出したいみたいで
8:38 AM
それ完了してからって感じでしたね
8:39 AM
mutateValueも絶対あったほうがいいけど、早く切り出されないかな。
Avatar
Short description of the issue: I'd like to be able to share a Variable object, without allowing access to the setter of value. Expected outcome: Basically, it could be another type (e.g. ReadOnlyV...
Avatar
BinaryInteger導入で[T1: BinaryFloatingPoint][T2: BinaryInteger]に変換するメソッドが書けるようになって喜んでたら [T1: BinaryInteger][T2: BinaryFloatingPoint]に変換するほうができなかった
Avatar
SignedIntegerUnsignedIntegerに分けてそれぞれInt64, UInt64を経由して変換するというろくでもない方法に落ち着いてしまった
Avatar
今、↓を受け取ってこれをコンパイル時に検出できないのはおかしいんじゃないかと思ったけど、 Conditional Conformance がないからまだできない? fatal error: Array<Foo> does not conform to Encodable because Pedestrian does not conform to Encodable.: (edited)
Avatar
できないですね
Avatar
Conditional Conformance 待ち遠しいですねぇ。
3:33 AM
Countable...Range を一掃できるのもうれしい。
Avatar
Argo ( Runes, Curry )を取り除いて Codable に置き換えた!
Avatar
omochimetaru 9/22/2017 3:48 AM
CodableってJSONのどこがわるかったかってわかるんですっけ
3:49 AM
あ、まあArgoならどうせわからないから関係ないか
Avatar
@omochimetaru Codable のエラーメッセージがどうなってるかは知らないけど、原理的にはパスをたどれそうな気がする。エラーが throw されてきたら素通しにせず、一度 catch してからエラーメッセージにパスを追記して throw しなおせばいいんじゃない?そうなってなかったら swift リポジトリへの PR チャンスかも?
Avatar
omochimetaru 9/22/2017 3:52 AM
潜りながら追記していくんじゃなくて
3:52 AM
例外の浮上に合わせて後ろから書いていくのか
3:53 AM
あ〜全然思いつかなかったけどそれでもできるな
Avatar
norio_nomura 9/22/2017 3:53 AM
Encoder, Decoderのエラーに含まれるパスは「とりあえずあるレベル」だと記憶。 (edited)
Avatar
omochimetaru 9/22/2017 3:54 AM
そのほうがパスの取り回しが異常系だけになるしパフォーマンス的にも賢いな
Avatar
swift リポジトリじゃなくて foundation か。
3:56 AM
いや、違うのか? Decoder につけなきゃいけないのか。
3:56 AM
JSON に限った話じゃないか。
Avatar
Swiftのmain repositoryだと、String.CharacterViewってDeprecatedなんすね、無限に警告が出てくるw
Avatar
なんか前も話したかもだけど、 =>inout 版がほしい気がしてきた。
12:39 AM
func =><T>(lhs: T, rhs: (inout T) throws -> ()) rethrows -> T { var value = lhs try rhs(&value) return value } (edited)
12:39 AM
みたいな感じ。
12:41 AM
でも、↓とオーバーロードしたら嫌な感じで衝突しそう。 func =><T, U>(lhs: T, rhs: (T) throws -> U) rethrows -> U { return try rhs(lhs) }
Avatar
そこはシグネチャ変えたほうが良さそうですね
Avatar
演算子でないと中置にできないから、新しい演算子導入するのは辛い・・・。
Avatar
’==>’ はもう使っちゃったんでしたっけ?
Avatar
使ってないけどそういう問題じゃなくて、わけのわからない演算子を二つも導入するのは耐えられないなぁと。
Avatar
まぁ、それはそうですね…
Avatar
さっき投稿した https://qiita.com/koher/items/344657d7a9ce85322c09 の中で書いた、 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 } } って書けそうだなぁと。
先日 Swift 4 がリリースされました。みんな注目しているのは Codable など劇的にコーディングが楽になる新機能だと思いますが、ちょっとした便利な小技もあります。 そんな、 Swift 4 の小技の魅力の一面を 3 行...
Avatar
subscript にデフォルトなんてのが増えていたんですか
Avatar
めちゃくちゃ便利
1:14 AM
↓なんかうまくいかない。何かミスってる?? 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)
Avatar
{ (a: inout [Int]) -> () in a.append(42) } クロージャパラメータに inout が必要
1:25 AM
推測させちゃったほうが楽ですね。
Avatar
ここもコミットチャンスだな
Avatar
なるほど、そこも inout がいるんですね・・・。考えてみれば当たり前だ。
1:27 AM
推論はうまくいかなかったんですよねぇ・・・。
1:27 AM
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)
Avatar
Swift 4.1だと推論うまくいきますね
Avatar
Swift 4.1👀
1:28 AM
こちらの環境はですね。 $ swift --version Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36) Target: x86_64-apple-macosx10.9
Avatar
3.2 でいけるからデグレってる。
1:29 AM
あ、3.1
Avatar
reduce(into:_:) だとうまく推論できたのも謎。
1:29 AM
↓これは動くんですよねぇ。 // 型の準備 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)") }
1:30 AM
クロージャ式のteamToCountinout なんですが、問題なく通ります。
Avatar
あ、やっぱりXcode9/Swift3.2 でいけますね。 4.0 だけの問題か。<推論
Avatar
4.1 でも推論できるってことは、既知の問題で対処済みってことなんですかね。
1:34 AM
発現条件が謎だ・・・
1:35 AM
reduce(into:_:) と違うのは inout の後の第二引数があるかないかくらいな気がするけど・・・
1:36 AM
演算子なのもよくないのかな・・・
Avatar
関数でも再現して、第二引数つけると 4.0 でも推論効くので、
Avatar
なるほど、単一引数のときに起こる問題なんですね・・・。
Avatar
3.2 と 4.0 で挙動違うとなると SE-110 https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.md 絡みの何かっぽいですね。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
norio_nomura 9/26/2017 2:20 AM
4.0.1へ入る修正と入らない修正の判断基準ってどんな感じなんだろう
Avatar
omochimetaru 9/27/2017 6:45 AM
片側レンジめっちゃいい
6:46 AM
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)
Avatar
Swift Parser!
Avatar
omochimetaru 9/27/2017 7:33 AM
libSyntaxを使ってるんだけど
7:33 AM
libSyntaxの実装が半端で
7:33 AM
やりたいことやるにはちょっとたりないのでパーサーをでっちあげてる
👏 1
7:34 AM
で、一応できたんだけど、Array + Int から ArraySliceにリファクタリングしてみていて
7:34 AM
[...<index] [index...] で分割できて良い・・・ってなった
Avatar
omochimetaru 9/27/2017 8:23 AM
うーん・・・ArraySliceだめだ・・・
8:24 AM
indexを更新しないといけないケースで型が同じだから書き忘れちゃう
8:24 AM
ダメというか今のシーンにはあってなかった
Avatar
omochimetaru 9/27/2017 8:42 AM
Contribute to SwiftPack development by creating an account on GitHub.
8:42 AM
結局Sliceやめちゃった
8:43 AM
やっていて思ったんだけど、Swiftの構文は結構パースしやすいように意識されている?
Avatar
norio_nomura 9/28/2017 1:54 AM
echo 'Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated())'|TOOLCHAINS=swift swiftc -swiftcがクラッシュする。
1:54 AM
タプルのラベルって一致してないとダメなんだったっけ?
Avatar
omochimetaru 9/28/2017 1:56 AM
クラッシュが再現した export TOOLCHAINS=org.swift.3020170918a
Avatar
norio_nomura 9/28/2017 2:00 AM
Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated().filter { $1 != "a" }) もクラッシュ。
2:00 AM
Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated().filter { $1 != "a" }.map { ($0, $1) }) でクラッシュ回避。
Avatar
.map { $0 } でもいけますね
Avatar
omochimetaru 9/28/2017 2:01 AM
3> Dictionary(uniqueKeysWithValues: [(offset: 0, element: "a")]) $R2: [Int : String] = 1 key/value pair { [0] = { key = 0 value = "a" } }
2:01 AM
これ自体はいける・・・
2:02 AM
["a"].enumerated().makeIterator().next() の型は (offset: Int, element: String)? なので
Avatar
norio_nomura 9/28/2017 2:02 AM
ラベルは関係ないのか。
Avatar
omochimetaru 9/28/2017 2:02 AM
ラベル一致性とかは多分大丈夫で型検査も正しく動いてて
Avatar
Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated().lazy) は別の形でクラッシュ
Avatar
omochimetaru 9/28/2017 2:03 AM
その先の動作系で何かが変?
Avatar
omochimetaru 9/28/2017 2:42 AM
いつのまにかはえてた
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 9/28/2017 2:43 AM
なるほど
Avatar
echo 'Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated())'|TOOLCHAINS=swift swiftc -でswiftcがクラッシュする。 swift-DEVELOPMENT-SNAPSHOT-2017-09-28-aで直った。
Avatar
omochimetaru 9/29/2017 1:14 AM
👏
Avatar
↓この前話してたやつのChris Lattnerのコメント。 [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
Avatar
omochimetaru 10/3/2017 1:47 AM
なんかそのスレでもう一回、Swift5のABI優先したいから無視で、みたいな
1:47 AM
返事がついてたきがする
Avatar
このML、せめて各メールにMLページへのパーマリンク入れてくれたら対応するページ探すの簡単になるのに・・・。
Avatar
omochimetaru 10/3/2017 1:48 AM
あー、週ごとに分断するの不便ですよね
Avatar
それも不便だけど、メール見てからリンク貼ろうとして探すの大変
Avatar
型システムバグってる気がする。 $ 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 = true
Avatar
omochimetaru 10/5/2017 1:59 AM
Array<T> と Array<U> の間のサブタイピングは
1:59 AM
本当のサブタイピングじゃない中途半端なやつって感じがしてる
Avatar
事実上のmap
Avatar
omochimetaru 10/5/2017 2:00 AM
代入可能だし is は 真になるのに、関数型に組み込まれたときはその互換性が発揮されない
Avatar
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] // true
2:01 AM
事実上のmap
確か前にここで確かめたときはこの場合でも CoW 効いててコピーは lazy だって話じゃなかったですっけ?
Avatar
そうそう
2:02 AM
CoWの効いたmapみたいなそんな感じだったと思います
Avatar
これはSemaあたりのバグなのかな?
Avatar
omochimetaru 10/5/2017 2:04 AM
バグ説だ
2:04 AM
こういうの慣れてきてバグみ感じない
Avatar
let f: () -> Cat? = { Cat() } let g: () -> Animal? = f // OK こっちはできたw
Avatar
omochimetaru 10/5/2017 2:06 AM
草w
2:07 AM
そういえば is の振る舞いって
2:07 AM
OptionalとArrayだけ特別扱いで
2:07 AM
自作のジェネリック型では無理ですよね?
Avatar
うん、今のところ。
2:10 AM
↓壊れ方に一貫性はあるw 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 }
Avatar
omochimetaru 10/5/2017 2:11 AM
contravariance側でも同じかw
Avatar
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 }
2:14 AM
関数もOKなので
2:14 AM
Array だけ壊れてるみたい
Avatar
omochimetaru 10/5/2017 2:15 AM
おお
Avatar
↓こういうのは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 } do { let a: [String: Cat?] = ["": Cat()] let b: [String: Animal?] = a // OK }
Avatar
omochimetaru 10/5/2017 2:17 AM
マジか!
Avatar
norio_nomura 10/5/2017 2:18 AM
as, is をoperatorにしてユーザーが定義できる様にして欲しくなる話だね。
Avatar
omochimetaru 10/5/2017 2:19 AM
それでもコンパイラの代入チェックのときには動かないような?
2:20 AM
実行時はas/isが書き換えられればいいけど、代入文の型検査時は静的だから書き換えたisが評価できない
Avatar
do { let a: () -> [String: Cat] = { ["": Cat()] } let b: () -> [String: Animal] = a // error: cannot convert value of type '() -> [String : Cat]' to specified type '() -> [String : Animal]' }
Avatar
norio_nomura 10/5/2017 2:26 AM
代入文の型検査時は静的だから書き換えたisが評価できない func as(lhs: A) -> Bの有無で決まるとか? (edited)
Avatar
omochimetaru 10/5/2017 2:29 AM
おー asの有無で制御してisはasの有無で自動生成だといけそうですね
Avatar
as書けるようになる時に、ジェネリクスの指定でサブタイプ指せるようになったら
2:36 AM
ジェネリクスの共編性をそっち側で表現できるかな
2:37 AM
func as<T, U>(_ v: My<T>) -> My<U> where U: T こういうの。無くても出来るかな?
Avatar
omochimetaru 10/5/2017 2:42 AM
as自体に型パラ取ってそうやれば変性をしばれそうだね
2:42 AM
ジェネリック型の変性は C# 形式のdeclaration-siteで class Box<out T> とかやるのが楽だしわかりやすいとは思うけど
Avatar
scalaの+-は解りやすくて好き
2:45 AM
swift、共編性やる気無さそうだしas拡張が先に来て、ワークアラウンドをツミツミすることになるなぁ
Avatar
前のジェネリック値型の自動共変、問題になるのはクラスが絡んだときだったから、値型に閉じた世界なら実現できそうな気がする。
2:46 AM
C# のジェネリック値型がどうなってるのかずっと気になってる
Avatar
値型は継承できなかった気が。。。
Avatar
前に↓読んだときには値型だけ特別視されてた気がする。その頃はJavaについて調べてただけだったから、読み飛ばしたけど。 https://blogs.msdn.microsoft.com/ericlippert/2009/12/03/exact-rules-for-variance-validity/
I thought it might be interesting for you all to get a precise description of how exactly it is that we determine when it is legal to put “in” and “out” on a type parameter declaration in C# 4. I’m doing this here because (1) it’s of general interest, and (2) our attempt to make...
2:50 AM
@hironytic 値型自体は継承できませんが、 Swift でいう↓みたいなのを作ったときの話ですね。 struct Box<T> { let value: T }
2:50 AM
この T についての変性をどう扱うのかが気になってます。
Avatar
ああ、そっちが値型
Avatar
omochimetaru 10/5/2017 2:51 AM
Swiftの値型って一箇所書き換えるのが全体書き換えだから T は常に out 扱いでうまくいかないんですっけ?
2:51 AM
あいや、メソッド引数の方に受けてればoutとは限らんか
Avatar
ジェネリック値型を作れる&declaration-site variance annotationな言語がC#しか思いつかない
2:51 AM
@omochimetaru 参照型と組み合わせたときに罠がある話を昔 @rintaro さんがしてた。
2:52 AM
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) らしいのですが、どういうケースなんでしょう?
2:53 AM
↑あたりの会話
2:53 AM
"Covariant" で検索
Avatar
omochimetaru 10/5/2017 2:54 AM
リンク先なんか見れないな
Avatar
↑の発言の後で「わかった!」みたいなのがあったはず。
2:55 AM
検索してJumpして前後を見るのが早いと思う
Avatar
前に @rintaro が成り立たない場合あるよ~みたいなことおっしゃってませんでしたっけ
Avatar
はい、言ってました。それをおもちに伝えてるとこです。
3:00 AM
ただ、値型に閉じてれば問題ないんじゃないかと思ってます。
3:00 AM
(プロパティもすべて値型)
Avatar
omochimetaru 10/5/2017 3:01 AM
検索して前後見たけどわからなかった 俺もそのときわかった感じになった記憶あるんだけど
Avatar
値型に閉じてればジェネリクスのout固定が成り立つ、ジェネリクス自体も値型に閉じてないと駄目じゃないですかね
3:25 AM
でもジェネリクスを値型に限定することは今はできない
3:25 AM
protocool Foo: classはできるけど、逆は出来ない。
Avatar
そうですね
3:26 AM
値型限定ほしいですよねぇ・・・
Avatar
もし値型に閉じていたら、FenceとFarmの例はどうなるんでしょう?
Avatar
ちょっと参照型で何が悪かったのか覚えてないですが、インスタンスの共有が起こらなければ起こらない問題だった気がします。
Avatar
インスタンス共有されてると、Fence<Cow>にSheep型がこんにちはしちゃうみたいな感じだった気がする
Avatar
Javaって確かそんな感じで配列がぶっ壊れるみたいな話有りましたよね
Avatar
あります。
Avatar
「Farm が Generic なクラスを持ってたらだめってことでした。」で検索 > FenceとFarmの例
Avatar
昨日の Array のキャストの絡みで、こういうの let a: [Int] = [] a is [String] // true
☠ 2
Avatar
omochimetaru 10/6/2017 2:31 AM
あー実行時検査だから
2:31 AM
あれ?でも [Int] とかってboxingしないメモリレイアウトじゃないんか??
2:32 AM
アクセスの都度、静的に Int仮定してんのかな
Avatar
空だけ特別?
Avatar
unsafeBitCast([Int](), [String].self) これ動きそう
Avatar
要素ごとにキャスト試して、エラーのものが見つからなかったら成功みたいな感じなのかな
Avatar
omochimetaru 10/6/2017 2:35 AM
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.
2:36 AM
このエラーメッセージが出るってことは、Arrayオブジェクト自体はメモリに Int型だよって情報を 持ってるように思う
2:36 AM
それか Int じゃなくて要素ごとに AnyにBoxingされちゃってるかだけど・・・
2:36 AM
流石にそれは無いと思うんだよなあ
Avatar
いや、たしか @rintaro さんの言うように全要素検査してた気がする。 Any にボクシングはない。
Avatar
omochimetaru 10/6/2017 2:37 AM
全要素検査しようにも、Intはただの8バイトなので
2:37 AM
それがIntであることがわからないはず
2:37 AM
Array側でメタ情報として知ってないと。
Avatar
そこは持った上で全検査なのでは?
Avatar
omochimetaru 10/6/2017 2:38 AM
AnimalからCatへのダウンキャストとかなら
2:39 AM
それでうまくいくか
Avatar
class Animal {} class Cat: Animal {} let a: [[Cat]] = [[Cat()]] a is [[Animal]] // true
2:40 AM
こういう複雑なのを考えたくないのかな?
2:40 AM
でも型だけで判断できると思うんだけど。
Avatar
omochimetaru 10/6/2017 2:40 AM
全検査の結果が正しくて、値型で個別検査できないケースは継承が無いからメタ情報だけで結論が出せて全検査をスキップ?
Avatar
何のために検査するんだろ??
Avatar
omochimetaru 10/6/2017 2:40 AM
[Animal] から [Cat] へのダウンキャストは
2:40 AM
要素が全部Catのときだけ成功するはず
2:40 AM
Dogが混ざってるかどうかは静的にわからない
Avatar
あー、それが true になるんだっけ
2:41 AM
そうか
2:41 AM
is の検査と as の成功が一致してないといけないのか。
2:42 AM
なので、 is はあくまでインスタンスをチェックしてるだけで式の型を調べているわけではないと。 (edited)
Avatar
let x = [Int]() as? [String] // Cast from [Int] to unrelated type [String] always fail, 但し x = []
2:42 AM
クソワロタ
Avatar
omochimetaru 10/6/2017 2:42 AM
式の型っていうのは静的検査のこと?
2:43 AM
@tarunon それはおかしいね 空の時だけは成功するんだから
2:43 AM
always failでコンパイルエラーはバグだ
Avatar
いや、warningですね
Avatar
omochimetaru 10/6/2017 2:44 AM
warningならいっか・・・?
Avatar
x = []が🙅なきがする
Avatar
いや、成功しちゃだめだと思うw
Avatar
omochimetaru 10/6/2017 2:45 AM
そもそも空の時にですか?
2:46 AM
ああ、warningじゃなくてerrorじゃないとってことかな
Avatar
warningは良いけど、キャスト成功シちゃだめ
👍 1
2:46 AM
つまりx = nilが正しい
2:46 AM
でも実行時にArrayはメタ情報とか持ってないからこうなってるんだと思う
Avatar
omochimetaru 10/6/2017 2:47 AM
持ってない派だ
2:47 AM
そろそろソース見るか・・・
Avatar
そうするともしかして
Avatar
1> let a: [Int] = [] a: [Int] = 0 values 2> type(of: a) $R0: [Int].Type = [Int]
2:47 AM
これは実行時情報じゃないってことですか?
2:49 AM
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>
Avatar
あれ、メモリサイズ同じ構造体ぶち込んでキャストしたらうまくいくかもと思ったら弾かれた
2:49 AM
うーん
Avatar
多分、キャストできるかどうかの判定を全要素がキャスト可能かで判定しているのがややこしい原因で
2:50 AM
インスタンスとしての型で考えてないんだと思います。
2:50 AM
でもそれって変な気がする・・・
2:52 AM
let cats: [Cat] = [Cat()] let animals: [Animal] = cats 一瞬、↑みたいなケースで catsanimals にコピーされないからインスタンスの型という概念が成り立たないかと思ったけど、コピーされないのはあくまでバッファであって、インスタンス自体の領域は別だからやっぱりインスタンスの型で判断できる気がする。
2:52 AM
あー、でもそうすると animals から catsas で戻せなくなるのか。 (edited)
2:53 AM
戻せなくてもいい気がするけどなぁ。
2:53 AM
Optionalisas もややこしくなるな・・・。
2:54 AM
runtimeがObjC ではない 場合の、 Array の _Buffer がこのオブジェクトだけど
2:54 AM
_EmptyArrayStorage って型もあって
2:54 AM
そっちは
2:55 AM
型パラがなくてstaticElementType がVoid.selfになってる
2:56 AM
internal struct _ContiguousArrayBuffer<Element>は
2:56 AM
空で初期化するときは↑のEmptyArrayStorageを内部で使う
2:57 AM
要素数付きの未初期化(uninitialized memory) バッファを確保するinitは型月の_ContiguousArrayStorage<Element> を使う
🌜 1
2:59 AM
final class _EmptyArrayStorage : _ContiguousArrayStorageBase { } final class _ContiguousArrayStorage<Element> : _ContiguousArrayStorageBase { }
2:59 AM
↑共通の親クラスになってて struct _ContiguousArrayBuffer は、 _ContiguousArrayStorageBase を var _storageでもってる。
3:01 AM
struct Array がAPI層で runtimeによってBufferの型を変える struct ArrayBuffer が 可変長バッファの制御をしてる実装の層 class ArrayStorage系 が実際の連続メモリを表現してるメモリの層で、空と型付きがあって、要素の型が取れる
3:03 AM
Arrayのinit() では _Buffer のinit() を呼んでるから _EmptyArrayStorage になってそう
3:04 AM
objc runtime の場合は、 ContiguousArrayBufferじゃなくて、 ArrayBufferが使われていて、 ArrayBufferは storage を持ってるので、 Array / Buffer / Storage の3層設計はおなじだけど
3:04 AM
internal typealias _ArrayBridgeStorage = _BridgeStorage<_ContiguousArrayStorageBase, _NSArrayCore> Storageの型がこれになっていて
3:05 AM
Storage の実装として BridgeStorage という概念が出てきて、 _NSArrayCore ・・・
3:05 AM
心配になってきた
3:05 AM
ちゃんとboxingしないでInt並べてるのか・・・?
3:07 AM
// rawValue is passed inout to _isUnique. Although its value // is unchanged, it must appear mutable to the optimizer. @_versioned internal var rawValue: Builtin.BridgeObject
3:07 AM
@_inlineable // FIXME(sil-serialize-all) public // @testable var nativeInstance: Native { @inline(__always) get { _sanityCheck(isNative) return Builtin.castReferenceFromBridgeObject(rawValue) } }
3:08 AM
var objCInstance: ObjC { @inline(__always) get { _sanityCheck(isObjC) return Builtin.castReferenceFromBridgeObject(rawValue) } }
3:08 AM
NativeとObjCは BridgeStorageの型パラメータで、
3:08 AM
rawValueってフィールドに
3:08 AM
どっちかの型のオブジェクトがぶちこまれて
3:08 AM
分岐したりキャストしてなんかEitherっぽくなってる
3:09 AM
internal typealias _ArrayBridgeStorage = _BridgeStorage<_ContiguousArrayStorageBase, _NSArrayCore> で、左側が さっきの pure swift のときの Storage の _ContiguousArrayStorageBase だから、
3:09 AM
大丈夫そうな気がする
3:09 AM
ObjCから来たオブジェクトだとBridgeStorageのrawValueが右側の_NSArrayCoreになっていて
3:10 AM
Swiftから来たオブジェクトだとrawvalueが左側のContiguousASBになっていると予想
3:10 AM
あとはなんか as とかでObjC側にブリッジしたりするときにめんどくさいことが起こるんだろう・・・
Avatar
[Animal] as? [Cat] これを実現するためには、1要素毎にキャストして成功したらOKみたいな処理にする必要があって
6:15 AM
Emptyだとキャストが発生しないから素通りしてしまってる、とか
Avatar
omochimetaru 10/6/2017 6:15 AM
Emptyならキャストできるのは正しいんじゃない?
Avatar
いやそうじゃなくて
6:16 AM
[Int] as? [String]
Avatar
omochimetaru 10/6/2017 6:16 AM
.none は Optional<Int> でもあるし Optional<String> でもあるのと一緒で。
6:16 AM
ああ その
6:16 AM
バグの話か
Avatar
それキャストできていいの?
Avatar
omochimetaru 10/6/2017 6:16 AM
俺はいいんじゃないかと思ってて。
Avatar
いや俺は駄目だと思う
Avatar
omochimetaru 10/6/2017 6:16 AM
Arrayの「内部の型」は
6:17 AM
あくまで効率化のためのメタ情報で
6:17 AM
Arrayは本当に値のリストを抽象化してるなら
6:17 AM
互換性がある方が正しい
Avatar
Optional<Int>.none as? Optional<String> これの結果は Optional<Optional<String>>であるはずで、その上で、Optional<Optional<String>>.noneになるはずだ
Avatar
omochimetaru 10/6/2017 6:19 AM
うーんっとつまり
6:20 AM
var a: [Int] = [] var b: [String] = [] print(a == b) これで結論が出ると思ったらコンパイルエラーだったw
Avatar
型をロジックの一部として使うことはわりとあると思うんだけど、 func 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)
👀 1
Avatar
やばい
6:21 AM
let x = [Int?.none, Int?.none, Int?.none] let y = x as? [String?] // [nil, nil, nil] これもなかなか。
Avatar
omochimetaru 10/6/2017 6:23 AM
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)
Avatar
Optionalを直接as?しようとすると怒られるので 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も同様にキャストが成功している。
Avatar
omochimetaru 10/6/2017 6:24 AM
こうすべきなんじゃないか
Avatar
それを書け、というのは中々どうして厳しいと思うけど。普通に初見殺しだ
Avatar
omochimetaru 10/6/2017 6:25 AM
あ、これtype: 消せるか
6:25 AM
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)
6:26 AM
うーんでも
6:26 AM
「値的な特性としての互換性」をみとめないと
6:27 AM
animals as! Array<Cat> のパターンが
6:27 AM
認められないと思う
Avatar
個人的にはそれ今実装されてるけど認めてない存在なのでなんとも
Avatar
omochimetaru 10/6/2017 6:28 AM
なるほど。
Avatar
そもそもArrayとOptionalの共変性、結構色んな所でボロが出てて酷い
Avatar
omochimetaru 10/6/2017 6:28 AM
型だけでみれば Array<Animal> は一般にDogも飛び出してくるから
6:28 AM
互換性が無いってのがいいね
6:28 AM
なんかSwiftのキャストって
6:28 AM
値の型がその型でもあるか
6:28 AM
っていう意味じゃなくて
6:28 AM
その型に変換できるかって意味な感じがする
Avatar
asの挙動としてはそう
Avatar
omochimetaru 10/6/2017 6:29 AM
(型変換コンストラクタはなんなんだってなるけど
6:30 AM
値変換性としてみた全体的な方向性は納得できて、おかしいのは、 var a: [Int] = [] var b: [String]? = a as? [String] // Cast from '[Int]' to unrelated type '[String]' always fails この警告だけ (edited)
6:31 AM
あ・・・
6:33 AM
わかった
6:33 AM
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)
6:33 AM
こうかくべきなんだ
Avatar
値型として考えたときにコピーで互換性さえあればいいでしょ、と言うのはそれはそれで成り立つかもしれないけど、だとするとクラスの型変換が同じ as で出来るのはおかしい。こっちは世界の崩壊を招く
Avatar
omochimetaru 10/6/2017 6:33 AM
「オブジェクトの型」で分岐したいのか「is/as 互換性判定」で分岐したいのかが別
6:35 AM
だとするとクラスの型変換が同じ as で出来るのはおかしい。こっちは世界の崩壊を招く
クラスの方は変換して新しいオブジェクトができちゃうと同一性が維持されないから無理で、
6:35 AM
インスタンスの実際の型が互換性があるかでしかキャストされない (edited)
Avatar
let x = [Int?.none, Int?.none, Int?.none] x is [String?] // true type(of: x) is [String?].Type // false
6:35 AM
これが正しい世界とは到底思えないんだけど
Avatar
omochimetaru 10/6/2017 6:35 AM
そうかなあ 俺はスッキリしてきた
Avatar
じゃあこれもOKなの? let x = [Int??.none, Int??.none, Int??.none] let y = x as? [Int?] // [nil, nil, nil]
Avatar
omochimetaru 10/6/2017 6:37 AM
let x = [Int?.none, Int?.none, Int?.none] type(of: x) == [Int?].self // true
6:38 AM
メタクラスの同値性で見れるから == でも書けるね、継承を区別したいときはこれが必要になる (edited)
Avatar
特定のケースに突入するとOptionalのtagged unionの特性が喪失するということと同義
Avatar
omochimetaru 10/6/2017 6:39 AM
OKで、 as? の考え方が違うってだけだと思う
6:40 AM
asってなんなんだ ドキュメント見てくる
6:42 AM
subclassがうんぬんと書いてあった・・・
6:42 AM
てかさっきの例で思ったんだけど
6:42 AM
Anyってやっぱnominal typeじゃないから
6:42 AM
元の値の型を保持してるんだな
6:42 AM
どんな型の値でも保持できる型であって、Anyという特定の型じゃない
Avatar
全部のprotocol型変数がそうじゃないかしら
Avatar
omochimetaru 10/6/2017 6:43 AM
だね protocol の Existentialがそう
6:43 AM
Anyもちゃんとそれの仲間ってことが確認できた
Avatar
そもそもAnyってprotocol<>じゃなかったっけ
Avatar
omochimetaru 10/6/2017 6:43 AM
それはそう
6:44 AM
でもなんかそれ証拠ってどこにあるんだっけ
6:44 AM
俺も知識としてはそれ知ってるんだけど。
Avatar
ヘッダーで見た気がするんだよなぁ
6:45 AM
なかった。かわりに
6:45 AM
/// 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)
6:45 AM
お前なんのエイリアスなんや…
6:46 AM
それちょうどみつけたよ
6:46 AM
BuiltIn.AnyObject
6:46 AM
public typealias AnyObject = Builtin.AnyObject public typealias AnyClass = AnyObject.Type
Avatar
stdlib特有のprivate(privateとは言っていない)だ
Avatar
昔は typealias Any = protocol<> が実際にあったけど、 & 記法になったタイミングで Any がキーワードになり、Parser で特別扱いになりました。
Avatar
omochimetaru 10/6/2017 6:54 AM
ほーーー
Avatar
そのうち typealias Any = Builtin.Any になるかもしれないですね。
Avatar
Swift4からOptional同士のキャストもas?で書けるようになってた。3からいけたっけ? 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)
9:48 AM
で、↑の非対称性が気になる
9:48 AM
そもそも値の互換性というのが動的型付け言語っぽくって中々厳しい感情があるというのが
9:50 AM
nn?
9:50 AM
これはこれで問題ないのか
9:54 AM
ああ、これですね
9:55 AM
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)
9:58 AM
as? と asで挙動がかわるのもあった
9:59 AM
bugs.swift.orgにあがってるかな。なければ後でまとめて書いておこう。
Avatar
すごいねそれw
10:04 AM
as? の使用に対して警告だしながら > Conditional cast from '[Optional<Int>]' to '[Int??]' always succeeds
10:04 AM
違う結果になるというw
Avatar
値互換、やろうとすると型システムの加護受けられないから、この手のバグが無限にでてくると思う
10:14 AM
jsでどう見てもfalseなのがtrueになる問題が対岸の火事じゃなくなるよ
10:15 AM
ああ、バグじゃなくて仕様になり得るのか
Avatar
検索(Covariantで)した感じあまり報告されてないっぽかったんで報告しようと思うんですが
1:05 PM
これの他に特筆するやつありますかね
1:05 PM
funciton周りとか?
5:31 PM
あった、これっぽい
5:32 PM
てか報告者りんたろ先生じゃんw
Avatar
swift tweetsの原稿書いてたらLoEのバグを見つけた https://bugs.swift.org/browse/SR-6103
Avatar
もうSwift 4.0.1へ入れてもらえないと諦めていた修正が入りそうで嬉しい。 https://github.com/apple/swift/pull/12369
What's in this pull request? Cherry-picks #11315 to swift-4.0-branch. Explanation: Better resolves SR-5206 until the introduction of conditional conformance. As a temporary workaround for SR-5206, ...
🎊 3
Avatar
@norio_nomura 元々は SingleValueContainerの中にUnkeyedContainerが入っててその中にバイト値が1つずつ入ってたのを
1:29 AM
Codable.swift と JSONEncoder.swift を改造することで SingleValueContainer に包む事がないようにした、って感じですか?
1:31 AM
いや中に入ってるわけじゃなくて2種類のフローがあるのかな、うーん
Avatar
Encoder, Decoderはサポートする型により、Codable自身のコーディング表現をオーバーライドする様になってます。
1:42 AM
例えばURLURL自身にエンコードさせると、["relative":"http://apple.com"]みたいな辞書表現になります。
Avatar
ふむふむ
1:44 AM
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.
Avatar
しかし、JSONEncoder"http://apple.com"として扱いたいので、EncodableURLだったらこうする、と特別扱いします。
Avatar
} else if T.self == URL.self { // Encode URLs as single strings. return self.box((value as! URL).absoluteString)
1:50 AM
本当だ。
Avatar
Optional, Set, Arrayにこれらの型が入っていた場合にも特別扱いしなければいけないのですが、Conditional Conformanceがないため、Decodableのコードが素直にかけませんでした。
Avatar
あーこれそういうことか URL.swift の initの冒頭にあるのは、 文字列表現だったときのフローがまずあって、ダメだったら辞書表現をやってた
Avatar
Swift 4.0の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)
1:59 AM
本当は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)
2:05 AM
Swift 4.0では、Standard Libraryで提供されるJSONEncoderとかのCoderで特別扱いされるURLの側で「JSONEncoderだったら辞書表現をやめる」みたいな力技で対応されていました。 https://github.com/apple/swift/pull/10766 (edited)
What's in this pull request? Addresses SR-5206 for JSONEncoder and JSONDecoder. One of the limitations of not having conditional conformance at the moment is that the implementation of init(from:) ...
Avatar
これだと任意のEncoder実装しても上手くいかなくなる
Avatar
そう、サードパーティのCoderではバグっていたのです。
2:09 AM
これがSwift 4.0.1で直りそう、というお話。
Avatar
ウレシイ
Avatar
サードパーティのCoder実装がどれくらいあるのか知りませんが…
2:15 AM
僕が書いてたYAMLCoder実装は未リリース。
Avatar
これがSwift 4.0.1で直りそう、というお話。 4.0.1に入るかどうか微妙な時期らしい…
Avatar
Slackから転載 @tarunon --- RxTestについての質問なのですが、Observable<Void>の送信をTestableObserverで検知したい場合 let results = scheduler.createObserver(Void.self) XCTAssertEqual(results.events, [next(0, ()), next(10, ())]) と書くとコンパイルエラーになってしまいます。 どのように書くと良いのでしょうか…? (そもそもObservable<Void>はTestableObserverでテストを書くべきでは無いのでしょうか…?)
Avatar
VoidってEquatableだっけ
Avatar
() == () // true
6:55 AM
それは俺も試した
Avatar
== はあるけど Eqatable ではないんじゃないかな?
Avatar
next(0,())、これ.足りてない?
6:59 AM
ああ、今はnextで書けるのか
6:59 AM
バージョン欲しいな
Avatar
func f<X: Equatable>(x: X) {} f(x: ())
7:00 AM
error: TempGround.playground:3:6: error: argument type '()' does not conform to expected type 'Equatable' f(x: ()) ^
7:00 AM
ほんとだ。
Avatar
イや違うよね
Avatar
Nominal ではないので、プロトコル当てられないと思う。
Avatar
next(0,())って書けるのはRxSwiftのテストケースがRecorded+Timeless.swift持ってるから
Avatar
--- @omochimetaru ありがとうございます。nextはRecorderというRxTestのObserveイベントの型を生成するメソッドです。 let results = scheduler.createObserver(Bool.self) XCTAssertEqual(results.events, [next(0, true), next(10, false)]) のようにBoolでは正常にコンパイル出来るので、voidの比較は出来ないのかなぁと ---
Avatar
書いてあるのか
Avatar
Equatableじゃないことが原因っぽいなあ
Avatar
えーと
7:04 AM
public func == (lhs: Recorded<Void>, rhs: Recorded<Void>) -> Bool { return lhs.time == rhs.time } これその辺に書いたら何とかなりませんかね
Avatar
なるほどな
Avatar
上と加えてEvent<Void>も要るかも。風邪なので布団に戻ります。
Avatar
風邪だったの・・・・
Avatar
@omochimetaru なんでXCTAssertEqualがEquatableじゃないRecordedを引数に取れるんだ?と思ったら
7:57 AM
XCTest+Rx.swift
7:58 AM
ここに拡張されたXCTAssertEqualが入ってた。なんでここにVoidの拡張を付け足すのが正解。
Avatar
お、なるほど、他にもそうやってる場所があるのか
Avatar
ConditionalConformanceはよ案件だねぇ。
7:59 AM
あとそもVoidがEquatableじゃないの、空タプルだから仕方ないとはいえ結構厳しい
Avatar
VoidはいかなるVoid同士で同一ということであってほしいね
8:00 AM
ああまだタプル自体もEquatableじゃないのか
Avatar
ConditionalConformanceが実装されても
8:01 AM
extension Void: Equatableが書けない限りはここに関して悲しみを繰り返すので
Avatar
どんなメタクラスでも入る型って書けないのかな?
1:37 AM
AnyClass は typealias AnyClass = AnyObject.Type なんだけど
1:37 AM
これだと class Cat {} ; struct Stone{} で Cat.self は代入できるけど、Stone.self は代入できない。
Avatar
Any.Type
1:39 AM
だめかな?
Avatar
あ、それがうまくいかないと思ったけどそれでいけたわ ありがとう
1:44 AM
メタクラス、Hashableになっていなくて、Dictionaryのキーにできない・・・
Avatar
ObjectIdentifier定期
Avatar
あ〜
Avatar
メタクラスは型毎にアドレスあるからいける
Avatar
メタクラスはシングルトン保証あるんだっけ
Avatar
クラス値と型
Avatar
完璧だ
1:45 AM
定期スレだった
Avatar
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)
😭 1
2:38 AM
今更Codable触り始めてるんですけどこんなもんなんですか?
Avatar
継承はうまくいかない
2:39 AM
手動定義でいろいろやっていかないと。
Avatar
protocolにEncodable適用した場合もその型でencodeに渡すの無理みたいですね……
Avatar
protocolに適用した場合ってどうなるんだ? Encodable protocol自体は連鎖して引き継ぐと思うけど
2:42 AM
いや、それでも自動生成されるはずじゃない? Codable protocol は Encodable & Decodable だから
Avatar
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)
2:43 AM
Dとして渡すと通ります
Avatar
Cのまま渡すってことか
Avatar
protocolでやるならCencodeメソッドを足してDや各々でエンコードってのが良さそうですかね
Avatar
/// 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 }
2:48 AM
型的にはなんでダメなのか謎だな
2:49 AM
そこでencodeメソッド手動で足すとどうなるんだ?w
Avatar
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()
2:51 AM
こんなつもりでしたが
2:51 AM
encode実装が個々に必要になるのが難点 (edited)
Avatar
open func encode<T : Encodable>(_ value: T) throws -> Data {
2:51 AM
JSONEncoder側の <T: Encodable> が
2:51 AM
このTって自動生成のerasureは適用できないんだっけ。
2:53 AM
protocol P {} class Cat : P {} func f<X: P>(_ p: X) {} var a: P = Cat() var b: Cat = Cat() f(a) // NG f(b) // OK
2:53 AM
やっぱそうだ
2:53 AM
さっきのCがダメな理由はこれ↑
Avatar
C のextensionにencode書けばいいのか。
3:02 AM
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() これがいける?
Avatar
encode() って名前の意味が変わっちゃっててわかりにくいし、 JSONEncoderを使う事が埋め込まれてるから、 toJSON() -> Data という名前の方が良さそう
🙆 1
Avatar
うーん軽く調べた限りではOptional.noneは常にフィールド自体省略になってnullにすることができない気が……
3:31 AM
fileprivate func box<T : Encodable>(_ value: T) throws -> NSObject { return try self.box_(value) ?? NSDictionary() } Container上では
3:32 AM
うーんいったりきたりしててよくわかrなn
3:32 AM
public mutating func encodeNil() throws { self.container.add(NSNull()) }
3:32 AM
こんなのもあるけどね
3:33 AM
return try JSONSerialization.data(withJSONObject: topLevel, options: writingOptions)
3:33 AM
↑ここで消えてるのか、それとも、コンテナ構造の時点で消えてるのか?
Avatar
コンパイラが生成するencode(to:)だとそうなりますね。
Avatar
あ、そこで消えるのか!
3:41 AM
じゃあ、encode(to:)を手動で書いて、encodeNilを明示的に使うようにしたら、挙動を変えられるんですね。
3:41 AM
コンパイラが生成するencode(to:)も合わせてコードを追跡しないと全容がわからないのがなかなか悩ましいな 便利だけど
Avatar
OptionalだとencodeIfPresent(_:forKey:)が使われるコードが生成される。これをencode(_:forKey:)を使うコードを自分で書けばnullが使われる。 https://github.com/apple/swift/blob/master/lib/Sema/DerivedConformanceCodable.cpp#L623-L624 (edited)
swift - The Swift Programming Language
Avatar
おおー これ読むと面白そう
3:50 AM
C++内部のSwiftコード生成APIだ
Avatar
Codable使う旨味が減っちゃいますねぇ。 Optional.noneのあつかいもstrategyで書けたらいいんじゃないかと思うんですが データ全体じゃなく部分ごとにここは省略したいとかある可能性もあるんで微妙ですかね
Avatar
そういう場合はOptionalを使わずに自分でモナド用意すれば?
Avatar
それが無難ですかねやっぱり
Avatar
Codableの旨味を最大化したいならそれがいいとおもう
3:51 AM
標準のOptionalはキーが消えるものとして諦めて、捨てる
3:52 AM
別に、computed property で Optional な get / set を作っとけば
3:52 AM
使い勝手は変わらないし。
Avatar
struct Foo: Encodable { var optionalInt: Int? private struct FooEncode: Encodable { var optionalInt: KeyedOptional<Int> /* Foo <-> FooEncode 変換書く */ } func encode() throws -> Data { return FooEncode(self).encode() } } こげな
4:14 AM
って考えたんだけど、変換書いてる部分がencode自動生成に相当するのであんまうま味ないですね
Avatar
Codableサボりたい方へ。 https://swift.quicktype.io
Avatar
JSONが先なのか
4:16 AM
べんりそう
Avatar
こういうの見るといじめたくなってしまう
Avatar
www
Avatar
quicktype - Quick types from data
Avatar
普通にかしこくて腰抜かした
😇 1
Avatar
無茶苦茶な型を与えるとちゃんとenum使って分岐してくれる、すごいねこれ
Avatar
へ〜〜〜〜!
Avatar
{ "objects": [ { "key": 1, "value": "foo" }, { "key": "2", "value": "bar" } ] } こういう意地悪すると、 enum Key: Codable { case int(Int) case string(String) } こんなのが生える
Avatar
そうそう、Optionalの判定もしてたはず
4:25 AM
{ "objects": [ { "key": 1, "value": "foo" }, { "key": null, "value": "bar" } ] } で、 struct Object: Codable { let key: Int? let value: String } (edited)
👏 1
Avatar
NSDictionaryからDataを経由せずに直接デコードしたい…
☝ 2
Avatar
遅レスですが、Codableで継承は基本的にsuperclass, subclassともに手で書くことになると思ってます。subclassの実装書く時にはsuperEncoder/superDecoder使うと感じで。 (edited)
1:40 PM
継承が使えないわけではなくて、一応仕組みは用意されてる。
1:42 PM
JSONDecoderがDataしか受け付けないの、やっぱり扱いづらいですよね(他との相互運用性的に) (edited)
Avatar
superEncoder/superDecoderの利用は必須ではないですね。superclassのデータをキーsuperに入れるかどうかはユーザー次第になってるかと。
Avatar
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) } } めちゃくちゃ汚いですがこれでやりたかったことはできそうです
12:30 AM
pythonでサーバー/クライアント書かれてるところにswiftクライアント作ろうとしてるんですがjsonの扱いが自由すぎて分析が大変……
Avatar
型付けしなければベタ移植できるのでは?
Avatar
型付けしたい願望
Avatar
型付けしないならパイソンでいいでしょw
Avatar
あと、スキーマ定義とかどっかにないのか
12:34 AM
パイソンのデコーダソースだけから目で復元するのはやばそう
Avatar
無さそうなんですねこれ……
Avatar
あ、デコーダよりエンコーダの方が構造わかりそう
Avatar
元のAPIはdictに何もかも詰め込んで放り投げてます
Avatar
そこのコードから構造が読み取れそう
Avatar
@ikesyo の ---
型パラメータをサブクラスで持って、親クラスではもたないと、型パラメータ部分を消せる
ちょうどKeyPathのクラス階層がそんな感じな気がする。ルートがAnyKeyPathで、そこからPartialKeyPath<Root>, KeyPath<Root, Value>みたいな。 https://developer.apple.com/documentation/swift/key_path_expressions --- これ、ウェブだとよくわからなかったのでXcodeからコピペ↓ 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)
2:23 AM
話題キープ
6:49 AM
AnyObjectにキャストすればresponds(to:)とか使えるという話
6:50 AM
import Foundation class Cat { @objc func eat() {} } (Cat() as AnyObject).responds(to: #selector(Cat.eat)) // true
6:50 AM
こんな感じで。
Avatar
Linux SwiftだとObjC Runtimeが無くてできなそう
Avatar
Foundation importすると使える裏技
Avatar
これって
7:04 AM
#selector(Cat.eat) ってやってるけど
7:05 AM
class Dog { @objc func eat() {} }
7:05 AM
に対してもtrueなのか?
7:05 AM
ObjC的にはセレクタになるときに "Cat" 性は落ちてるから
7:05 AM
Dog.catも #selector(Cat.eat)でヒットしそう。
Avatar
それはそう
Avatar
ダックタイピングができるね
Avatar
eatに@objcがついてないと当然Selectorは生えないのでfalseになる
Avatar
- (oneway void)release;
7:09 AM
おもしろいアトリビュートついてる
Avatar
oneway
Avatar
多分レシーバが使用不能になるとか
Avatar
これつまりSwiftのオブジェクトを、MRCのObjective-Cでも相互利用できるってことかな
Avatar
@objc class になってればできると思う
Avatar
Codableに準拠した型のletプロパティは、エンコードはされるけどデコードされることはないのね。
1:32 AM
letプロパティをエンコードされない様にするには、letプロパティを含まないCodingKeysを用意すると。
Avatar
あいや、デフォルト値を持つletプロパティだ。
Avatar
デフォ値無しなら復元出来ますよね?
Avatar
ですね。
Avatar
SE-0182 String Newline Escaping を読むとsingle lineでも使えると書かれてるけど、実際には使えない? https://github.com/apple/swift-evolution/blob/master/proposals/0182-newline-escape-in-strings.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
使えないです。Rationale に記載されております。 < single line (edited)
Avatar
なるほど、ありがとうございます。 🙏
Avatar
リリースタグはついてないけど、4.0.1と4.0.2はApple内部で存在しているのだろうか。 https://github.com/apple/swift/commit/1ba634302805b92f505cc3b87047aeccadc8dcf7
Avatar
NSDictionaryからDataを経由せずに直接デコードしたい… 作った。 https://github.com/norio-nomura/ObjectEncoder
ObjectEncoder - Swift Encoders implementation using [String: Any], [Any] or Any as payload.
6:57 AM
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"
Avatar
おお?
6:58 AM
Codableのencodeメソッドはどうなるんです?これだと。
Avatar
JSONEncoderPropertyListEncoderみたいに、各型についての特殊な処理が一切入っていないCoders実装になってます。
6:59 AM
[String: Any[Any]へそのまま突っ込むイメージ。
Avatar
あ、逆だ、勘違いsてた
7:00 AM
Codableはエンコード形式を特に規定していなくて
7:01 AM
JSONEncoderだからDataが最終的にやりとりされているだけか。
7:01 AM
ObjectEncoderだからAnyなどが出てくるんですね
Avatar
なるほど
7:02 AM
普通にお世話になりそうだw
7:02 AM
JSONオブジェクトとしかやりとりしない品のないOSSめっちゃありますからね (edited)
7:03 AM
G○○gle製とかFaceb○○k製とか
Avatar
利用イメージとしては 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)
7:05 AM
に、使えるはず…
Avatar
ああ、それ系のカオスなオブジェクトw
Avatar
JSONEncoderPropertyListEncoderData以外も受け付けるAPIを作ってPR出すことも考えたけど、変換部分が邪魔だった。
Avatar
Optional<URL>の関連ネタなんですけど、 { “id”: 1, “url”: “” } というAPIのレスポンスがあったとして、 struct Hoge: Codable { let id: Int let url: URL? } これでデコードしようとすると、Invalid URL StringということでdataCorrupted扱いになります。このとき、urlをnilで取り扱うためのワークアラウンド、どなたかお持ちですか? (edited)
Avatar
"url": "" がウソなのでそっち修正したいなぁ
Avatar
それな
Avatar
まあでも "url": null でも同じことなりませんか
Avatar
そうなの?
Avatar
その場合はちゃんとURL?.noneとしてデコードできます
Avatar
よかった
Avatar
あ、そうですっけか
Avatar
生のURLはムリな気がする、ウソもデコードできるURL型を自分で定義するしか無いんじゃないかな
Avatar
urlキーがない場合は自前でdecodeIfPresent書かなきゃいけないだけか
Avatar
struct Hoge: Codable { let id: Int let jsonUrl: String? var url: URL { get { ... } set { ... } } }
5:18 AM
こうしておいて、jsonUrl の CodingKeyを "url" にさせる
5:18 AM
とかってできるっけ
Avatar
Codable周りのコード全部自分で書けば出来る
5:19 AM
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 } }
5:19 AM
他のキーも定義しないといけなくなっちゃうけど・・・
5:19 AM
Codable全部書くよりはマシにできる
Avatar
たしかに、別なComputed Propertyで回避すればいいか。CodingKeysは俺の場合はQuicktypeで生えてるから、すぐいけそう。
Avatar
CodingKeyだけ定義できるのか
Avatar
Computed Propertyのgetterで 空文字列なら nil に変換する。 (edited)
Avatar
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)
Avatar
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)
5:28 AM
あー、不正ならそのままでいのか
Avatar
nilになる条件確認してみたけど空文字のときだけか
Avatar
"日本語" とか
Avatar
ほんとだ
Avatar
URL、確か怠け者なのでpunycodeとかクエリがデコード済みだとnilです
Avatar
URL(string: "httttttp::::////aaaaa") ↑いけた
😂 1
Avatar
punycodeやクエリがデコード済みでもURLにできる勤勉なメソッドも存在します(privateに)
5:32 AM
まじでゆるさんからな~~~
Avatar
struct Hoge: Codable { let id: Int let url: String? } extension Hoge { var urlurl: URL? {return url.flatMap {URL(string: $0)}} } Codableがjsonをそのままうつしていると考えればこう (edited)
Avatar
url: Stringimage: UIImageView と同じレベルでやめたい
Avatar
お、それだとCodingKeyの修正が要らないですね。モデル利用側では url のほうを使わずに urlurl を使うのが注意点か
Avatar
JSONと直接変換するモデルとプログラムに使うモデル切り分けるのがいいのではという気がしている
Avatar
Kishikawa Katsumi 10/26/2017 5:39 AM
url: String は合理的だと思いますよ。 URL オブジェクトはデータ構造というよりはユーティリティ。
Avatar
struct _Hoge: Codable { 略 }struct Hoge { 略 } でこいつら相互変換可能に。
Avatar
@Kishikawa Katsumi 何かパス加工などをするときに都度都度生成する方がいいってことですか?
Avatar
JSONと直接変換するモデルとプログラムに使うモデル切り分けるのがいいのではという気がしている
まさにやろうとしてる
Avatar
なるほど<切り分ける
Avatar
Kishikawa Katsumi 10/26/2017 5:40 AM
はい。URLのパスに関する操作が必要なときにオンデマンドで使えばいいと思います。もちろんURLで素直に受け渡しができるならそれでいいと思います。
Avatar
きみたちViewとViewModel切り分けるの得意でしょ
Avatar
extension Hogeをtargetted extensionにしてカッコイイ名前つければ、hoge.カッコイイ名前.url になるのでは
Avatar
フーム そのスタイルはあんまり考えたことなかったけど、 URL型はどうせガバガバだしありな気もします
Avatar
Hogeモデルのインナー型にRawみたいな構造体作ってJSON構造そのままマッピングしてアプリ内で使うやつはHogeにvar fuga: String { return raw.fuga }とかしてる
Avatar
targetted extensionはアリな気がしてきた
5:42 AM
codable、private propertyでも動きますよね
Avatar
@hiragram インナー型で HogeHoge.JSON にするの良さそう
5:43 AM
ただわける系の話はフィールドの転送を用意することになるしCodableからまた一歩遠ざかるなあ
Avatar
@omochimetaru jsonのキーの名前とアプリ内で使う名前が違うとかそういうのはそこで吸収するようにしてるからjsonのいけてなさにアプリがひきずられることがなくなっていいよ
Avatar
@omochimetaru @hiragram JSONから生成されるのがHoge.JSONなのでHogeをHoge.JSONから転写するのがしんどくなりそう
Avatar
Kishikawa Katsumi 10/26/2017 5:44 AM
まあAPIから受け取る値についてはAPIが外部のものかコントローラブルなのかによっても変わるけど、外部のAPIだったらURLは規格としておかしいけどAPIレスポンスとしては正しいみたいなものも来るのでStringで受け取ってから考えるとかはよくあると思います。
Avatar
URLって結構クエリストリング部分のマルチバイト文字エンコーディングとか挙動ブレがあって、型付けしたらはみ出して詰むとかまあまあ怖い
5:46 AM
たるのんがいってたパニーコードとかもそう
Avatar
Kishikawa Katsumi 10/26/2017 5:46 AM
まあURLは例としては極端なので一般化は難しいですね。
Avatar
URLだけじゃなくて、CGSizeとかでも辛みが回収されてよさそう Codableだと CGSize(width: 100, height: 50) に対応するのは { "width": 100, "height": 50 } ではなくて [100, 50] なんですよ
Avatar
マジw
Avatar
Kishikawa Katsumi 10/26/2017 5:48 AM
ただまあちょっと前にMastodonのJSONが id: Int から id String に変わったとかあるので、外部APIを最初に受けるところはあまり厳格にしてもというのはあります。
Avatar
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? } よさそう
😮 1
Avatar
Kishikawa Katsumi 10/26/2017 5:48 AM
コントロールできるAPIで自動生成とか厳格にできると思います。
Avatar
MastodonのJSONが id: Int から id String に変わったとかある
oh...
Avatar
まーた丼か
5:48 AM
あいつはほんまに
Avatar
おっマストドンまだ行きてたのか!
Avatar
💭 Mastodonを一般的Webサービスのレベルと同等に語るのは…
Avatar
マストドンもっと他にやることあるよな!な!
Avatar
壊れたHTML投げつけてくるのって治ったんですか
Avatar
コントロールできるAPIで自動生成とか厳格にできると思います
これになりたい
Avatar
Kishikawa Katsumi 10/26/2017 5:49 AM
別にアナウンスなしで、というわけじゃ無いので、問題ないかと。Swiftの変更とかとかわらない。
Avatar
Swagger Codegen的な
Avatar
マストドンid: Int のサーバとid: Stringのサーバと両方存在してつらい
Avatar
あーーーー
5:50 AM
マストドンだとそういうことになるのか
Avatar
Kishikawa Katsumi 10/26/2017 5:51 AM
まあ外部のI/Oは意図して/しないにかかわらず突然変わりうるという前提で作るのは我々の責任なので。
5:52 AM
変わったら潔くクラッシュするというのはそれはそれでアリ。
Avatar
Tagged Extension、この間のおもちのsubscript filterの応用でsetも出来るように出来ないかしら
Avatar
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)
5:58 AM
いろいろ雑だけど肝の仕組みは動きそう↑
Avatar
extensionで一括subscript定義はsetterがあるからムリかな?
Avatar
subscriptの引数が無駄になるっていうのが・・・
Avatar
そこは良い考えがある
Avatar
あ、あれか、オーバーロード法
Avatar
適当にありえないfunction定義して
5:59 AM
そうそう
Avatar
www
Avatar
func M<A: Modelable>(_ arg: A) -> Never { fatalError() } こいつ作っておけば cat[M].t.age = 6ってできるんじゃん?
Avatar
cat[Rx].tap.subscribe ...
6:03 AM
↑だと書き戻しが無いから例が悪いか
Avatar
extensionに一括setterむりぽ
6:17 AM
というか別に引数必要無いシーンでsubscript使う意味はなかった
Avatar
subscript使う意味は書き戻しでしょ?
Avatar
varで良い
6:18 AM
subscriptの価値は引数を与えて読み書き可能なプロパティを絞れるところなので
6:22 AM
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") } いけた。
6:22 AM
Mutableにしたいときは自前で書く
6:24 AM
MutableなExtensionでもいけました
6:24 AM
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") }
6:24 AM
うん、よさそう
Avatar
おお
Avatar
varで良いってそういう意味か。たしかに。
6:41 AM
varだと書き戻しが事前定義した静的な対象しか取れなくて、subscriptだとそれが実行時の値になるわけか。
Avatar
そうそう
Avatar
で、funcだと書き戻しができないと。
Avatar
subscriptはジェネリックなプロパティと言える
Avatar
そう考えるとそれぞれちゃんと役割が別れてるなあ
Avatar
本音を言うとModelに対してJSON<Model>を作りたい (edited)
Avatar
上のほうのURL?のDecode、ちょっと使えなさそうだけど、こういう方法もということで載せます。エンコード・デコードのカスタマイズも若干可能。 https://gist.github.com/rizumita/ae789fc056805f3843a946c76e1206f8
Avatar
ArrayとDictionaryを考慮しないといけないかなというのと、ネストしたらどうなるかしらというのが気になる
Avatar
ArrayとかだとArrayのextensionが必要になったり、たぶん面倒です。可能かも検証してないです。なのでちょっと使えなさそうということで。
Avatar
URL を URLComponents として保持するのもありなのかも?と思ったけど、これはどういう状態なんだろうか。 import Foundation var comps = URLComponents(string: "")! comps.url! // (no URL) (edited)
Avatar
URLComponentsはわからないけど、 NSDateComponentsは、抜けをゆるすタプル表現みたいなもので、そこからNSDateを構築する感じだったから
7:15 AM
↑の例も、いろいろたりなくて、その状態だと .url が作れないって感じ?
Avatar
Kishikawa Katsumi 10/26/2017 7:15 AM
URLComponentsは本当にユーティリティなのでそれで保持するのはやめたほうがいいと思います。
Avatar
URL -> URLComponents -> URL でラウンドトリップが完全に成立してるのか心配・・・
Avatar
Kishikawa Katsumi 10/26/2017 7:17 AM
DateComponentsとかと同様にDateまたはURLを作って終わり。
Avatar
@Kishikawa Katsumi 的には UUID も String で持つべきだと思います?
Avatar
Kishikawa Katsumi 10/26/2017 7:18 AM
APIから受ける値はStringで持ったほうがいいと思いますね。
Avatar
あ〜
7:19 AM
サーバーの実装がタコだと、小文字大文字違いによって、クエリ通らないとかありえるか・・・
Avatar
Kishikawa Katsumi 10/26/2017 7:20 AM
UUIDはそれこそ振る舞いというか性質というか(なんていうのが適切かわからないですけど)は手段であって、文字列以上のものではないと思います。
7:21 AM
APIとかモデルを規定するのにこのUser IDはUUIDですよというのを表明する意味でモデルのプロパティを UUID にするのはもちろんやるべきですし、私もそう書きます。
Avatar
ごめんなさい、ちょっと違いがわからなかったです。 モデルの User ID プロパティを UUID で定義するなら、 UUID を String で持つべきなのはどういうケースですか? (edited)
Avatar
(UUIDという型は定義するけど内部表現としては文字列で持つという事かな?
Avatar
アプリでUUID生成する場合は UUID、サーバから受ける場合は String?
Avatar
Kishikawa Katsumi 10/26/2017 7:31 AM
別にすべてStringで受け渡しするべき、というような極端な話ではないということを伝えたかったのです。難しいですね。
7:31 AM
外部APIから受け取るものはStringの方が望ましい場合が多い、
7:32 AM
ただ、それをアプリで使うときはStringじゃなくてUUIDを受け取るような設計の方が良いことが多いと思います。
7:32 AM
例えば、そのモデルを更新したり、こちらから生成するときのイニシャライザはUUIDを引数に取る方がいいです。
7:33 AM
UUID -> Stringは失敗することはあり得ないので。
7:33 AM
外のAPIからくる値がUUID型だったらUUIDで受けていいけど、大抵はStringなので、String => UUIDは失敗することがあるし、失敗は自明ではない(ことが多い)ので水際で弾くよりはStringでいったん受け入れる方が現実的、みたいな主張です。 (edited)
Avatar
なんとなく意図はわかった気がします。ありがとうございます!
🙏🏻 1
Avatar
Typed Dataへのパースと、 Domain-specific validationが一体化してるほうがいいか、分けてたほうがいいか という判断基準でしょうかね
7:41 AM
Avatar
@takasek 元ネタURLください!
Avatar
今気が付いたけどModel<Foo>、Realmで良く見るワークアラウンドそのものだし、同じ事がRealmで出来るかも
Avatar
ボイラープレート消せる方向性探りたいですね
2:26 PM
URLを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"}
Avatar
ウソもデコードできるURL型を自分で定義これすね
Avatar
ああー…そこで言われてましたね
Avatar
enumかRawValueで悩む
Avatar
encodeで元の値に戻るのを期待するかどうかですかね
Avatar
rawValue楽すね
2:43 PM
これ
2:43 PM
stringとしてデコードして
2:44 PM
extension String { var asURL: URL? { get } } が生えてるのと変わらないのではと思った
2:44 PM
RawRepresentableってCodableで特別扱い(=その値として扱われる)ってなってますかね
👀 1
Avatar
関係ないStringに asURL は欲しくないですね
Avatar
struct Bar: Codable, RawRepresentable { let rawValue: String init?(rawValue: String) { self.rawValue = rawValue } } これはエンコードできないな。
Avatar
ん?試したらそれいけますね
Avatar
oya
2:57 PM
あw
2:57 PM
JSONEncoderはTopLevelがオブジェクト/配列じゃないとだめだった
2:57 PM
すません
2:58 PM
RawRepresentableにするとかなり良さそう
Avatar
struct RobustURL: Codable, RawRepresentable { let rawValue: String var typed: URL? { return URL(string: rawValue) } init?(rawValue: String) { self.rawValue = rawValue } } すっきり
😃 2
Avatar
bbb
Avatar
RawRepresentable、なにも書かなくても、 {"rawValue": ...} の階層つくらないんですね、まじか‥
Avatar
その例だと init?(rawValue: String) も要らないんじゃないかな。
Avatar
昨日書かないとコンパイルエラー起こったと思ったんですが、今やったら削っても通りました…
Avatar
publicにする時には要るか。
1:21 AM
internalなら要らないですね。
Avatar
ですね
Avatar
プロトコルを定義する時に mutating func は mutating をつけておかないと、structで実装するときに実装できなくなっちゃうけど、 どうせいま考えてる実装がclassしかないとき、 ひとつひとつmutatingをつけるのが面倒だし意味がないので付けてなくって、 でもその状態だとどうせ struct で実装できないから、 protocol 自体に : class をつけることが多いんだけど
2:01 AM
みんなどんな感じ
Avatar
なんか protocolmutating 関連の Proposal なかったっけ?
Avatar
マジ 記憶にない 気になる
Avatar
気のせいかな?
Avatar
weakのやつならある
Avatar
: class にしてしまっている
Avatar
: classで思い出したけどこれ。 protocol Foo: class {} class Bar<X: class> {} Bar<Foo>() // 🙅
Avatar
あれ、 :class ってそこでもつかえる? :AnyObject にしてた。
Avatar
あ、AnyObjectか、でもダメだよ
Avatar
3行目はそれは無理ではって思う
2:07 AM
protocolは型じゃない(?)し
Avatar
じゃあArray<Animal>もダメでは?
Avatar
クラス: varが作れる、引数の型にできる、型制約にできる、型パラメータにできる シンプルprotocol: varが作れる、引数の型にできる、型制約にできる、型パラメータにできない 一般protocol: varが作れない、引数の型にできない、型制約にできる、型パラメータにできない
2:13 AM
言語仕様としてExistential周りの制約が緩まれば、それらもできるようになる可能性はある
Avatar
実は裏ワザもある @objc protocol Foo: class {} class Bar<X: AnyObject> {} Bar<Foo>() // 🙆
Avatar
wwww
Avatar
えぇ。。。
Avatar
@objc は深入りしたくない・・・互換性のためにいろいろ諦めてそうだしちゃんと考えて無さそう (edited)
2:14 AM
ObjCのプロトコルをインポートしてきた時に @optional なメソッドとかSwift上にそんな概念ないのにちゃんと考慮されたりするし
2:15 AM
しらんしらん
2:16 AM
@Biacco42 > : class にしてしまっている :class つけなくてもその前提条件だとコンパイルはできるんだけど、 考慮せずぜんぶ func にしてるんだって自覚を表明するためにつけといたほうがマシかなって思ってる
👀 1
Avatar
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 AnyObject
2:18 AM
しかもプロトコルじゃないのか。 https://developer.apple.com/documentation/swift/anyobject typealias AnyObject
Avatar
クロージャって値型だと思ってた
Avatar
クロージャは参照型です。
Avatar
Builtin.AnyObjectですよ
Avatar
それってどこから判断するんですか?
Avatar
The Swift Programming Language に書いてあった
Avatar
なるほど。
2:23 AM
ちなみに↑みたいなパターンだと僕は Box<T> に入れちゃう事がある
Avatar
あれ?3からautoboxingじゃなかったっけ
2:24 AM
as AnyObject
2:24 AM
クロージャだけ埒外なのか
Avatar
議論が難しい
Avatar
あーごめん 俺がBoxに入れたのは同一性判定がしたかったからだ
2:25 AM
でも参照型ってことはクロージャのままでもできるのか?
Avatar
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 ~ ^ ~
Avatar
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'
2:26 AM
できない
Avatar
=== のオペランドの型が AnyObject なのかも。
Avatar
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のポインタ比較だと思うんで
2:28 AM
毎回Box生成してるから中身の比較はできて無さそう
Avatar
うーんやっぱ値型っぽいんだよなあ手触りが
2:29 AM
あーでもあれか
Avatar
↓こういうところが参照型? var a = 0 let b: () -> Int = { a = a + 1; return a } let c = b print(b()) // 1 print(c()) // 2
Avatar
スコープオブジェクトのカウンタが増えるのか、スコープオブジェクトのプロパティのカウンタが増えるのか、の違いがあるのか。
2:30 AM
@koher キャプチャした変数をプロパティにもつstructとみなせるなあと考えていました
Avatar
@convention()によって挙動がいろいろですね。
Avatar
@norio_nomura 3種類ぐらいありますよね
Avatar
まあ実際にコピー時には関数の実体をコピーしてるわけじゃなくてポインタをコピーするだけだし参照型なのでは。
Avatar
Cコンベンションな8バイトポインタ、ObjC runtime互換なブロックオブジェクト8バイト、SwiftのFat Pointer 8x2バイト
Avatar
キャプチャした変数をプロパティにもつstruct
それなら↑のコードの c()1 にならないとおかしい。
Avatar
あー、a自体は値型だからか。
Avatar
@conventionは7種類あるらしい
Avatar
たしかに。値型をキャプチャして書き換えた時の挙動はスコープオブジェクトに対する参照型なのか
2:34 AM
- ``@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.
Avatar
多いw
2:35 AM
@convention(thin) indicates a "thin" function reference, which uses the Swift calling convention with no special "self" or "context" parameters. あー、ここに出てくる、 self と context がミソっぽいなあ 今の話
Avatar
これだとどうなるんだろ let b: () -> Int = { [x=a] in a = x + 1; return a }
Avatar
一応確認したけど、どれもAnyObjectには入らなかった>7種類。
Avatar
話戻るけど
プロトコルを定義する時に mutating func は mutating をつけておかないと、structで実装するときに実装できなくなっちゃうけど、 どうせいま考えてる実装がclassしかないとき、
class やめるのダメ?
Avatar
var a = 3 let b: () -> Int = { [x=a] in a = x + 1 return a } print(b()) // 4 print(b()) // 4 print(b()) // 4
2:37 AM
ああ、c忘れてた
Avatar
Objective-Cでidにはブロックが入った気がするから、AnyObject != id
Avatar
var 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 4
Avatar
あーまぁそうなるか、そうだね
Avatar
@koher > class やめるのダメ? classやめた瞬間に代入文の意味が変わってくるし 共有ができなくなるからいろいろ状況が変わる
Avatar
共有は↓だけ class 使うとか? class Ref<Value> { var value: Value }
Avatar
その時の例でいうとツリーノードを作ってて親への弱参照も欲しかったし、継承機能も使ってた。
2:43 AM
何もかも Ref で包めば参照グラフは作れるけど 何もかも包むとC++みたいで大変だし、そのパターンだと継承ができない
2:43 AM
クラス制約付きのprotocol と親クラスの比較だと、 親クラスだと1つしか持てないから特性の合成が表現できないし protocol なら実装漏れチェックができるけど親クラスだとできない
2:44 AM
クラス特有の機能が使いたくて、かつ、親クラスじゃなくて protocol を使いたい状況ってのはあると思ってて
2:44 AM
値型に無理によせても、それらの機能を手動でエミュレートしていく事になるから、それなら最初からclassに寄せたほうが良いと思う
2:46 AM
逆に TypeErasure でどこまでができて、どこまでならクラスにのっかったほうがいいのか っていうプラクティスは最近考え中。
Avatar
うーん、 C の &* がほしくなってきた。 struct&* の世界、実は良かったのでは? mallocfree が面倒だっただけで、そこをリファレンスカウントで勝手にやってくれるなら。
Avatar
スタックアロケートなオブジェクトはリファレンスカウンティングできませんよ。
Avatar
継承は半ばアンチパターン化してると思うからそれはやめて、抽象化はサブタイピングじゃなくてジェネリクスでやれば、問題になるのって共有したいときくらいで、簡単に参照型化できてメモリ管理をいい感じにやってくれたらそれが良いのかも? & じゃなくて、実体コピーした上で参照型化かな。
2:49 AM
参照型化した瞬間にヒープに領域確保されてコピーされる。
Avatar
それだと既存の参照がdanglingになります
Avatar
既存の参照?
Avatar
たとえば・・・
Avatar
重要なのは参照がとれることじゃなくて、任意の値型を共有したいときにヒープに確保して(もちろんリファレンスカウント付き)共有できることかと。
Avatar
あー、エスケープする前にコピーされてるから、それはできる気がしてきた。
Avatar
struct Foo を作ったけど、それを共有したいときは Foo * として取り扱えるとうれしい。 (edited)
2:52 AM
* の意味は C と同じになるけど、 & はちょっと違うから別の記号が良さそう。
Avatar
なんか変な破綻が起きる気がしなくもないけど (edited)
2:53 AM
必要な場所では Box<Stone> になっているボクシングが
2:53 AM
全部自動で行われているような状態になるのかな
Avatar
うん、やってることは Box<Foo> と同じなんだけど
2:54 AM
簡易的な構文があるとうれしいねって話。
Avatar
Go言語のスタック退避GCを
2:54 AM
同じ話を逆方向から見た話か
2:54 AM
ちなみにrustには
2:54 AM
box 1
2:54 AM
って、boxって書くとboxingされますよ。
Avatar
OptionalArray みたいに BoxReference でもいい)のシュガーがあればいいのかも。
2:55 AM
Foo*Reference<Foo>
Avatar
weak var foo: Foo*? こうなる? (edited)
Avatar
class Reference<Value> { var value: Value }
2:56 AM
prefix func * もほしいか
Avatar
それ自体は作れそうですね。
Avatar
で、 Foo*Reference<Foo> だとうれしくない?
Avatar
ああ、tarunonが言ってるのは、boxの型の略記か。
Avatar
これweak参照どうやるんですか
Avatar
weak var a: Reference<Int>? で良いんじゃない? (edited)
Avatar
weak var foo: Foo*? かな?
Avatar
structがweakになれないだけで weak varは作れるんだっけか
2:58 AM
いつもぐちゃぐちゃになる
Avatar
いや、Referenceはそもそもclassだから
2:58 AM
普通のswiftの話だよ
2:58 AM
あ、違うのか?
Avatar
ちょっと戻るけど let a: () -> Int = { 42 } let block = a as @convention(block) () -> Int as AnyObject
👍 1
Avatar
いや、そうだ。class Box じゃないとそもそもヒープ退避できない。
3:00 AM
@rintaro let a: () -> Int = { 42 } let block = a as AnyObject print(block) as AnyObject はそもそもそのままできそうですよ
Avatar
あら。
Avatar
あ、ちがうか、 === の話ですか?
Avatar
NSMallocBlockとかになるの?
Avatar
僕が議論が追えてないだけだと思う。
Avatar
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
3:01 AM
いや、完璧に追えてますね、なるほど!
Avatar
ほーー
Avatar
これはおもしろいw
3:03 AM
() -> Int false @convention(block) () -> Int true
Avatar
↑は aas AnyObject でボクシングされるけど
3:03 AM
b はすでに AnyObject だから
Avatar
type(of: a) と type(of: b) をprintしてみた↑
Avatar
何も変化してないってことやんね?
3:04 AM
当然↓にはなる。 let a: () -> Int = { 42 } let b = a as AnyObject b === b // true
Avatar
let 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'
3:04 AM
bはあくまでコンベンションブロックなクロージャであってAnyObjectではないみたい。
3:05 AM
まあ実際にはAnyObject互換なオブジェクトなんだろうけど・・
Avatar
protocol P { func method() } type(of: P.method) でコンパイラがクラッシュする
😫 1
Avatar
クロージャのようなAnyObjectのようなやつ
Avatar
is NSObject?
Avatar
@norio_nomura www
3:06 AM
報告価値ありそうだけど今まで誰も踏んで無さそう・・・
Avatar
dump(P.method)もダメだった。
Avatar
dumpってなんですか?
Avatar
↓これ納得行かないな・・・ var x: AnyObject = b // NG: value of type '@convention(block) () -> Int' does not conform to specified type 'AnyObject' (edited)
Avatar
あった。
Avatar
コード内でlldbのpoをやるみたいなの。>dump (edited)
Avatar
@koher もうほんと形式的な話でしょうねw
Avatar
闇を感じる 2 行だ・・・。 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'
Avatar
コレみたいなものだと思えば import Foundation let a = "str"; let b: NSString = a
Avatar
class 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
3:14 AM
_SwiftValue なる型になってた。
Avatar
_SwiftValue、言語側のboxingでよくみる
Avatar
@rintaro ↓ですw swift-string.swift:3:19: error: cannot convert value of type 'String' to specified type 'NSString' let b: NSString = a ^ as NSString
3:17 AM
そして @rintaro さんがコンパイラのソース( C++ )に触れすぎて ; が付いてる😅
😄 1
😱 1
Avatar
そう、 as NSString なら通る。明示的なキャストを言語的に強制してるということです。
Avatar
T -> T?とか[Cat] -> [Animal] も明示するようにしよう!!!
Avatar
:tarunon: 絵文字ほしくなってきたな
Avatar
@rintaro うーん、↓はいいと思うんです。 false だから。 import Foundation let a = "str" a as NSString === a as NSString // false
3:19 AM
納得がいかないのはさっきの ===true になるところ
Avatar
それも import Foundation let str = "str" let b = str as NSString (b as AnyObject === b as AnyObject) // true と同じじゃないかと。 (edited)
Avatar
let b: @convention(block) () -> Int = { 42 } b as AnyObject === b as AnyObject // true
3:24 AM
でも
3:24 AM
import Foundation let str = "str" let b = str as NSString let c: AnyObject = b // OK
3:24 AM
ですよね?
3:24 AM
納得がいかないのは let b: @convention(block) () -> Int = { 42 } b as AnyObject === b as AnyObject // true let c: AnyObject = b // ERROR
👍 1
Avatar
なるほどー、そこか。
Avatar
純粋にバグな気がしてきました・・・ let b: @convention(block) () -> Int = { 42 } b as AnyObject === b as AnyObject // true b is AnyObject // true let c: AnyObject = b // ERROR
3:26 AM
is AnyObjecttrue なのに代入できない・・・
Avatar
import Foundation let a = "aaa" a is NSString let b: NSString = a is trueだけど代入できないのはよくあるから
3:27 AM
それとあわせて as AnyObject === がtrueになるのが特殊?
3:28 AM
なんだろう、一つ一つは他にも例がある現象だけど、全部の組み合わさった時が独自のふるまいになっている感じ。
Avatar
このあたりの特殊型変換は闇が深そう・・・この前話してた Optional も含め
Avatar
@convention(block) の時点で ObjC の世界に入っているわけだから、 AnyObject にそのまま突っ込めてもいい気はしますね。
Avatar
そうですよねぇ。
Avatar
なるほど。
Avatar
protocol Proto : AnyObject {} class Box1<X> {} Box1<Proto>() // OK class Box2<X: AnyObject> {} Box2<Proto>() // NG: 'Proto' is not convertible to 'AnyObject'
4:01 AM
なんだこりゃ
Avatar
そうだよ
4:11 AM
Array<Animal>が成り立つのはElementがconditionalじゃないから
Avatar
'Proto' is not convertible to 'AnyObject' ってエラーメッセージ出てるけど Proto : AnyObject なんだけどなあ
Avatar
@objc つけよう^^
Avatar
@tarunon のそこでいうAnimalはprotocolなのかclassなのか?
Avatar
protocolやで
Avatar
マジか さっきの勘違いしてた
4:12 AM
Animalはスーパークラス世界代表
Avatar
これ今まさにRxSwiftでやらかしてしまって、対応中なのです
Avatar
protocol は protocol に準拠できない。
Avatar
protocol は protocol に準拠できない。
おお。ルールとしてはこれだけか。
Avatar
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)' これと同じですね。
Avatar
これ2桁番台でバグ報告されてるんですよね
Avatar
なるほど。納得。
4:27 AM
これがあるから シンプルなプロトコルでexistential変数が作れる機能が実質役に立たないと思ってる最近。
Avatar
シンプルなプロトコルでexistential変数が作れる機能
禁止でいいと思ってる。
Avatar
ドヒャア
4:29 AM
え、じゃあこれも反対ですか?
4:30 AM
Generalized Existentialの、ジェネリックパラメータが無い状態だけ中途半端に実装済み、という状態と理解していて
Avatar
Generalized Existential もほとんどいらないと思うんよね。
Avatar
禁止じゃなくて発展の方向だと思ってた。
4:30 AM
マジか
Avatar
手書きType erasureは移行期間中のワークアラウンドで
4:31 AM
Generalized Existentialがサポートされたら不要になる、という方向なのかと・・・
Avatar
いや、そりゃそうなんけど
4:31 AM
実際 AnySequence とか使いたくなるケースの 8 割くらいは実はいらないんじゃないかなぁ。
Avatar
あと、手書きErasureとGeExの違いとして、 as とか is の挙動が
Avatar
Java 的な感覚が抜けてないパターンが多そう。
Avatar
メソッドでエミュレートしないといけないのがしんどいから言語サポートされてほしい
4:32 AM
あるプロトコルを満たすオブジェクトをコレクションに集めるってパターンがよくあるんじゃないですかね。
Avatar
まあ、今の状態が中途半端なのは間違いないから、 Generilized Existential サポートするか、シンプルプロトコル型も禁止するかどっちかにしてほしい
Avatar
で、集めたやつらに対して、そのプロトコルのメソッドを呼び出し。
4:33 AM
そうですね。
Avatar
あるプロトコルを満たすオブジェクトをコレクションに集める
うーん、これってサブタイピングをベースに抽象化しようとするからじゃないかな?
4:34 AM
最初からプロトコル型が使えなければそもそもそういう事態にならなくない?
Avatar
いえ、シンプルじゃないプロトコルはそもそもExitstentialが無いので
4:34 AM
TypeErasureを作ってからコレクションに集める話なので
4:35 AM
最初から使えないという前提ですね
4:35 AM
たとえば3Dシーングラフでも、プログラミング言語のASTでもいいですけど
4:35 AM
ノードツリーに対して
Avatar
heterogeneous なコレクションはあるか
Avatar
ノードツリーをウォークして、ある特徴をみたすノードを洗い出して
4:36 AM
一括で処理をかける
4:36 AM
みたいな事はあると思う
Avatar
enum Node とか?
Avatar
たとえば、ASTなら、visibilityがコントロールできるノードについて全部publicにする、
4:36 AM
というのを最近実際にやった。
4:37 AM
enumにしてしまうとparent参照が作れないです
4:37 AM
あ、enumならindirectでいけるのかな
Avatar
indirect
Avatar
まあでも話それてませんかね
4:38 AM
あるメソッドを持つノード、だから、enumだと余計に面倒になる気が。
4:38 AM
全部同じ型だし。
Avatar
うーん、最近サブタイピングに懐疑的で、 9 割くらいはサブタイピングなしでいけると思うんよね。さっきの参照型の話と同じで。
Avatar
それはわかるんですけど残り1割のための言語機能はあったほうがいいと思います
4:41 AM
なるべく回避したいし、9割回避できるのは同意だけど、1割が書きやすいにこしたことはない。
Avatar
一つだけ type erasure 作ってなんとかならないかな?さっきの Reference と同じように。後は使いやすいシュガーがあれば。
Avatar
一つだけ?というのは、何に対して?
4:42 AM
いまはprotocol1種類についてerasureを1つ実装しないといけない
Avatar
そうだな・・・
4:43 AM
結局 Generalized Existenstial になってしまうか?
4:44 AM
うーん、なんというか、 existential に変換する場合のオペレーションが明示的ならいいと思うんよね。
4:47 AM
クラスも継承もサブタイピングもなくて、本当に必要な場合だけ参照や Existential に変換できる世界だと型システムがもっとシンプルになる気がしてる。今の Swift の protocol と参照型の相性が良くないような。
4:47 AM
もちろん今の状況から現実的じゃないのはわかってるけど。
Avatar
「protocol は protocol に準拠できない」ルールの話、いっそ { ∃X, X: Animal } という存在型を略して Animal 型と書くのをやめてぱっと見で存在型だってわかるようにすればもうちょい理解しやすくなりそうですね
Avatar
そのルールが間違っているように思います
5:55 AM
実際、手書きで type erasure を書いたときはそうだし、組み込みのAnySequence は Sequenceだし。
5:56 AM
typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> let strings: AnySequence<String> = ["a", "b", "c"]
5:57 AM
manifestoのgeneralized existentialのところに、↑の例もありますが、これが実装された時互換性の観点からもAnySequene : Sequence になるはず
6:04 AM
これ報告したのについたコメント見る限り、コアチームとしては「protocolはprotocolに準拠できない」が正だという認識を持ってそう (edited)
6:06 AM
↑のGeneralized existentialに習うと、
6:06 AM
シンプルだろうが一般だろうがprotocolの存在型を示すときに
Avatar
ん、それは、今はそのルールがあるから、現状のこのレポートは正しい挙動になるはずって話で
6:06 AM
僕が言っているのはそのルールは今後見直すことになるはずってこと。
Avatar
シンプルなら、Any<Animal> 一般なら、Any<Sequence where ...>と
6:07 AM
そう表現したものを存在型ということにすれば
6:07 AM
Animal.selfがprotocol型で準拠するものではなく、Any<Animal>.selfが具体的に準拠したりできるようになるはず
6:07 AM
かしら?
6:08 AM
つまり、Animal型の変数を持つときに let animal: Animalは駄目になって、
6:08 AM
let animal: Any<Animal> がOKになると色々整合性取れてきそう
💯 1
Avatar
あーなるほど
6:09 AM
Any<>で作ったExistential Type と、 protocol type は別のものだよねって認識なら
6:09 AM
protocolはprotocolに準拠できないままで特に困らないのか。
Avatar
そうそう
6:09 AM
それで困らないためには、シンプルプロトコルを変数の型にできる今の状態は相容れないので、
Avatar
Existentialの方が準拠するわけか。ああ、そっちのほうが正しいな。
Avatar
今はprotocolが、protocolとしての機能と、部分的にExistentialの機能も内包して混乱の元になってる
Avatar
はげしくどうい
Avatar
混乱の元というか、まあ壊れてるんですよ
6:12 AM
かなしい
Avatar
なんだったんだろうね?シンプルプロトコルのExistential
6:13 AM
ObjCのprotocolの相互運用のためにあるのかな
Avatar
ObjCのprotocol闇が深い
Avatar
P1 & P2Any<T where T: P1, T: P2> とか?
Avatar
よさそう
6:14 AM
Any<P1 & P2> と短く表現できるならそれも有り得るかな、これは昔あったけど死んじゃったんでしたっけ (edited)
Avatar
Any<P1 & P2> が Exitentialになるという仕様になってほしい P1 & P2 はあくまで protocol (edited)
Avatar
protocol<P1, P2>P1 & P2 になりました。
Avatar
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絡むととたんにやばくなるやつ
😇 1
Avatar
ってかそれクラッシュしそう
Avatar
しないんだなこれが
Avatar
・・・
Avatar
respondsToSelector で false 返すから?
Avatar
UITableViewDelegateって@required なメソッドもなかったっけ。
Avatar
UITableViewDelegateは全部optional funcなので
Avatar
ないのか。
Avatar
requiredはDataSource
Avatar
あ〜〜〜〜〜w
6:19 AM
やられたw
Avatar
でも多分、required funcのあるパターンも書ける、何が起こるかは試したことがない
Avatar
メソッド無くてクラッシュじゃないかしら。objcではよくあること
Avatar
よくあることやな
😂 1
Avatar
それが(なるべく)無いように注意深く API 設計してるのか。。。
Avatar
unrecognized selector sent to instance 0xXXXXX いつものだw
Avatar
なつかしい
Avatar
見てない間に進んでた。
つまり、Animal型の変数を持つときに let animal: Animalは駄目になって、
let animal: Any<Animal> がOKになると色々整合性取れてきそう 良さそう。
Avatar
よさそうですね! んで、 Animalbark() メソッドをもってるとして、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()
Avatar
よさそうですね! < Any<Animal>: Animal なわけではなく (edited)
Avatar
struct S { var a: Int = 3, b: Int = 4 }
12:20 PM
こんなんかけたんか
Avatar
CGFloat って Swift 3.1 まで FloatDoubletypealias じゃなかったっけ? https://developer.apple.com/documentation/coregraphics/cgfloat
5:31 AM
struct になった?
Avatar
元からそうだった気がします
5:31 AM
typealiasなのはTimeIntervalですね
Avatar
わざわざ変換して計算してた記憶なのでtypealiasじゃなかったような (edited)
Avatar
あれ?元から struct でしたっけ?
5:32 AM
記憶違いのようですね。ありがとうございます。
5:33 AM
仕様としては確実に struct の方が良いと思います。(環境によって FloatDouble に切り替わるとやっかいなので)
Avatar
omochimetaru 11/6/2017 5:37 AM
ObjectiveC では typedef だった
Avatar
ObjC はそうだね。それと記憶が混ざっちゃったのかな・・・。
Avatar
omochimetaru 11/6/2017 6:03 AM
Swiftになって CGFloat はいつも明示的変換で、おっ、ええやんけ、って思ってた気がする
Avatar
あれ?自分も CGFloat は昔 DoubleFloattypealias だったような気が…Obj-Cとの記憶が混乱したのか 😇
Avatar
TimeIntervalはDoubleのエイリアスなのでそれも相まって記憶が混濁してそう
Avatar
TimeInterval と ObjC の両方と混同してたような気がします😅 (edited)
8:36 AM
すくなくとも Beta時代は typealiasだったっぽい
Avatar
omochimetaru 11/6/2017 8:38 AM
本当だ
8:38 AM
Swift 考古学
Avatar
おお、なんか 32bit か 64bit かで CGFloat のコンパイルが通らなくなる夢を見てた気がしてたんですが、この頃の記憶かも。
Avatar
よかったよかった記憶が正しかった
Avatar
swift のコミットを遡れば時期も明らかになるかと思ったけど CoreGraphics だった・・・ (edited)
Avatar
omochimetaru 11/6/2017 8:39 AM
swift本体側のSDK overlay header?かも。
Avatar
まあ確かに CoreGraphics だし import Foundation しないと使えないし
8:40 AM
こういうのはswift側に入ってるんですよね、よくわからんけど。
8:41 AM
CGFloat.swift.gyb あった。
8:41 AM
@_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)
Avatar
NativeTypetypealias になったね
8:44 AM
このファイルではこれより昔はなさそう。
Avatar
omochimetaru 11/6/2017 8:44 AM
拡張子が変わってるけど、
Avatar
CGFloat is 32-bit on 32-bit architectures and 64-bit on 64-bit architectures for historical reasons. Rather than having it alias either Float (32-bit) or Double (64-bit), introduce a distinct struc...
Avatar
omochimetaru 11/6/2017 8:45 AM
+public struct CGFloat { +#if arch(i386) || arch(arm) + public typealias UnderlyingType = Float +#elseif arch(x86_64) || arch(arm64) + public typealias UnderlyingType = Double +#endif (edited)
Avatar
@rintaro おおお!
Avatar
omochimetaru 11/6/2017 8:46 AM
@DougGregor DougGregor committed on 9 Jul 2014
8:46 AM
オープンソースになる前・・・?
Avatar
1.0 の頃じゃない?
Avatar
1.0のリリースのときっぽ
Avatar
omochimetaru 11/6/2017 8:46 AM
なるほど
Avatar
betaからやってきてもリリースノートちゃんと読まないとこうなるんですね 😇
Avatar
omochimetaru 11/6/2017 8:59 AM
古い仕様の事は忘れたい
Avatar
昨日話していてそんな気がしたんですが やっぱりOptionalの暗黙変換とOptionalの共変性は矛盾した結果を生むので両方入ってるのは厳しいですね
😂 1
Avatar
暗黙の型変換をサブタイピングっぽく振る舞わせてるのが諸悪の根源ですね・・・。
5:52 AM
暗黙の型変換出ない本物のサブタイピングである Kotlin なら何の問題もありませんね。 // 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?) }
Avatar
String?.none as? Int? => Int??.some(.none) は確かにおかしい結果を生むんですが、それ以前に共変性周りが崩壊していることに気がついた
Avatar
ただし Int?? でネストを表現できないですが😅
Avatar
Kotlinはネストしないからいけます
Avatar
Swift では本来 IntInt? のサブタイプじゃないですからねぇ。
Avatar
サブタイプじゃないのにサブタイプっぽく振る舞わせてるのがダメ
Avatar
はい。そこがヤバイです。
Avatar
あとは共変性もウソなのではという気がしないでもないけどまあそれは
5:55 AM
えゔぉりゅーしょん書かなきゃいけないンゴねぇ…
Avatar
共変性はまあいいんじゃないですか? Optional<Cat>Optional<Animal> のサブタイプでも、 IntInt? のサブタイプでなければ Optional<Int>Optional<Int?> のサブタイプにならないですし。
5:56 AM
暗黙の型変換はともかく、サブタイプのように振る舞わせてるところが一番邪悪な感じがしますね。
Avatar
String?.none as? Int? => Int??.some(.none) こいつをウソのサブタイプを倒した後でどう説明するのが良いのか、どう言う振る舞いであるべきなのかを考えないといけない気がする
6:00 AM
Cat?.none as Animal? これが暗黙のmapであるとするのであれば上の結果は正しいということになりますね
Avatar
String?.none as? Int? => Int??.some(.none)
これよくわからないんですが、 StringInt はパースですか?
Avatar
Avatar
ああ、 StringInt
Avatar
String?.none as? Int? ってやると結果が Int??.some(.none)になるんですよ。つまりキャストが成功する
Avatar
あれ?違った。
7:11 AM
あー、そういうことか。
Avatar
正しそう
Avatar
as?? を忘れてた。 (edited)
Avatar
[String]() as? [Int] これは 空配列になる。
Avatar
あー、要素全部キャストできたらルールがあるからか。
7:13 AM
そのルール変だと思うんだけどなぁ。
Avatar
この2つは同じ問題の具象で、なので個人的には共変性はウソなのでは?という疑念を持っている
Avatar
読み違えてた。キャストできちゃうの型としてはおかしいですね
Avatar
↓成功しないのおかしくないですか? 1> Int?.none as? Int? $R0: Int?? = nil (edited)
Avatar
omochimetaru 11/7/2017 7:24 AM
え!?
Avatar
.some(.none)も.noneもnilとして表示されます
7:24 AM
なのでチェック用の関数作ってください
Avatar
omochimetaru 11/7/2017 7:24 AM
なるほど!!!
Avatar
あ、そうなのか、
Avatar
nilリテラルわかりづらい
Avatar
omochimetaru 11/7/2017 7:25 AM
おそらく .some(.none) なわけだ
Avatar
2> print(Int?.none as? Int?) Optional(nil)
7:25 AM
大丈夫だった。
Avatar
omochimetaru 11/7/2017 7:25 AM
1> dump(Int?.none as? Int?) ▿ Optional(nil) - some: nil $R0: Int?? = nil
7:25 AM
dump便利
Avatar
↓がおかしいのか。 String?.none as? Int? // .some(.none)
Avatar
それがどうあるべきかということですね
Avatar
僕は .none であるべきだと思います。
Avatar
desune
Avatar
omochimetaru 11/7/2017 7:28 AM
空配列の互換性ルールから考えると .none になりそうですよね
Avatar
はい
7:28 AM
なので
7:28 AM
[String]() as? [Int] // .some([]) (edited)
7:28 AM
これも .none であるべきかと
Avatar
Animal?.none as? Cat? ではこれは?
Avatar
omochimetaru 11/7/2017 7:29 AM
あれ?そっち派?
Avatar
だって、全要素チェックとかおかしい気が。型の互換性だけを見るのがいいと思う。共変性は許すにしても。
7:30 AM
あー、違うのか、値だから一度アップキャストしたらダウンキャストできなくなるのが問題なのか。
Avatar
でですね
7:31 AM
([String]() as [Any]) as? [Int] (edited)
7:31 AM
じゃあこれどうすんのという話になるわけです
7:32 AM
なのでボクの立場としては共変性多分ウソなのでmap明記するようにしたい
Avatar
Animal?.none as? Cat? ダメな気がしてきた
Avatar
let cats = [Cat]() let animals: [Animal] = cats // OK let cats2: [Cat] = animals as! [Cat] // これは? (edited)
7:32 AM
↑になってしまうのかぁ。
7:33 AM
確かに共変性はウソなんだけど、
Avatar
omochimetaru 11/7/2017 7:33 AM
そうですね、値型だから、実体共有はそもそも起きないから、都度都度の話になる
Avatar
let animals: [Animal] = cats // OK ↑ここで CoW を効かせたいからなぁ。
7:34 AM
明示的に map すると先行コピーされちゃう。 (edited)
Avatar
omochimetaru 11/7/2017 7:34 AM
なるほど。
Avatar
lazy sequenceでなんとかなんないですかね
Avatar
omochimetaru 11/7/2017 7:34 AM
Arrayになるときにlazyを保てないような?
Avatar
アップキャストは共変っぽく働いて、ダウンキャストは明示的 map でもいい気も?
7:36 AM
C# って値型とジェネリクスと変性がそろってるけどその辺りどうなってるの?
Avatar
omochimetaru 11/7/2017 7:36 AM
C#は空でも別物扱いだった気がする、あとListは参照型じゃなかったかな
7:37 AM
まともになったJavaって印象がある
Avatar
List は参照型だけど、値型+ジェネリクス+ out のときどうなるのかなって。
Avatar
omochimetaru 11/7/2017 7:39 AM
普通に共変が効いた気がするけど曖昧です
7:39 AM
ダウンキャストできないんじゃないかなあ・・・
Avatar
アップキャストは通るがダウンキャストは全てNG、これは筋が通ってそう
7:40 AM
wandboxにC#もあるっぽいです
Avatar
C#, 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); } } }
Avatar
omochimetaru 11/7/2017 8:03 AM
なるほど・・・
Avatar
omochimetaru 11/8/2017 2:07 AM
Swift版のgybを作ったんだけど、Swift4の文字列APIがいい感じだった。 https://github.com/omochi/gysb/blob/master/Sources/gysb/Parser.swift#L201-L209 あと enum Token がいい感じだった。 https://github.com/omochi/gysb/blob/master/Sources/gysb/Parser.swift#L51-L60 (edited)
gysb - Generate your swifty boilerplate
gysb - Generate your swifty boilerplate
Avatar
omochimetaru 11/9/2017 2:39 AM
昨日の async void の人から長文が返ってきた https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171106/041028.html
Avatar
async throws voidだったらどうするんだっていうの聞きたいな
Avatar
@tarunon 是非聞いて下さい〜🙃
Avatar
後で聞いてみます
Avatar
夜に送信したら送信先ミスってることに夜中に気づいて送信し直したんですよね
Avatar
しかし、元の beginAsyncthrows をなくそうという話への反応が少なくて悲しい。 Chris Lattner と Joe Groff の見解が知りたい。
Avatar
Void自体は存在していて、それはasync funcのタスク完了を意味するから言語仕様としてomitしてはいけない
Avatar
(Foo) async -> Void の戻り値を受けなくても別に問題ないですよね?
9:41 AM
await foo() await bar() await baz()
9:41 AM
単に foo の非同期処理が完了後 bar が実行され、 bar が完了後 baz が実行されるだけで。 (edited)
Avatar
はい。省略する分には構わないと思います。
Avatar
ああ、そういうことか。 < 言語仕様として
9:42 AM
async -> Void ができなきゃいけないって意味ですね。
Avatar
そうです
Avatar
beginAsyncthrows について反応がないのはなんでなんだろう?静的チェックの安全性を壊すか壊さないかの重要な話だと思うんですけどねぇ・・・。
9:45 AM
英語がひどすぎて読めないのかな?😂
😫 1
Avatar
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"
5:13 AM
型名からメソッド名を参照すると、レシーバについてカリー化された関数の型になっているの、知らなかった。
Avatar
https://github.com/apple/swift-evolution/blob/master/proposals/0042-flatten-method-types.md 一応仕様変更予定です。が、Swift3に間に合わなかったので再考の必要あるとTedがMLで発言していた記憶あります。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
ああ、このプロポーザル眺めた記憶が出てきた
Avatar
- Indices.swift.gyb + Indices.swift
2:32 AM
おー、 CondConfでgybが一つ減る
Avatar
これは4.1へ入ると期待していいのかしらん?>Conditional Conformance (edited)
Avatar
もう機能はできててガンガンstdlibに適用してるフェーズですかね?
Avatar
CountableRange 系の削除に期待。
Avatar
それがあった
Avatar
gybかなり減りそう
Avatar
Generics系の機能が一つ入るたびにgybの需要が一つ減るからね
Avatar
Conditional Conformance で CountableRange 消す PR 書くの気持ち良さそう。
Avatar
https://swift.org/blog/swift-4-1-release-process/ によると 11/27 がデッドラインかと。大きなバグが見つかったら4.1ブランチだけで機能 disable の可能性はあるにせよ。
This post describes the goals, release process, and estimated schedule for Swift 4.1.
Avatar
やっぱり厳しそうですよね。
2:40 AM
Conditional Conformance自体は書けるけどstdlibは書き直されていない、な状態で入る可能性もあるのかな? (edited)
Avatar
過去にそういう事例はあった気がする。
Avatar
難しそう。>Conditional Conformance自体は書けるけどstdlibは書き直されていない
8:50 AM
CodableとかAPI自体を見直さないとダメそう。>Conditional Conformance (edited)
Avatar
import 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で動いた。
👏 2
Avatar
おおお
9:02 AM
ついに Conditional Conformance な世界が触れるようになるんですね。
Avatar
extension S: Sequence where Wrapped: Sequence { func makeIterator() -> Wrapped.Iterator { return value.makeIterator() } } はコンパイラクラッシュ
Avatar
なるほど。まだまだ開発中な感じなんですね。たしかに SequenceElement, Iterator, SubSequence とあって、それらが関係しているので複雑そうです。
9:12 AM
↑の Wrapped.Iterator を自分の Iterator として解決する辺りとかヤバそう。
Avatar
Conditional Conformanceが入ると[Any]Codableでは無くなる?
Avatar
そうだと思ってます。
9:36 AM
extension Array: Codable where Element: Codable {} かと。
9:37 AM
Equatable とかと同様に。
Avatar
[AnyHashable: Any]も。
Avatar
[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.
Avatar
extension Dictionary: Codable where Value: Codable {} が必要な気がします。正確には EncodableDecodable 別々に。
3:39 AM
あー、キーもか
3:39 AM
extension Dictionary: Codable where Key == String, Value: Codable {} こうかな?
Avatar
そうではなくて、AnyCodableみたいなものが必要なんじゃないかな?と。
Avatar
CodableassociatedtypeSelf も持たないだたの protocol だから、 Codable 型として existential になりますよね? struct Foo: Codable {} let foo: Codable = Foo() // OK
Avatar
Existentialそれ自体はそのプロトコルを満たさないからそれで取り回すと不便な事が多いですよ
Avatar
そう、それがさっきのエラーメッセージに書かれていたこと。> You must use a concrete type to encode or decode. (edited)
Avatar
protocol P0 { } struct A : P0 {} func f<X: P0>(_ x: X) {} var a: P0 = A() f(a) // error
Avatar
EncodingContainer達にも、<T: Encodable>を受けるAPIはありますがEncodableを直接受けるAPIは無いです。
Avatar
ですね。
Avatar
なるほど。
Avatar
Swift.Codersの実装PRにも「内部でダイナミックキャストが必須なのであれば、<T: Encodable>ではなくEncodableを直接受け取れば良いのでは?」とコメントしたのですが、受け入れられませんでした。
Avatar
ほお・・・
Avatar
これって Generalized Existential で AnySequence がなくせる話と絡んで、 Any<Codable> とかできるようになるのかな?
Avatar
そう思います
Avatar
プロトコル型がそのプロトコルを満たさないのってなんでなんだっけ?
Avatar
それは僕も疑問、仕組みだけで言えば満たせると思う。全部の機能をちょうど持ってるから。 (edited)
Avatar
↓はできるのか。 1> let a: Any = 42 a: Int = 42 2> func foo<T: Any>(_ x: T) { print(x) } 3> foo(a) 42
Avatar
PRではなくJIRAだった。 https://bugs.swift.org/browse/SR-5206?focusedCommentId=25786&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-25786 Encodableではなく<T: Encodable>なのは、decode()側が<T: Decodable>を使う必要があり、そちらと一貫性を持たせる為だと言われた。
Avatar
よさそうですね! んで、 `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でなくなる理由とか嬉しい点って何ですか?
11:42 AM
この話とAnimal protocolがAnimalのextentialじゃなくなる話が多分同じはず
Avatar
Any<Animal>がAnimalのextentialでなくなる理由
12:23 PM
説明が難しいんですが、一言で言うと存在型の理論そのままいくとそうなるって感じです。内部的にはいまもopenas ↑の動きになってますね
12:24 PM
型チェックの段階でopening existentialが入ってます
Avatar
今もそうなんじゃないかと直感していて、じゃあ現状のprotocol変数は存在型として実装されていて、理論があってということ
12:25 PM
理論を理解しないと先に進めないか
12:26 PM
とすると、 Animal.self こいつは存在型の型で (edited)
12:26 PM
Animal.self is Animal.Typeはfalseになるのが正しい?
Avatar
存在型へのpack/unpackが暗黙的に行われているのでサブタイプっぽく振る舞えるのがややこしくしている原因かなと思います。
12:27 PM
Animal.self is Animal.Typeはfalseになるのが正しい?
12:27 PM
Self: Animal って意味ならtrueが正しいです (edited)
Avatar
えーっと、ArrayとOptionalの変性はめちゃくちゃなので無視するとして
12:31 PM
func foo<T: SomeProtocol>(...) これに対して、Tの型はかなりカッチリしていて
12:32 PM
ちゃんとSomeProtocolを実装した型じゃないと通らない。SomeProtocolの存在型は変数ではキャスト可能(に見える)が型としてはダメなので通らない正解.というわけ
12:33 PM
T:AnyObjectの時にTにStringが通らないのと同じか。
12:34 PM
@ukitaka 理論は後回しにして挙動と斯くあるべきかは理解できました、ありがとう。
👌 1
Avatar
foo<T: SomeProtocol>(t: T)とfoo(t: SomeProtocol)の話で言えばこんな感じですね
Avatar
let a = animal openas A // 将来opening existentialが入るとする
12:48 PM
このときの a の型ってなんですか?
Avatar
Aです
Avatar
それは test2 の型パラメータの <A> と同じって意味?
Avatar
あ、いやなにかわからないけどA: AnimalなAという意味です。
Avatar
Existentialだからサブタイプじゃないってことですか?でも Genralozed Existentialが導入されたらExistentialを使ってAnySequence (= Sequence のサブタイプ) を作りたいわけですよね??
Avatar
うーん、AnySequenceは、Self: Sequenceな型であって、AnySequence: Sequenceではないって感じですかね。。
Avatar
書きたいことがあるんですが今スマホなので後ほど…
Avatar
↑の件です。 まず、↓はできません。 protocol Animal {} struct Cat: Animal {} func bar<T: Animal>(_ x: T) { print(x) } let b: Animal = Cat() bar(b) // NG (edited)
1:49 PM
しかし、↓はできます。 func foo<T: Sequence>(_ x: T) { print(x) } let a: AnySequence<Int> = AnySequence([2, 3, 5]) foo(a) // OK (edited)
1:50 PM
そして、 Generalized Existential が実現されたら↓になることが示唆されています。 typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials (edited)
swift - The Swift Programming Language
1:51 PM
そうすると、現状との互換性を考えると当然 fooAny<Sequence where .Iterator.Element == Element> という Existential Type を渡せるということになります。
1:52 PM
ここで、 Existential をサブタイプとして振る舞わせるのであれば、 Animalbar に渡せてもいいように思うのですがいかがでしょう?
Avatar
たしかに...渡せたほうがよさそうですね > 現状との互換性を考えると
1:57 PM
その場合はAnimalをbarに渡したときにも型チェック時にopening existentialが挿入されるようになるとかですかねぇ〜
Avatar
確かに今は型パラメータは具体的な型で埋められるので、どういう扱いになるのか謎ですね🤔
Avatar
これのremove()実装、1個づつmoveInitialize()してるけど、まとめて出来るはず。 https://qiita.com/omochimetaru/items/f32d81eaa4e9750293cd
Swift の Array や Dictionary は Copy on Write になっていてとても使いやすいです。この記事では、そのような Copy on Write の実装方法を解説します。

CoW の動作

Copy ...
Avatar
おっ、そんな細かいところまで、見てくれてありがとうございます
10:06 PM
ちゃんと一個ずつずらしてやってくれるんですかね?
10:06 PM
この手のAPI、メモリ領域が重なってても期待通りに動くことがあったり動かなかったりするので避けました。
10:07 PM
インデックスが若い順に1つずつ処理されるなら大丈夫そうだけど、インデックスが後ろからやるかもしれないとか。
Avatar
そもそもSwiftのArrayの removeSubrange も O(n) だからいいじゃないかなと思ったりする https://developer.apple.com/documentation/swift/array/2884498-removesubrange
Avatar
moveInitialize にしても O(n) なのは変わらないですね でも、ループを自分でやるより関数に畳み込むほうが最適化も期待できるし、コードはシンプルにできるので、ちゃんと動くなら書き換えたほうが良さそう。
Avatar
当たり前っちゃ当たり前だけど、remove 系のメソッド全部確認して見たらやはりremoveLast だけ O(1) だった
Avatar
あっ
1:35 AM
左から右か右から左か
1:35 AM
アドレスで分岐するのかw
1:35 AM
かしこいな
1:35 AM
/// - 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.
1:35 AM
source and this may overlap だから
1:36 AM
オーバーラップもオッケーだ
Avatar
更新しました。
Avatar
いつぞやのfilterMap、acceptedになってた (edited)
12:45 AM
Forced Reviewってなんぞや
Avatar
focused re-review で、名前だけ再考するってことかと。
Avatar
flatMapのオーバーロードが危険なのは間違いないから分けるとして、分割先のメソッド名は考えましょうってことですか?
Avatar
んだ。
We are re-opening the review until next Monday, November 20th, 2017, in order to have a focused discussion about the new name.
Avatar
Focusedだった、完全に空目でした. 🙈
Avatar
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) }
Avatar
げっ、なんだこりゃっ
2:43 AM
正規表現リテラルをただ入れるだけじゃなくて、正規表現リテラルと言語を合体させて、内側に let があるのか。
2:43 AM
すごいアイデア
2:43 AM
あ、パターンマッチのマッチと
2:43 AM
regexのマッチが
2:43 AM
同時に成立するのか。
Avatar
正規表現の表現力って一般的なパーサのサブセットだと思うんだけど、標準ライブラリにパーサコンビネータ的なものを入れて、正規表現リテラルからそれを組み立てることで一本化するとかできないかな? (edited)
Avatar
繰り返しパターンとかのときってうまくいくんだろうか
2:45 AM
パーサコンビネータと正規表現って実装技術や理論体系が結構違うはずだから難しそう
Avatar
できたとしてもパフォーマンスが出ない?
Avatar
パーサコンビネータがParseqみたいな「Packrat Parsing」をさすならだけど。
Avatar
あとでグループから読むのは面倒だと思ってましたが直接書けるのも長くなりそうな……
Avatar
できたとしてもパフォーマンスが出ない?
とおもいます
Avatar
たとえばだけど、構文適当だけど正規表現を文字列以外に拡張して↓みたいなことができるとか。 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)人") }
Avatar
↓正式な evolution のプロセスに乗りそう。 https://github.com/apple/swift-evolution/pull/768
This proposal introduces a new DynamicMemberLookupProtocol type to the standard library. Types that conform to it provide "dot" syntax for arbitrary names which are resolved at runtime. It is usef...
Avatar
a = someValue.someMember someValue.someMember = a mutateParameter(&someValue.someMember) a = someValue[dynamicMember: "someMember"] someValue[dynamicMember: "someMember"] = a mutateParameter(&someValue[dynamicMember: "someMember"]) (edited)
7:15 AM
この変換って、 Swift のメンバーとしてパースできないものは使えない?
7:16 AM
たとえば、 Ruby の a = [2, 3, 5] a.empty? とか。
Avatar
subscript(dynamicMember:) 内で適宜書き換えてあげないとだめっぽいですね。 (edited)
Avatar
あー、↓の例がたまたま add_trick のままなだけで、 PyValsubscript で読み替える実装にすれば 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)
8:10 AM
ん??シンタックスハイライトが壊れた。
Avatar
let Dog = Python.import(DogModule.Dog")
👍 1
Avatar
そういえばこの " のコピペ問題、 @rintaro さんとハッカソンやったときに多発してた気がする。
Avatar
Appleの提供する最強のうんち仕様が一、「スマート引用符」ですよ
9:03 AM
何もスマートじゃない
9:03 AM
Preferences -> Keyboard -> Text -> Use smart quotes and dashesをDisableでOk
🙏 1
9:03 AM
でもこれアプリごとにゾンビみたいに復活して苦しめられる記憶があります
Avatar
“□” U+201C (8220) , U+201D (8221)
9:05 AM
Swiftコンパイラなら201Cと201Dの検出機能が入ってるからダイジョーブ😇
9:06 AM
逆にこの設定で全部""にしたほうが安全では??
9:06 AM
おお
9:06 AM
いける、いけるぞ!!
Avatar
コピペで多発したのは SOFT HYPHEN(U+00AD) かな? https://github.com/swift-script/swift-script/pull/18 Apple のドキュメントをコピペすると入ってる時がある。
Avatar
あー、 soft hyphen でしたね。
9:09 AM
soft hyphen も凶悪だ・・・。
Avatar
もしかして 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)
8:02 AM
subscript は元々ジェネリックじゃなかったけど、ジェネリックになったときに対応忘れたとか? (edited)
Avatar
_ つきだから、 stdlib で使用する要求が無いと実装されないかもしれないですね。
Avatar
なるほど。
Avatar
https://github.com/apple/swift/blob/603e5359fd534117c452adeccf10d04624ddab70/include/swift/AST/Attr.def#L172-L174 ここに OnSubscript を足せばそのエラーの先には行けます。
swift - The Swift Programming Language
Avatar
おお、そんな形で管理されてるんですね。
9:19 AM
前に話してた cross module specialization ってどうなったんでしたっけ?
9:19 AM
結局 Proposal にならず??
Avatar
最近追えてないっす。
Avatar
スレッドチェックしたら 10/8 で止まってますね・・・
9:24 AM
@_specialize と言えば、昨日過去最多の @_specialize をつけました・・・。 https://github.com/koher/EasyImagy/blob/dev-0.4.0/Sources/EasyImagy/ImageSpecialized.swift#L2-L677
EasyImagy - Makes it easy to deal with images in Swift
👀 1
Avatar
やべえw
Avatar
世界中探してもこんなに @_specialize の付いてるコードは見つけられないかもしれないw
Avatar
Numeric一通り対応するだけで組み合わせるとすごい数になりますからね 早くクロスモジュール最適化が欲しい
Avatar
そのNumericが RGBA で倍増して、それを組み合わせたのでこんなことに・・・。 (edited)
9:29 AM
早くクロスモジュール最適化が欲しい
それが 10/8 でスレ止まってるし、 Proposal も出てないっぽいです。
Avatar
前のメールは正規のやつじゃなくて意見募集だったから、今提案をまとめてるのだろうか
Avatar
スレッドの最後で Chris Lattner と Joe Groff がやりとりしてるっぽかった。
9:31 AM
伸びすぎてて中身はチェックしてません。
Avatar
cross module specialization で提案されている @inlineable って @_inlineable として既に実装されているような?
Avatar
そんな雰囲気でしたよ
10:12 AM
_ を外して正規仕様にするために提案を整理してるけど内容は現状あるやつ
10:12 AM
みたいな感じで。
10:13 AM
あと private なメソッドでも インライン化したい件については、 @inlineable ではできないけど、現状 @_versioned でできてるから、これは別の提案で出す、とか。
10:13 AM
こっちは @_versioned はわかりにくいから別の名前が良いって意見があった
Avatar
@_inlineable も最初 @_fragile だった。いずれにしてもパッとは分からないですねー。
Avatar
Conditional conformances aren't quite ready yet for Swift 4.1, so introduce the flag -enable-experimental-conditional-conformances to enable conditional conformaces, and an error when one declares ...
Avatar
グエー
Avatar
😲
Avatar
でもまあフラグ指定で使えるのであれば……
Avatar
ちょっと小難しいことやると壊れそう
Avatar
やはり
Avatar
↓こんなの見つけた。バグでは? 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
Avatar
Kishikawa Katsumi 11/29/2017 7:36 AM
Segmentation faultは明らかにバグですね
Avatar
ですよね。
Avatar
コードがオモロイ
Avatar
本当だ
Avatar
4.1 で直るはず。チョット待ってくださいね。
Avatar
おお、そうなんですね。
7:39 AM
4.1 ということは春か。それまでクロージャ式でラップするか。
Avatar
subscriptもそういう使い方できるんだ…
7:41 AM
subscriptもそういう使い方できるんだ…
いいえ。できないです。 master だと error: value of type '[Int]' has no member 'subscript' let f: (Int) -> Int = a.subscript ^ ~~~~~~~~~
Avatar
ああ。
7:41 AM
本来はコンパイルエラーになるべきということですね。
Avatar
@rintaro さんが 1 年以上前に通ってた・・・。 Rintaro Ishizaki added a comment - 15 Sep 2016 4:51 AM Minimum repro: class C { subscript(x: Int) -> Void { return } } _ = C().subscript
7:42 AM
subscript のリファレンスを取る方法は封じられたんでしたっけ? (edited)
7:42 AM
しかも、さっき検索したリストの下の方にこのバグレポート出てた。検索力が足りない😂
Avatar
知ってる限り、 subscript のリファレンスは取れないですねー。
Avatar
ありがとうございます〜🙇
Avatar
class C { subscript(x: Int) -> Void { print(x) } } let idx = 12 let kp = \C.[idx] C()[keyPath: kp] keypath はインデックス固定のリファレンスと見れなくもないか? やりたいこと逆ですがw
Avatar
今、 (Int) -> Element として高階関数に渡したいので😅
Avatar
おーマージされたね https://github.com/apple/swift/pull/13273
This pr is improvement of comment. Seems SomeEnumWithAssociatedValues implements require result initial value.
👍 2
🎉 10
✌ 1
Avatar
omochimetaru 12/6/2017 6:26 AM
6:28 AM
Streamが長いと購読解除のスタックトレースが深い・・・
Avatar
それはもう必然やね
Avatar
omochimetaru 12/6/2017 6:44 AM
テーブルビューのセルがリサイクルされるときに
6:44 AM
セルとモデルはflatMapLatestの内部で古い方を解除して新しい方を接続するんだけど
6:44 AM
そこで時々プチフリーズしていてプロファイルとったら↑が出てきた
Avatar
Type-erasureに再帰的に詰めてるところ、ズルはできないかな?
Avatar
omochimetaru 12/6/2017 8:18 AM
継承にしたら1段減らせると思ったんだけど
Avatar
例えばRxSwiftではObservable.mapはちょっとだけズルをしていて、Map.mapがズルい実装になっています
Avatar
omochimetaru 12/6/2017 8:18 AM
そうすると init で別の実装を差し込むことができなくて、例の技を使う必要が出てくるんだけど
8:19 AM
一般のサブクラスでDog漏れが生じて終わった
Avatar
そこでclass + convertible protocolですよ
Avatar
omochimetaru 12/6/2017 8:19 AM
RxSwiftのずるってどういうズル?
8:19 AM
イレイジャーの中にあるbaseを触るとか?
8:20 AM
RxSwiftのObservableはまさに、class + convertible protocolの作りになっていて
8:20 AM
ユーザーランドではsubclassを作れない、代わりにconvertible protocolが使える
Avatar
omochimetaru 12/6/2017 8:20 AM
なんだこれは、mapオペレータの内臓を取り出してる?
Avatar
えっと、mapの実態はcomposeMapなんだけど
8:21 AM
Mapはそれをオーバーライドしていて不要なスタックが増えるのを防いでいる
Avatar
omochimetaru 12/6/2017 8:21 AM
ほんとだ override だ
Avatar
Disposableのスタックが増えて困るなら、そうだね
8:22 AM
DisposableとDisposableConvertibleを作って
8:22 AM
public class Disposable: DisposableConvertibleにしてユーザー側ではサブクラス作れないようにする (edited)
8:22 AM
オレオレ作りたい人はDisposableConvertibleを使う、とやると解決しそう
8:25 AM
これとか、 Disposables.create になっているけど、
8:25 AM
これを Disposable.init() にしたかったんだよね
Avatar
うむ
Avatar
omochimetaru 12/6/2017 8:25 AM
(複数形じゃなくて本体の名前で、かつ、init)
Avatar
RxSwiftはクラスクラスタではないからDisposablesというUtilを使っているね
8:26 AM
Disposables、JavaにおけるArraysみたいな感じで複数系ではなくUtilクラスの意味だとおも
8:26 AM
Lists?なんかsのつくUtilあったよね
Avatar
omochimetaru 12/6/2017 8:26 AM
いろいろあるね
8:27 AM
// 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) }
Avatar
omochimetaru 12/6/2017 8:28 AM
この _map ってどこに定義されてるんだ?
Avatar
omochimetaru 12/6/2017 8:29 AM
なるほど
8:29 AM
つまり、 map オペレータに関しては
8:30 AM
一般のObservable を扱う実装じゃなくて、一般のやつはObservable で実装してあって、一部のサブクラスではオーバライドして最適化してる?
Avatar
一部というかMapだけ
8:32 AM
public class Disposable { public init() { // ここはクラスクラスタ } } private class CompositeDisposable: Disposable {} // ... その他諸々 protocol DisposableConvertible { var asDisposable: Disposable { get } } public extension Disposable: DisposableConvertible { var asDisposable: Disposable { return self } }
Avatar
omochimetaru 12/6/2017 8:33 AM
その場合さ、CompositeDisposableを使いたいユーザーはどうしたらいいかな
Avatar
こうするとユーザが拡張Disposable作るときはDisposableConvertibleを使って実装することになる。 基本的にはDisposableConvertibleでやり取りしていればおk
8:34 AM
Disposableのinitのパターンを増やす
Avatar
omochimetaru 12/6/2017 8:34 AM
Compositeの場合は一個ずつaddとかがやりたい場合がある
Avatar
後から追加する場合か
8:35 AM
うーん、まあクラスタのメンバーは必ずしもprivateじゃなくていいんじゃない?
8:35 AM
必要に応じて見えてていいと思う
Avatar
omochimetaru 12/6/2017 8:35 AM
いやそうすると
8:35 AM
CompositeDisposable.init() // NopDisposable用のfactory init
8:35 AM
CatにみえるDog問題が出てくる
Avatar
overrideしてunavailableつけれない?
Avatar
omochimetaru 12/6/2017 8:35 AM
その手があったか
Avatar
兎角Disposableをopenにしなければなんとかなるはず
Avatar
omochimetaru 12/6/2017 8:38 AM
RxSwiftのObservableConvertibleTypeって
8:38 AM
実装は各自でやって、ってなっていて
8:39 AM
ObservableType : ObservableConvertibleType は、実装をもっていたけど
8:39 AM
ObservableTypeとObservableConvertibleTypeに分けておく嬉しさはどこにあるん
Avatar
そこは俺は知らない
Avatar
omochimetaru 12/6/2017 8:40 AM
なるほど
Avatar
ObservableTypeとObservableConvertibleType、型パラの指定で使い方が違うから
Avatar
omochimetaru 12/6/2017 8:40 AM
今の自分の設計だと、 protocol DisposerProtocolとclass Disposerがあって、Disposerは init<X: DisposerProtocol>(_ base: X) なイレイジャーにしてあって、 DisposerProtocol は extension で asDisposer() -> Disposer を持たせていて
Avatar
そうすると無限にスタックが積まれるね
Avatar
omochimetaru 12/6/2017 8:41 AM
一般にこの XxxProtocolと Erasure用の Xxx の2つがあればいけそうにおもうんだけど
8:42 AM
うん。あーそこがうまいことできるのか?
8:42 AM
いや、Disposer自身の asDisposer() は return self だから、真の型が Disposerの時はそこで止まるけどね
Avatar
Erasureだけだと、Erasureが多重化するパターンがしんどいから
Avatar
omochimetaru 12/6/2017 8:42 AM
静的に見えてる場合だけだけど。
Avatar
あれ、そこはうまくいってるのか
8:42 AM
動的にそこが解決できるとスタックネストしないように出来ないかな
8:43 AM
動的にする最短ルートがクラスクラスタの気もするけど
Avatar
omochimetaru 12/6/2017 8:43 AM
プロパティとかではDisposer で保持して 引数では DisposerProtocol で受けてるから保持する直前には真の型が見えててうまくいく (edited)
8:45 AM
8:45 AM
Convertible自分でもやってたわ、EventSinkProtocolとEventSinkConvertibleを作っていた
8:45 AM
Convertibleは メソッド名を固定してないんだ。
8:46 AM
ああ、RxSwiftのObservableも同じっぽい
8:46 AM
ObservableType は subscribe が生えてるから、 subscribe メソッドをラップして Observable に erase する動作がデフォルト提供されてるけど
Avatar
ああ、そうだね
8:47 AM
それはそうなんだけど、僕はそれが別れていて何が嬉しいのかがよくわかってない
8:47 AM
間の型の必要性が良くわかってないな
8:47 AM
classとconvertibleだけでいけるのでは?と思っている
Avatar
omochimetaru 12/6/2017 8:48 AM
ObservableConvertibleType は subscribe じゃないメソッドで Obserbable化したい場合にそなえてrんだ
8:48 AM
ああ、そっちか。
8:48 AM
それは、ユーザーが、継承じゃない形で ObservableType を実装できるようになってるんじゃないか
8:49 AM
ああ、その場合もConvertibleでいけばいいってことね
Avatar
そう
Avatar
omochimetaru 12/6/2017 8:49 AM
まあsubscribeメソッドが補間で出てくるから少し温かいのでは・・・
8:49 AM
Convertibleはsubscribeメソッドの概念は持ってないから。
Avatar
いやでも
8:49 AM
あーーー
8:49 AM
理解した
8:50 AM
各種オペレーターはObservableTypeに生えてるので
8:50 AM
ObservableTypeなら使えるわけだ
8:50 AM
オケオケ
Avatar
omochimetaru 12/6/2017 8:50 AM
ああ
8:50 AM
Convertibleはまだそれではないから結構使い勝手が違うのか
Avatar
あるメソッドを前提として色々functionが生える場合には
8:51 AM
分ける価値があるね、そうじゃなければ特に無い
Avatar
omochimetaru 12/6/2017 8:51 AM
なるほど。
8:52 AM
Disposerには特にそういう芸は無いな
Avatar
omochimetaru 12/6/2017 9:03 AM
親クラスに designated initializerが2つある場合に、 designated initializerを1つだけoverrideした時は、サブクラスでは convenience initializerは呼び出せないのに
9:03 AM
2つ両方をoverride すると convenience initializer が使えるようになる
9:04 AM
これはまあいいとして
9:04 AM
2つ両方をoverrideしているが、convenience initailizerは 使えるようにならない 方法が無いのが
9:04 AM
例のfactory initを使っている場合に限って困る。
9:05 AM
Avatar
convenience initってoverride出来ないんだっけ
Avatar
omochimetaru 12/6/2017 9:05 AM
privateにできそう
Avatar
factory init自体はprotocolをprivateにして隠蔽できるはず
Avatar
omochimetaru 12/6/2017 9:05 AM
そこはそうだね
9:06 AM
convenience init は private にして隠すことができた
Avatar
convenience init via factoryはoverrideしてunavailableしか無いんじゃあないかな
9:06 AM
あー
9:06 AM
convenience init自体を隠蔽するのもありですね
9:06 AM
使わないなら
Avatar
omochimetaru 12/6/2017 9:06 AM
というかfactory initされるから使うとぶっ壊れる
Avatar
いや
9:07 AM
Disposableからは使いたいがサブクラス群からは使わせたくない、という話と思っていた
Avatar
omochimetaru 12/6/2017 9:07 AM
パッケージ内部はまあいいよ危険でも
9:07 AM
外部から触れなければ。
9:08 AM
あとはユーザ継承だけが問題か〜 まあそのケースはスタック伸びちゃうでいいか
Avatar
ユーザーにはConvertibleだけ触らせるでいいんじゃないのとは思うけど
9:18 AM
そうすれば一段だ
Avatar
omochimetaru 12/6/2017 9:18 AM
だね、これはそういう意図だった > そのケースはスタック伸びちゃうでいいか (edited)
Avatar
omochimetaru 12/6/2017 9:28 AM
b
9:29 AM
できた〜〜〜〜
9:29 AM
サンクス
Avatar
CompositDisposerなんとかなんないかな?w
Avatar
omochimetaru 12/6/2017 9:31 AM
そこは多分flatMapLatestとかが重なってるのでそこに専用のinner classのDisposerを作れば
9:31 AM
見えるようになりそう
Avatar
そこがスタック地獄になってるのは、解決出来ないか
Avatar
omochimetaru 12/6/2017 9:32 AM
ネスト自体は本当にロジックがそうだからなくせないと思う それはそれとしてちょっと重いのでストリームの組み方は見直すつもり
9:38 AM
なんか見つけたんだけどこれなんだろう
Avatar
self: Selfってことはインスタンスメソッドすな
Avatar
適当にオレオレクラス作ってAnyObjectにキャストするとunrecognizedで怒られる
9:41 AM
_SwiftNSRangeってなんだ
Avatar
Kishikawa Katsumi 12/7/2017 9:42 AM
名前だけ見るとNSArrayのメソッドっぽいけど。
Avatar
_NSArrayCore 🤔
Avatar
同じところ見てました
9:45 AM
nextObjectはこっちかな
Avatar
_NSArrayCore ふくめ、このファイルの型は Foundation なしの stdlib で Foundation 系の型を扱うためのもの。みたいな感じだと思ってます。 (edited)
Avatar
omochimetaru 12/8/2017 5:48 AM
関数の引数をジェネリックなプロトコルで受けると、型が決まってないからドット記法が使えない
5:49 AM
イレイジャの型で受けるとドット記法が使えるけど性能によくない
5:49 AM
って両方満たす作戦ない?
Avatar
普通のGenericsじゃあだめなの
Avatar
omochimetaru 12/8/2017 5:50 AM
普通のGenerics?
5:50 AM
func bind0<X: EventSourceProtocol>(modelStream: X) where X.Event == Model func bind1(modelStream: EventSource<Model>) (edited)
5:51 AM
bind1は bind1(modelStream: .of(3)) とか書ける事もあって便利
5:51 AM
でも逆に bind1(modelStream: Property(3).asEventSource()) 変換が必要
5:52 AM
bind0 は逆にドット記法が使えないが後者のケースでは変換が不要
Avatar
オーバーロード
Avatar
omochimetaru 12/8/2017 5:53 AM
bind0とbind1両方定義するのって安全なんだっけ。 EventSource is EventSourceProtocol だから、曖昧なんだけど
Avatar
厳しい方にマッチするはずだからambiguousは出ない気がするね
Avatar
omochimetaru 12/8/2017 5:53 AM
(実際には0と1はのぞいて両方共bindとしてオーバーロードの話)
5:56 AM
やってみます
5:57 AM
いけるっぽい。
5:58 AM
ありがとう
5:58 AM
これ今だとprotocolにはstatic funcが定義できないから
5:58 AM
大丈夫だけど、それもできるばあい
5:58 AM
EventSourceProtocol.ofEventSource.of が曖昧になりそうだ .of() だけ書いてある場合 (edited)
Avatar
いや
5:59 AM
それでもGenerics側はProtocolが何なのかを解釈出来ないからマッチしない
5:59 AM
一意に決まります
5:59 AM
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)
Avatar
omochimetaru 12/8/2017 5:59 AM
あーそういう順番なのか
Avatar
protocolにはstatic funcが定義できない
ん?
Avatar
omochimetaru 12/8/2017 6:01 AM
@rintaro static func を持つという制約は書けるけど
Avatar
それはおもちprotocolはと解釈した
Avatar
omochimetaru 12/8/2017 6:01 AM
プロトコル名をネームスペースとして定義するstatic funcが書けない
6:03 AM
protocol AnimalProtocol { static func makeNya() -> Cat } ↑は Cat.makeNya() や Dog.makeNya() が呼べる事を示す定義であって、 AnimalProtocol.makeNya() という式で呼べる関数を定義するわけじゃないからいいけど
6:04 AM
protocol をネームスペースとして protocol 宣言の内側に inner class や inner struct を定義したいって話題をたまに見かけるので
6:04 AM
んーまあだから関数は記法がもう消費されてるからありえないけど
6:05 AM
もしprotocolのinner classなどのネームスペース的な記述ができるようにもしなったときは、 ↑のbind0とbind1のオーバーロードに対して ドット記法があると曖昧になりそうという事
Avatar
なるほど。
Avatar
protocol AnimalProtocol {} class Cat : AnimalProtocol {} extension AnimalProtocol { static func makeNya() -> Cat { return Cat() } } こういう話ではなくて?
6:20 AM
ああ、AnimalProtocol.makeNya() で呼べないということですね。 (edited)
Avatar
omochimetaru 12/8/2017 6:24 AM
はい。まあ現状の仕組みからすると呼べたら意味不明ですけど。
Avatar
お~~
Avatar
Swift で浮動小数点数使うときって Float 使いますか? Double 使いますか? Java だと double が普通だと思うんですが。
Avatar
Double ですかね?そもそも指定がなかったらデフォルトで Double 使われますし…
Avatar
確かにデフォルトそうですね。
Avatar
Floatにしてた。
Avatar
標準ライブラリの API で、一般的な小数と取りたい部分で、 Double のみ(もしくは Float のみ)の API ってありますっけ?
Avatar
いきなり意見が割れた 😇
Avatar
浮動小数周りの命令って32と64だと32bitのほうがパイプライン効率とかCPU上で2倍になりそう、計測はしたことないけど
Avatar
Floatabs がないっぽい?
3:10 AM
1> let a: Float = -3.14 a: Float = -3.1400001 2> abs(a) $R0: Float = 3.1400001
Avatar
FloatとDouble両方のページ開いて var func init( で数検索して見たけど func だけFloatが1個少なくて軽く見て見たらFloatのページにだけ abs がなかったけどドキュメント作った人のせいか
Avatar
CoreGraphics とかは浮動小数点数いっぱいでて来るんですが、標準ライブラリじゃないし、みんな CGFloat なんですよねぇ。
Avatar
CGFloat は標準ライブラリーで使えなかったっけ?
Avatar
let a = 0.12 print(type(of: a)) // Double
3:13 AM
デフォルトDoubleなのは今知った
Avatar
あほんとだ使えない
Avatar
Java の HashMaploadFactor みたいなのないかと思ったけど、 https://docs.oracle.com/javase/jp/9/docs/api/java/util/HashMap.html#HashMap-int-float-
3:15 AM
Swift の Dictionary にはなかった・・・。 https://developer.apple.com/documentation/swift/dictionary
Avatar
HashMapの負荷係数としてはDoubleは過剰とかあると思うので
3:15 AM
用途次第だと思います
Avatar
Java でも float だしね。
Avatar
かと言ってそもそも今の処理系はみんな64bitになってるので、32bit使っても64bit使ってもパフォーマンスに影響はないと思うんですよね…メモリは4バイト分の節約にはなりますが
Avatar
↓ここからして https://developer.apple.com/documentation/swift
Fundamental data types such as Int, Double, and String
だし、 Double を優先して使うのがいいのかな。
Avatar
32bit使っても64bit使ってもパフォーマンスに影響はないと思うんですよね
64bitマシンで32bitFloatを64bitレジスタに2個詰めていっぺんに計算したりとかできないんかな
3:18 AM
armのSIMD命令とかもどうなんだろう
Avatar
むしろ 64 bit アーキテクチャだと 32 bit の Float を 64 bit に変換し直すから遅いという話を聴いた気がするし、実際 iOS で Float から Double に変えたら速くなったことが
3:19 AM
パッキングしてくれない
Avatar
64bitマシンで32bitFloatを64bitレジスタに2個詰めていっぺんに計算したりとかできないんかな
多分ないんじゃないかと 🤔 それができたら char が一遍に8バイト処理できる計算になるけどそんな話聞いたことないですね(聞いたことないだけかもしれないが
Avatar
x86_64 だとどうなんだろう…
Avatar
x86_64でも今普通double使いますね
Avatar
そうですね
Avatar
少なくともC言語入門の授業では「よっぽどのことがない限りfloatよりdouble使え」と教えられますた
Avatar
なんで今まで Float 優先で使ってたんだろうと考えてみたけど、
3:23 AM
昔の iOS アプリ開発が 32bit だったのと、
3:24 AM
(おそらくそれに引きづられて)↓のような API が Float になっていることが
Avatar
https://developer.arm.com/technologies/neon 8x16-bit*, 4x32-bit, 2x64-bit** floating-point operations
NEON is a SIMD architecture extension for the Arm Cortex-A series and Cortex-R52 processors.
Avatar
関係してる気がしてきた。
Avatar
うーんやっぱ専用レジスタのサイズの関係でビット数が小さい方がいっぺんに処理できるベクトルの要素数が増えると思うんだけどな
3:24 AM
一般のプログラムをコンパイラがベクトル命令に最適化するのかどうかっていう問題はあるけど (edited)
Avatar
UITouch の分解能ってどれくらいなんだろう? (edited)
Avatar
ベクトル命令自体はCoreGraphicsのMatrixとかは明示的に組み込まれてたし。 (edited)
Avatar
UITouch の分解能が低いなら Float でも合理的か。
3:26 AM
でも Swift だと型変換するの面倒かも?
3:28 AM
gccだと-marchでSIMD(Neon)狙ってくれ みたいなオプションあったりする
Avatar
@omochimetaru CoreGraphics は CGFloat だから、 64bit 環境では 64bit 浮動小数点数になってると思う。
Avatar
@koher あ、CoreGraphicsじゃなくて、GLKitのGLKMatrix4x4だ
Avatar
GL は特殊ケースじゃない? (edited)
3:32 AM
頂点配列とかも、演算速度優先で Float とか普通かと。
Avatar
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;
3:36 AM
GLKitの場合はシェーダーに飛ばした後の精度がどうせ32bitしか無いっていう別の理由もあると思うけど、 それはそれとして、CPU側で行列演算する必要もあるので、専用命令を使った場合に32bitのほうが早いっていうのも理由に含まれていると思う
3:37 AM
ベクトル命令じゃなくて普通の単体の命令の場合は32bitから64bitへの昇格/降格が挟まって遅くなるってこともありえると思うけど
3:37 AM
一方で(現在のSwiftコンパイラ/LLVMバックエンドがサポートしてるかは別として) GCCとかで通常のコードからなるべくベクトル命令を吐くっていうコンパイラ最適化は実在する技術だから
3:38 AM
それを見据えて期待してFloatにしておくと良いのでは、ってのが考えです
3:38 AM
頂点配列とか要素数が多くなってきた場合にはキャッシュサイズの影響が大きくなってきそうという別のメリットもあるけど、今の議題はなんかそういう場合では無さそう
Avatar
今知りたいのは、一般的に FloatDouble のどちらが使われてるのかということですね。
3:40 AM
もちろん、適材適所はあるけど、もっとざっくりと、小数を作りたいと思ったときに Swift ではどちらを使うのが一般的なのかと。
Avatar
暗黙的な処理としては let a = 0.12 の場合 aDouble なので Double の方が一般的かと思いますね 🤔
Avatar
そんな気がしてきました。自分がなんで Float 使ってたのかを考えると、昔の iOS アプリ開発から惰性でそうしてるだけな気がしてきました。 (edited)
Avatar
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 これ好き
4:21 AM
CGFloatおまえFloatちゃうやんけ!っていう
Avatar
型としての Float ではなく字面の意味通りのFloatだから(震え声
Avatar
public typealias Float64 = Doubleなのでセーフ
Avatar
FloatDouble って名前に統一感ないですよね。せめて SingleDouble にするか、 Float32Float64 にするかしてほしい。 Swift が悪いわけじゃないけど。
Avatar
Float80あるしFloat64でいいと思うんですよね
Avatar
IntだってInt64あるし
Avatar
個人的には、 Float32Float64 作って、 Int みたいな位置の Float ほしい。
Avatar
ObjectPascalならSingleだよ
Avatar
Int みたいな位置の Float ほしい。
BLASとか使うのめちゃくちゃめんどくさくなりそう
Avatar
型名にも技術的負債が…
Avatar
typealias あったのか・・・
4:45 AM
@t.ae それはそうだけど、そこは仕方ない気も。
Avatar
今もUnsafe*Pointer<Int32>受ける関数とかありますけどね。 そもそもIntのサイズがネイティブに依存するメリットがいまいち分かっていないです。
Avatar
一般的なコードで整数を扱いたいときにそれが Int32 だろうが Int64 だろうが成り立つことがほとんどで、
4:50 AM
32 bit 環境と 64 bit 環境でコードを共通化できないのは辛くない?
Avatar
僕もInt固定が良い派
4:50 AM
Int32って書いとけば共通化はできますよ
4:50 AM
むしろマシンによって挙動が変わりうるのが怖い
4:51 AM
掛け算のオーバーフローとか桁数半分の2乗でいくので稀に怖いです
4:51 AM
ふだんは64で作ってて32環境だけでエンバグする怖さですね
Avatar
Int って書いてるときはオーバーフローは Logic failure だし、バイト数で壊れるようなコードはそもそも Int で書いちゃいけないかと。 (edited)
4:53 AM
単純に現実的な範囲で N までをサポートする型として使って、その N が環境によって異なるだけ。
Avatar
壊れると思ってるときは書かないからよくて、
4:53 AM
うっかり使ってしまうリスクですね
4:54 AM
エンバグ条件もかなりレアになるから潜伏しやすい
Avatar
Int32 って書いたコードは未来に Int128 が当たり前になった世界でも Int32 のままになっちゃうよ。
Avatar
自分もそういうシビアな「絶対この桁数じゃないとダメ」のようなシチュエーション比較的にそんなに一般的ではない気がするので、そのような場合に Int64 とか Int32 使って、普通の環境は Int でよしなりにプラットフォームに合わせて使わせてくれる方が嬉しいかな派ですね
Avatar
なるべくどこでも同じ動きの方がよくないですか?なんでも
Avatar
テーブルのセル数とか Int32 でも Int64 でも変わらないでしょう派()
Avatar
テストのときに Int が色々なビット数で動いてくれるとうれしいとは思う。
Avatar
むしろテーブルのセル数が Int32 で足りないシチュエーションって相当レアですよね…
Avatar
そういう値は128ビットの時代になったからといって32のままで大丈夫ですね
Avatar
Java とか int が 32 bit 固定だけど、今の 64 bit 当たり前の時代でも 32 bit に縛られちゃってるのでは?
Avatar
マシンの進化に合わせて大きくなるのが嬉しいって場面があまり思い当たらない
4:58 AM
今さら標準ライブラリのほとんどの箇所で intlong にするとか無理では。
4:58 AM
しかも、過去に書かれたコードが「整数」を使いたいのか「32ビット整数」を使いたいのか区別されてないから (edited)
4:59 AM
コンバートしようとしてもできない。「32ビット整数」のつもりの箇所はぶっ壊れる。
4:59 AM
つまり、永久に32ビット整数を使い続けるか、古いコードをすべて捨てて新しい世界に行くかしかない。
Avatar
配列の要素数に関してはcppのstd::size_tが筋が良いとは思います
5:02 AM
これはポインタで表せる空間サイズに対応した型で
5:02 AM
たとえ128ビットのintのマシンでも
5:02 AM
メモリアドレスが64ビットなら、
5:02 AM
128ビットのインデックスに意味がないからです
5:03 AM
SwiftのIntも、ネイティブのポインタサイズの整数として
5:03 AM
定義されているんで、配列についてはそれで良いかも
Avatar
Kishikawa Katsumi 12/12/2017 5:03 AM
古いコードをすべて捨てて新しい世界に行くかしかない。
Avatar
アーキテクチャによってはポインタサイズとIntサイズを区別することもあって
Avatar
Kishikawa Katsumi 12/12/2017 5:03 AM
新しい世界は数年ごとに来るからそれで良いかも
Avatar
それはまた話がかわりそう
Avatar
Kishikawa Katsumi 12/12/2017 5:04 AM
数年前は64ビットサイズのIntとかなかった。
Avatar
@omochimetaru List を出したのは例であって、一般的に整数の意味合いで使われてる int がずっと 32 bit のままが辛いということです。
5:05 AM
@Kishikawa Katsumi うーん、でも Java はもう int が 32 ビットのまま変わらず 20 年使われてますよ。
Avatar
「一般的な整数」っていうのがあるのかなあと思います 純粋な整数計算アルゴリズムとかはそういうのいると思うけど、それはむしろ無限精度整数の方が良いと思うし。
5:06 AM
ちゃんとつきつめていけば、人間がUIで見通せる要素数、とか、メモリサイズに関連づけされた数、とか
5:06 AM
サイズ要件がだいたいはちゃんとあると思うんですよ
Avatar
Kishikawa Katsumi 12/12/2017 5:07 AM
^ Javaがそういう選択をしたというのはそれはそれで私は尊重したいと思います。ただいずれ32は無くなって、64or何かみたいなことは起こるので、そのときにより良い選択ができるようにこういう議論はしておいたらいいのかと思いますね 😃 (edited)
Avatar
@omochimetaru それで UITableView のセルの数&インデックスは Int32 だけど Array の要素数&インデックスは Int64 で境界で全部明示的変換が必要ですとか辛くないですか?
5:11 AM
あと、↑のポインタサイズの話は ArrayList 的なものを想定してると思うけど、 LinkedList とかを考えると話が変わってくるのでは? List は一般的なインタフェースだし。
Avatar
1要素が1バイトはあるので
5:11 AM
ポインタ表現幅を超えることはないのでは
5:11 AM
あ、ファイルストレージとかと連動するならありえますね それはもう別の型が良さそうだけど。
5:12 AM
うーん、Int32とInt64の都度変換ですが、cppで厳密にやるとそうなるんですけど、
Avatar
イミュータブルな List が動的に要素を計算するとかあり得るのでは?( List のアップデート系のメソッドはオプションのはず)
Avatar
僕は個別にToInt全部包むようにして
5:12 AM
そこで溢れチェックささるようにしたら
5:13 AM
安心感あって良かったですよ
Avatar
それって何も考えずに境界でキャストしまくるだけになって結局壊れないかなぁ。
Avatar
このばあいだとサイズの最大値が理由ともに片付けされているので
5:15 AM
クラッシュするときっていうのはなんらかの問題でその要素数などの仮定がぶっこわれたということなので
5:15 AM
そのキャストのところで落ちる方が
5:16 AM
問題の検出がはやくなっていて良いと思う
Avatar
@Kishikawa Katsumi Java やってた頃は固定されてる安心感があったんですが、いざ 64 bit への移行の世界を経験して、これからどうするんだろう?と思いますね〜🤔 最近の Java 事情詳しくないですが。
5:17 AM
@omochimetaru 脳内で一般的整数として扱ってるもの同士でやりとりするためにいちいちキャストが必要というのはちょっと許容しかねる気が。
5:19 AM
@omochimetaru バイト列として扱ったりするときは当然 Int から Int32 とかに変換するわけで、その境界で気付くんじゃないかな?普段は Int として扱っていて、ビット数を気にする処理をする際に IntXX に変換で十分だと思うけどなぁ。
Avatar
いや、前提が逆ですね、「一般的整数」として脳内の認識が緩まってしまうことで、
Avatar
Kishikawa Katsumi 12/12/2017 5:19 AM
私も詳しくはなくて互換性を重視したか、急な変化を避けたんだと思うんですけど、Swiftもいずれそういう選択は来るんだろうなと。今は標準APIを全部変える選択はまあ無いけど、その時にはありかも。
Avatar
64bitでは動くが32bitではおかしくなる、というバグを生みうることを懸念しているので
5:19 AM
それは脳内の認識が最初からゆるいのでちゃんと決めたほうがいいってアイデアです
5:21 AM
バイナリ操作の話はまた別かなと思います 64bitの時代になったからといってIntに42億を超える値を入れるシチュエーションそうそう無いはずで、 むしろなんらかのバグで計算が狂って入っちゃった(でも64bitだから動いてしまう)っていう事の方が多そう
5:22 AM
ちなみに新しい言語だとRustが具体的サイズ主義ですね (edited)
Avatar
うーん、整数という概念で用いているものに対して、これは Int32 とか Int64 とか色分けするのは変だと思うし、それが 32 ビット(に限らない XX ビット)に取り残される原因を生むと思う。
5:25 AM
Intに42億を超える値を入れるシチュエーションそうそう無い
そうそうないだけであり得て、 Facebook がユーザー 21 億超えたら(古の 32 ビットに引きずられて)それまでのコードが動かなくなりましたとか辛い気が。
Avatar
世界人口が2^32超えてるからユーザーIDはInt64がいいんじゃないですかね
5:26 AM
それこそ雑に Int をいつもつかう文化だったからやってしまう間違いな気がする
Avatar
でも Java のコレクションの sizeint なんです。
Avatar
いつも32と64気にしてればそこで回避できないか
Avatar
そして、それは Java が作られたときにはリーズナブルだったわけで
Avatar
コレクションのサイズはポインタサイズが良いと思いますよ
5:28 AM
Javaより先にC++がそうしていたので
5:28 AM
昔だったから思いつけなかったって話ではないはず
Avatar
いや、なのでコレクションのサイズは一例であって
Avatar
Javaには「ポインタサイズ」の概念が無いから
5:28 AM
マシンのメモリサイズを見据えた物の考え方がないのかと
Avatar
ありとあらゆる整数サイズが 32 ビットに固定されてるのが Java の世界で
Avatar
個別の間違いは個別の間違いだから
5:29 AM
都度都度なおしていきましょうで良いと思う
5:29 AM
フワッとしておけば後々伸ばせる、みたいな考え方は混乱をウムと思います
Avatar
Java の標準ライブラリの int を全部 long にしましょうとか無茶でしょ?
Avatar
そうかな
5:30 AM
Swiftだったら
5:30 AM
その程度の破壊的変更はやってますよ (edited)
5:30 AM
Javaの人たちはそういう点で保守的というだけで・・・
Avatar
Swift はまだ実用の範囲が狭いからね。
5:30 AM
それをやってるから本格的に採用できないということもある。
Avatar
逆説的に言うとその手の破壊的変更がある限りSSSは普及しない
Avatar
Java 1X からは int を 64 ビットにします(もしくは int で書かれてた API の大部分を long にします)とかやったら世界崩壊しそうな気が。 (edited)
Avatar
うーむ・・・ Java.util.とは別に java10.util.ArrayList とか用意して移行していくのはどうですかねえ
5:32 AM
SwiftのSSSも同じで。
5:33 AM
時代に合わせて新しい標準ライブラリを作る、古い実装を動かしたい人はそのまま動かす、
5:33 AM
時代に合わせてパフォーマンスやスケールを伸ばしたい人は書き換える。
Avatar
Kishikawa Katsumi 12/12/2017 5:34 AM
私はそういう大きな移行を促進するのはある程度パワープレイが必要だと思いますね。それか明確なメリットがあるか。
Avatar
Date を新しい API にするだけでも大変そうだったのに https://qiita.com/tag1216/items/91a471b33f383981bfaa java.util をまるっと置き換えますとか地獄絵図な気が。
Javaで日付/時間を扱うには従来はDate/Calendar/DateFormat等のクラスを使っていたが(以下、旧API)、Java8からはjava.timeパッケージに新しくAPIが追加された(以下、新API)。 しかし新AP...
Avatar
えっと、ライブラリの移行は仮定の話しで、 僕の意見としては、Int32, Int64, IntPtr に関してはその3つをちゃんと考えて決めておけば、そもそも将来的に移行したくならないと思う、です。
Avatar
パフォーマンスの問題もないかな? 64 ビットに変換してから計算されたりしない?
Avatar
浮動小数と違ってその昇格が実質クロック遅延無しでできそう
5:41 AM
ビット線を併合してゼロ埋めするだけだから
5:42 AM
うーんでもそれは浮動小数も一緒か・・・? そこは知らないです (edited)
5:43 AM
ただ回路的には小さいから、仮に昇格コストがでかいとしたら、32bit演算機も搭載しておけばいいんじゃないかって気はしますけど
Avatar
将来的に移行したくならない
これがそうじゃない気がして、想定できないだけでそういうケースがぽこぽこ出て来ると思う。
Avatar
まあ、それ自体はIntに限った話しじゃなくて
5:44 AM
Unicode絵文字みたいに世界の事情が変わっちゃって、とかはままありますね
Avatar
Int はプリミティブすぎて影響範囲が他よりめちゃくちゃ大きいんじゃないかなぁ。
Avatar
それが無いと思うんですよね、実際に 2^32より大きい値をIntに自然に入れるのをみたことがないから。 明示的にInt64な有理数(分母と分子のタプル)時刻型とか、さっきの大規模サービスのIDとか、事前に想定されたシチュエーションぐらいです。
Avatar
大きなお金とか
Avatar
「普通の整数」としてIntが使われていて、64bit環境において、そこに42億以上の値を入れた
5:46 AM
って場面を見たことがないと思います
Avatar
ディスク容量とか
Avatar
お金も普通お金型使いますよ
5:46 AM
少数桁の税率計算とかでいろいろと面倒があるので
Avatar
普通お金型つかいますよが全然できてないJava屋さんはいっぱいいそう
Avatar
いや、さすがに居ないと思う・・・
5:47 AM
Java屋さんお金型使うプロでしょ・・・
Avatar
お金の例はルールと密接に絡んでるから特殊だったとしても
Avatar
ディスク容量は確かに難しいですね
5:48 AM
予想を超える爆発的増加がありえそう。
Avatar
32 bit の世界では仕方なく諦めて long を使ってたものが、 64 bit の世界では普通にとりあえ使えるようになってるのに、古い仕様にひきずられて永久に面倒な取り扱いを強要されるの辛そう。 (edited)
Avatar
実際 fseek はそんな事になってますね
5:51 AM
long なんだけど long が32bitの環境があるので64bit用のオーバーロードがOSによってはオリジナルで提供されている
5:51 AM
ただこれはこれで逆に示唆的で、 long っていう抽象的な型だったのに
5:51 AM
互換性のために32bit固定されちゃって
5:51 AM
longの柔軟性が将来的に発動できなかったんですけど・・・ (edited)
Avatar
あ、↑の long は Java の64 bit 整数の意図ね。
5:52 AM
互換性のために32bit固定されちゃって
うーん、これは将来的に起こらないように Swift では注意深く進めていくしかないんだろうけど
5:52 AM
今の Swift なら簡単だけど、広く使われてたら難しいかもしれないなぁ。
Avatar
ちなみに今の例にでてきたlongが32なのはバイナリ互換おばけのwindowsさんです
5:54 AM
同じような話しが C++ の char型にもあって、 charは「1バイト以上」って定義だったんですけど、 みんなが1バイトと仮定したコードを書きすぎて駄目になった
5:54 AM
それで近年になって char8_t を明示的に追加しようぜって話がでてきた。
5:55 AM
現実的な課題としてはそっちの方向のほうが難しい気がしてきました
Avatar
それはバイト型がなかったのが問題で、別の話な気がする。
Avatar
wchar_t は 2バイト以上」っていうのも同じ問題をおこしましたよ
5:56 AM
2011年に改正された C/C++ の標準規格、C11 と C++11 では、新たに2つの文字型が導入された。char16_t と char32_t であり、それぞれ UTF-16 と UTF-32 を内部表現とする。
5:56 AM
結局こうなりました・・・
5:56 AM
まあ文字は整数より意味が強いから問題としては別かも。
5:57 AM
SwiftのIntはポインタサイズ型だから128ビット時代にもいける気もしますね
5:58 AM
JavaのJNIコードは128ビット時代になったら long でポインタをハードキャストしてるところをまた直さないといけないのか・・・
Avatar
C/C++ の場合は長らく固定サイズの型が標準で提供されてなかったのが問題なのでは?
5:59 AM
Swift みたいに IntXXInt でキレイに分かれてたらそんなにひどいことにはならない気が。
Avatar
固定したい要求のある場面で明示的にそれが記述できないからか
5:59 AM
たしかにSwiftでバイトサイズが絡む時は UInt8 とか出てきますね。
Avatar
なので、固定しなくてもいい(一般的な整数を想定してる)ケースは Int 、固定したいケースは IntXX でうまくいくと思うんだけどなぁ。
Avatar
Kishikawa Katsumi 12/12/2017 6:05 AM
私は基本的にサイズを固定すべきで「一般的な整数」というのが必要なケースの方が例外的だと思ってるんですけど、 @koher さんは逆ですか?
Avatar
@Kishikawa Katsumi はい、僕は概念として一般的な整数があると思っていて、特殊なケースでそれを固定サイズの整数として扱いたいんだと思っています。
6:13 AM
たとえば、 UITableView のセル数は概念として一般的な整数だと思うんですよね。ユースケースを考えたら 99% のケースではそれが Int32 に収まるとしても。 (edited)
👍 1
Avatar
Kishikawa Katsumi 12/12/2017 6:21 AM
私はそういうのは一般的な整数ではなくてハード・ソフトの制約を考えてInt32かInt64などに厳密にモデリングするべきと思うんですよね。
Avatar
うーん、そのあたりは好みというか宗教になってしまいそうですねぇ。。。
6:29 AM
多分、型はコンピュータの内部表現を写し取っているべきだとすると Int32 になって、概念を写し取っているべきだとすると Int になるんじゃないでしょうか。
Avatar
Kishikawa Katsumi 12/12/2017 6:42 AM
私もそんな気はしている&koherさんの意見にもある程度納得しているんですけど、例えば文字列も「一般的な文字列」というのは厳密にはないのであってプログラミングするにはどこかで曖昧さをなくす必要があって、で、それはコンピュータの内部表現に依存するので、そうするとIntっていうのはほとんどのケースには便利だけど、、、という感じですね。
Avatar
文字列についても Swift ではできるだけ Unicode を隠蔽して書記素クラスタで「一般的な文字列」に近づけているとは思いますが、所詮文字列は人工的なものなのに対して、整数はより根源的な存在だから余計に Int32 等にすることに(僕が)違和感を感じるのかもしれません。
Avatar
-------------- ↓これできないのバグでしょうか? FooProtocolFoofoo の実装をコメントアウトすれば動きます。少なくともエラーメッセージはおかしいと思います。 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)
Avatar
バグっぽいですね。最後の行 a.foo { $0 += 1; () } でも動きます。
Avatar
; () 足して動くのヤバイですね。
Avatar
不思議なバグだ
Avatar
single expression クロージャの型推定が出来なくて(バグ1)、その理由を探すロジックが変な診断(バグ2)。って感じかと。 (edited)
Avatar
類似の探してみてなければ報告しておきます。
👍 1
Avatar
あ、 master だと動くみたいです。 4.1も試してみよう。
Avatar
なるほど。じゃあ報告は不要ですね。
Avatar
4.1でも動きました。
Avatar
おお。
Avatar
Still experimental. Work to eliminate ArraySlice in favor of Slice + conditional conformance. Requires additional features that would need evolution proposals: new ContiguouslyStored protocol that...
2:37 AM
ArraySliceを削除してSliceを作って public typealias ArraySlice<T> = Slice<[T]> にするPR (edited)
Avatar
えーー
2:48 AM
これって Proposal あったっけ?
Avatar
APIは変わらないんじゃないですか?typealiasだし
Avatar
Proposal出す時にPR参照は割とある気がする
Avatar
ProposalもMLも見てないけど、できてからメール出すパターンも多い
Avatar
でも Slice を導入するのは大きな変更では?
Avatar
Sliceはいまもあるのでは?
Avatar
あ〜そっちはたしかに。
2:49 AM
え、あるの
Avatar
なんかいま補完ででてましたけど
Avatar
www
Avatar
↓もなるの? typealias Substring = Slice<String> (edited)
Avatar
わからんです。
2:50 AM
プルリクの見出しとか見る限りStringの話はされてないですね。
2:50 AM
なんだこれ・・・こんなんあったんか・・・・
Avatar
えーー、 EasyImagy の ImageSlice の名前どうしよ。できるだけ ArraySlice を踏襲するようにしてたのに。
Avatar
ていうかSee Alsoのところに
2:51 AM
なんちゃらSliceがめちゃめちゃあるな
Avatar
@koher それもSliceを使った実装にできるのでは?
2:51 AM
二次元はきついのかな?
Avatar
次元が全然違うから無理そう
Avatar
せっかく ImageProtocol を導入して ImageImageSlice で共通の実装を持たせるとこが今朝大分できたのに・・・。
2:52 AM
2 次元は Slice にできないと思う。
2:52 AM
まあ、 ArraySlice の名前が残るならそれでもいいけど、
2:53 AM
Subimage にするか ImageSlice にするかで迷って、 ArraySlice 的なアップデートができるからそっちに寄せて ImageSlice にした。
2:55 AM
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
Avatar
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 }
2:56 AM
これ一度は絶対踏みそうなんだよなあ
2:57 AM
専用の型にして生のIntは渡せないほうが良いような気がするけどArrayと透過的な取扱にしたいというのもあるしなあ
Avatar
これを踏襲して、↓みたいな挙動にしてる。 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)
Avatar
https://github.com/apple/swift/blob/master/docs/StringManifesto.md#different-type-shared-storage このへんの話と合わせて Slice<T> is T みたいなサブタイピングが追加されそうな予感
swift - The Swift Programming Language
Avatar
SubstringからStringとかに戻すタイミングで
4:22 AM
部分バッファのコピーが発生するのを
4:22 AM
コントロールできなくなっちゃうからそれはないんじゃないでしょうか
Avatar
@omochimetaru 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.
Avatar
ふむふむ
Avatar
Optional だけでなくさらなる黒魔術を導入しようとしてるのか?😇
Avatar
まずい
Avatar
↑に書いたコード、 iOS から見るとシンタックスハイライトされてない・・・。なぜ?パースのしかたが違うのかな?
Avatar
Substring is a String 無理だと思うんだけどな。
5:39 AM
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"
5:40 AM
↑だからサブタイプとしての要件を満たせない気が。
Avatar
関数の引数に渡すときとかに String(substr) を暗黙に呼び出すとか
5:40 AM
そういう意味かなと↑の文を読んで思ったけど
Avatar
実際はそうだけど、それはサブタイプではない。
Avatar
はい
5:41 AM
だからそこらへんは厳密な議論をしてないとおもった
Avatar
Optional はもう一歩踏み込んでいて、↓ができる。 class A { func foo() -> Int? { return nil } } class B : A { override func foo() -> Int { return 42 } }
5:43 AM
StringSubstring は今はできない。
5:44 AM
ただ、実際のところ IntInt? のサブタイプにはなってなくて、↓はエラー。 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 } ^ ~~~
👀 1
Avatar
引数としては Array<T> を UnsafePointer<T> に渡せるなどの黒魔術があるので、サブタイプというよりは、引数マジックならいい気はします。
5:45 AM
StringUnsafePointer<UInt8> に渡せるし。
Avatar
完全に今思いついたんですけど
5:46 AM
その手の引数マジックも明示的な方がいい気がする
5:46 AM
例えば1文字だけ記号つけるとか
5:46 AM
そういう文法で。
Avatar
↓は単なる代入時の暗黙の変換よりも踏み込んだことを意図しているのかと思ったけど、そうじゃないのかな? Substring should be a subtype of String in the same way that Int is a subtype of Optional<Int>.
5:47 AM
ただ、暗黙の型変換にしても反対ですが。
Avatar
let str: String = "hello" strlen(str) // これはだめにして strlen(^str) // こうするみたいな。 (edited)
Avatar
optionalもその範疇で、wrapping operatorがあるといいなと思っていて
Avatar
@omochimetaru UnsafePointer 周りは & がその役割してるのでは?
Avatar
暗黙的に型変換するものを全部その体で扱うのなら、それ用のオペレーターがありOptionalもそこに類するのがよい
Avatar
@koher ArrayとStringのCポインタ変換は&いらないですよ
Avatar
^とか~がいいなぁと思った
Avatar
&はinoutとの対応メタファーになってて、MutablePointerに変換する時はつけるけど。
Avatar
in the same way that Int is a subtype of Optional<Int>. はもっと強い意味だけど、 the default string type used for everyday exchange between APIs. を解決するのにサブタイプは必要ないんじゃないか?っていう意見です。
Avatar
@omochimetaru そうだった。
5:53 AM
& も構文失敗してる気がする。↓ややこしい。 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)
5:54 AM
f(&b) が良くない
5:55 AM
@rintaro > 解決するのにサブタイプは必要ないんじゃないか? それはそうですね。ただ、明示的に型変換するくらいがちょうどいいと思うんですけどねぇ。
5:56 AM
どうしても型変換しまくるコード書くときは(パーサとか)
Avatar
Substringを受けるオーバーロードをその場で足す (edited)
Avatar
型変換して渡すときに明示オペレータ必須のほうが良いというのは同意です。
Avatar
internal な後置演算子作って変換すればいいし
5:57 AM
(前置でもいいけど後置の方が好み)
6:01 AM
@omochimetaru ^ で変換、今もできる。 prefix operator ^ prefix func ^(value: Substring) -> String { return String(value) } let s = "abc" let t: Substring = s[...] let u: String = ^t print(u)
Avatar
えーっと、値として返せばいいパターンはそうなんですけど
6:01 AM
Arrayが内部のポインタを返すやつとかって
6:02 AM
API仕様上はwithUnsafeBufferPointerのクロージャの内部の期間だけ有効
6:02 AM
っていうルールになっているんですよね
6:02 AM
Arrayが内部で直列なバッファを持っていなくても
6:02 AM
このwithXXXXの間だけそれを一時的にヒープ上に生成してわたしてやって
6:02 AM
その呼び出しが終わったらまたスパースなメモリレイアウトだけに戻る
6:02 AM
っていう実装が許されていて
6:02 AM
それを考慮すると現状のArray to pointer変換ってただの型変換じゃなくて
Avatar
Arrayが内部で直列なバッファを持っていなくても
そんなことあるの?
Avatar
strlen(str) // 元のコード // 変換先のコード str.withUnsafeBufferPointer { strlen($0) }
6:03 AM
こういう、関数呼び出しそれ自体をラップする形の書き換えが必要で
6:04 AM
そのケースについては現状の言語仕様上でできるユーザー定義演算子だと無理だと思うんですよね
6:04 AM
The pointer passed as an argument to body is valid only during the execution of withUnsafeBufferPointer(_:). Do not store or return the pointer for later use.
6:05 AM
↑ここで渡されるバッファポインタは、withUnsafeBufferPointerの呼び出しの間だけ有効で、ストアしたりreturnして取り出して後から使ってはいけない
6:05 AM
って書いてあるんですよ
6:05 AM
ということは逆に言うと
Avatar
ん? strlen(^substr) // 元のコード // 変換先のコード (^substr).withUnsafeBufferPointer { strlen($0) } になるのではなく? (edited)
Avatar
普段のメモリレイアウトに制約がないってことになります。
Avatar
var ary = [2, 3, 5] func f(_ p: UnsafePointer<Int>) { } f(ary) // は ary.withUnsafeBufferPointer { f($0.baseAddress!) } // の sugar (edited)
Avatar
普段のメモリレイアウトに制約がない
理論上そうかもしれないけど、それは Array の内部のポインタをそのまま取り回せないようにするのがその意図なんじゃない?( Array をぶっ壊したり、ライフサイクルを超えて取り回したりできてしまうから)
6:08 AM
連続メモリが保証された型としてはわざわざ↑が存在しているので
6:08 AM
The ContiguousArray type is a specialized array that always stores its elements in a contiguous region of memory.
6:09 AM
Arrayはそうでもないってこと・・・?って思ってます。
Avatar
NSArray からブリッジされた Array は Contiguous の保証はないという認識です。
Avatar
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.
6:11 AM
自由なメモリレイアウトが実現したいわけじゃないけど、 Obj-C 連携のために泣く泣くこうなってるってこと??
Avatar
そういう言い方もできますね
Avatar
それとも、 Obj-C 連携以外の余地も残したいのかな? (edited)
Avatar
逆に言えばObjC以外のブリッジングも
6:11 AM
できるように制約を弱めてあるともいえそう
6:15 AM
まあ言いたかったのは
6:15 AM
こういうケースがあるから
6:15 AM
型変換マジック演算子を自作できない場合があるということです
Avatar
↓はできたよ。 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: 3
Avatar
Substringはいけると思います。
6:16 AM
あ、でもあれか、
Avatar
ArraySliceArray にせよ、変換してから渡すから問題ないのでは?
Avatar
「引数部分だけに適用できる」ってルールがあったほうが明確なのかな
Avatar
mutating じゃないといけないときはダメだけど。
Avatar
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 こういうもんなのか
2:23 AM
func fuga(cellType: (UITableViewCell & ProtocolA).Type) {} fuga(cellType: typeA) // ok fuga(cellType: typeB) // ok ジェネリクスじゃなくしたら行けた。
Avatar
プロトコル自身がジェネリックのプロトコル制約を満たせない、っていうやつかな? (edited)
Avatar
具体型じゃないと〜というやつですかねえ
2:25 AM
🤔
Avatar
これは、そうだね
2:31 AM
もっとシンプルなのでいくとclassの制約の型パラにはclass制約を満たすprotocolの変数は入れられない
2:32 AM
swiftのprotocol型の変数が、実際には存在型として振る舞ってるという話だけどまだ全貌掴めてないや
Avatar
ふーむ
Avatar
こういうもんなのか
定期的に困るけどそういうもんやな
Avatar
初めて実際にアプリのコード書いててこれ困ったかも
Avatar
ひらりの最初に張ったコードであれば
2:34 AM
hoge(cellType: CustomCell.self)
2:34 AM
↑これはとおるよ
2:34 AM
いったん変数に入れるから駄目なだけで。
Avatar
うんうん
Avatar
メタクラスのtype erasureってもしかして自作できない・・・?
Avatar
何がしたかったかというとUITableViewのregisterのジェネリックな版みたいなのを作っていて、登録対象のセルの型を [UITableViewCell & ProtocolA).Type] に詰めてforEachで全部処理しようとしたら詰まったという感じです
Avatar
やったことないからパッとわからんけど、static func定義されたprotocolのerasureはうまくいかなかったから同様に難しそう
Avatar
前にも話したのは覚えてて結論を覚えてないんだけど、プロトコルが自身のプロトコルを満たさないのってなんでなんだっけ??
Avatar
存在型として振る舞っている、存在型はconformできない の二点セット
2:37 AM
結論は…各々の宿題になってますね(やってない)
Avatar
existential が conform できないのの理由ってあるんでしたっけ?現状の実装がそうなってるだけなのか、思想的な理由なのか。 (edited)
Avatar
登録対象のセルの型を [UITableViewCell & ProtocolA).Type] に詰めてforEachで全部処理しようとしたら詰まった
これは ProtocolA がstatic funcをもってるってこと?
Avatar
理論上という話だったので素直な実装だと無理ということだと認識してます
Avatar
それとも init で作られたオブジェクトが ProtocolA であることを要求してる?
Avatar
これは ProtocolA がstatic funcをもってるってこと?
static varがある
Avatar
@hiragram それ無理筋なのでgybで複数引数いっぱい生成したらいいよ
Avatar
gybまで引っ張り出さなくても感はある
Avatar
せいぜい10種類でしょ
2:39 AM
いや手書きはだるいw
Avatar
registerメソッドを10回呼べばいいので
2:39 AM
オーバーロードを生成する必要はないかな
Avatar
まあそやね
Avatar
ああそういう感じか
2:40 AM
10個配列に入れといてループで突っ込めたら良かったのにってことか
Avatar
そう
Avatar
あれに関していうとbind時にregisterごと解決できると言うアイディアはあったんだけど、class/nibのどっちを登録するべきなのか、tableViewのnibで定義済みなのか、が見分けられなくて結局断念した
Avatar
それができなくてもまあregister呼び出しが10行になるだけだからそんなに大困りしているわけでもない
2:41 AM
ふむふむ
Avatar
Generalized Existential で Any<Error> が許されるようになれば T: ErrorAny<Error> を入れられるようになるのかな??
Avatar
確かに見分けは無理そう
Avatar
うーんヒラリのやつはなんか簡単なコードでうまく解決したいな
Avatar
てか、それができないと typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> が成り立たないか。
Avatar
前回の結論は、それはそうですね、どうなるんでしょうでおしまい
🙏 1
Avatar
なるほど・・・。話したことの記憶しか残ってない・・・。
Avatar
でもそれを認めるなら、MyProtocol.self is MyProtocol.Type はtrueでなければならない、型システムを大きく書き換えないといけない
2:42 AM
ABI安定化が遠のく
Avatar
うーん、↓ができないと Generalized Existential の意味あまりなさそう( AnySequence 等の個別の実装をなくせない)だし、 typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> でもそのために早期 ABI 安定化ができないのだとすると、どちらかを諦めるしかなさそうですね。
Avatar
あー、
2:46 AM
現状のMyProtocol.selfは存在型のままで、Any<MyProtocol>.selfは一般的なtype-eresure、とすれば解決はできそうだ
Avatar
うーん、逆な気がしてます。 generalized existential はあくまで existential で、 type eresure を使わなくていいようにしたいけど、そのためには今の実装では無理だからすぐにはできない、じゃないですか?
2:48 AM
generialized existential が導入されたらプロトコルを型として使うのすべて禁止して、 Any<FooProtocol> の形に統一するのがいいんじゃないかと思ってます。
2:49 AM
今も Selfassociatefdtype を持つプロトコルは型として使えないのに、一部のプロトコルが型として使えることに気持ち悪さを感じてます。
2:49 AM
protocolinterface ではないので。
Avatar
その路線は早期ABI安定化を諦めることになりそう
2:50 AM
まあ何となくですが今の状況では無理だろうな(ABI)という気はしています
Avatar
安定化までせずとも、同一メジャーバージョン間では ABI を保つとかしてくれれば便利にならないでしょうか?
Avatar
Generics Manifesto つまみ食いしかしてなかったけど、ちゃんと見てみたらおもしろいこといっぱい書いてありますね。 https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md
swift - The Swift Programming Language
6:24 AM
Higher-kinded type の構文の例↓ protocol Functor { associatedtype A func fmap<FB where FB ~= Self>(f: A -> FB.A) -> FB }
Avatar
全部読んであるかと思ってました
Avatar
↓で protocol<P1, P2>Any<P1, P2> ではなく P1 & P2 に置き換えられちゃったみたいだけど、 generalized existential と整合がとれなくなっちゃってる気がするんだけどどうするんだろう・・・。 https://github.com/apple/swift-evolution/blob/master/proposals/0095-any-as-existential.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
P1 & P2 は今もあるプロトコルをそのまま変数の型にできるやつで
6:29 AM
Generalized Existentialになったときに
6:29 AM
associatedvalue があっても大丈夫になって (edited)
6:29 AM
表記がAny<P1, P2> になるのだと思ってます
6:30 AM
associatedtypeか
Avatar
@omochimetaru 元々 Any<P1, P2> という表記で提案されていたのが最終的に P1 & P2 に変更されて採用されてるんです。
Avatar
でもその元々のやつは
6:30 AM
associatedtypeがあったら駄目で、それ自体はプロトコルを満たさないやつですよね?
6:31 AM
だから、GEneralized Existentialで提案されてる Any<P1, P2> の表記で表される機能とは振る舞いが違うから
6:31 AM
むしろちょうど避けられてて良かったのかなと
Avatar
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.html
Avatar
なるほど。
Avatar
なので、 Any<P1 & P2 where ...> になるんじゃないかと思います。
Avatar
そうするとそのタイミングで P1 & P2 は廃止される?🤔
Avatar
僕の理想のストーリーだとそう (ただし変数の型の用法だけ)
Avatar
Any<P1 & P2> の sugar として残る(残さざるおえない)んじゃないかなー。
Avatar
でもその場合は P1 & P2 is P1 になるってことですよね?まあゆるくなるだけだから互換性はありますが・・・。
Avatar
あ〜 まあそれでも問題は無いか・・・
6:35 AM
これまでが変だっただけで普通にconformするようになるって視点では見られますね
Avatar
でもそしたらほとんどのケースで Any<P> よりも P が使われそうなのが微妙・・・
Avatar
そうですね。
6:36 AM
Any< > 表記はただ where を持つときの構文上の必要で使うってなりそう。
Avatar
P を型として書くのは existential であることを意識しないで使ってしまうので廃止してほしい。
6:37 AM
PAny<P> と書かないといけなければ、 func foo<T : P>(_ x: T) が望ましいものが func foo(_ x: P) と書かれるケースが減りそう。 func foo(_ x: Any<P>) だと気持ち悪さがあるので。 (edited)
Avatar
廃止はさすがに source breaking 過ぎるのでハードル高そう
Avatar
Delegateが厳しくなりそう
6:39 AM
class UITableView { var delegate: Any<UITableViewDelegate>? } これは受け入れられるのだろうか
Avatar
しかたないですね🙃
Avatar
民が受け入れないことにはw (edited)
Avatar
@tarunon それ全然ありだと思ってて
6:41 AM
ObjCの時 id<UITableViewDelegate> って書いてたんだよね
Avatar
それはそうなんだよね
Avatar
古き良き正しさに戻ってる感がある
6:42 AM
「型」と「型のみたす制約」は次元の違う概念だから (edited)
Avatar
おお、そんなのあった。 Obj-C のときは何これって思ってたけど、正しかったのか・・・。
Avatar
そこが曖昧な表記だったせいでみんなSwiftのprotocolで混乱してきたんだと思うんだよなあ (edited)
6:42 AM
@koher はい、あと、 & 記法みたいなのもありますよ。プロトコル2つのandができた。
6:43 AM
プロトコル合成がないSwift2(ぐらい?)のときはObjCのその点の機能で言えば劣化してしまってた
6:44 AM
rintaro - 今日 午後3時38分 廃止はさすがに source breaking 過ぎるのでハードル高そう
まあ実際これだと思うけどね・・・
Avatar
protocolinterface が概念的に違うことについて、公式ドキュメントでちゃんとした説明が必要だ・・・ (edited)
Avatar
そうですね。
Avatar
Sequence<where Element == Int> みたいな 構文になる可能性もありますね。
6:46 AM
P1<where ...> & P2<where ...>
Avatar
Any記法に全部置き換えないならそっちのほうがしっくり来るなぁ
Avatar
Sequence<where Element == Int> みたいな 構文
これはなんで Sequence<Int> にしないのかみたいな話を誘発しそうです・・・
Avatar
まあ protocol は型ではないんだけど、いろいろ外堀を埋めてって、型っぽく使っても壊れないようにしていく(違いを意識できていなくても動くものが作れる)方向を向く って道もありそうで、今のSwiftはそっち気味ですよね
6:48 AM
protocolに static func とか init とか書けるのが特にそう感じる
Avatar
でも Sequence<where Element == Int> はジェネリクスとの混同でやはりカオスになりそうw
Avatar
rustライクなGenerics protocolとは共存できない記法だ
Avatar
@omochimetaru protocolstatic func は必要では? Argo の Decodable とかそれなしに成立しないし。 initstatic func と同じだし。
Avatar
必要なのは必要なんですけど
6:52 AM
Scalaで型クラスをやった時の構成法とくらべて
6:52 AM
かなりシンプルというか
6:52 AM
Swiftのprotocol定義はclass構文から直感的に言いたいことがわかるじゃないですか
Avatar
そうかなぁ。 static func を持てるのは制約を表すために普通に必要だと思うけどなぁ。たとえば↓とか。 protocol Group { // 群 static func •(lhs: Self, rhs: Self) -> Self // 結合法則を満たす演算 static var identity: Self { get } // 単位元 var inverse: Self { get } // 逆元 } (edited)
Avatar
例えば Java だと interface は static func 制約をかけないし
6:59 AM
Haskellだと class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y)
7:00 AM
関数が基本形になっているから、static func相当のことは、2引数関数になるんですけど
7:00 AM
Swiftのprotocol構文は オブジェクト指向言語的に
7:00 AM
メソッドが前提になっていて
7:00 AM
メソッドが前提っってことは第1引数のthisがあるから
Avatar
Java の interfaceprotocol とは別の概念だから異なってていいのでは? (edited)
Avatar
それが無いstatic funcは一歩戻ってわざわざ書けるようにしている
7:01 AM
いや
7:01 AM
Swiftの構文がうまくできすぎていて自然すぎるから
7:01 AM
当たり前のことのように見えるだけで
7:01 AM
これまではうまく設計できなかったものを
7:01 AM
OOP目線で発明できたって僕は思ってます
7:01 AM
その証拠にSwiftと同じ構文構造の言語が他には無い (edited)
7:02 AM
引き合いとしてScalaが一番わかり易いと思う。
7:02 AM
implicit parameter推論まで持ち出して手書きさせるようになってるけど
Avatar
それは Swift が本質的にオブジェクト指向言語より関数型言語に近いからじゃないかな?
Avatar
あれはHaskellの型クラスの思想をおダスキー先生がJVM OOPベースで再発明しようとしたときに
7:03 AM
あーゆー形になったわけだけど
7:03 AM
Swiftのアプローチはもっとうまい方法を見つけられたってこと。
7:03 AM
(その代わり型クラス機能としてはSwiftはまだ欠陥が残っているけど)
Avatar
オブジェクト指向言語っぽく書けるうまい構文になってるのはその通りだけど
Avatar
本質的に関数型なのかどうかは置いといて、従来のオブジェクト指向言語のユーザーが、直感的に触れるようにうまくデザインできている
Avatar
結局理解してないと色々破滅を招きかねないので
7:06 AM
違いを理解することは必要な気がするけどなぁ。
Avatar
はい、そこで2方向あると思ってて、僕の意見も @koher に近いけど
Avatar
Java から来て一番ひっかかるのの一つは、なんで Sequence<Element> じゃないの?ってとこだろうし。
Avatar
わからないまま従来のオブジェクト指向言語的な考え方で直感的に使っても
7:06 AM
なんかうごく方向に全部がんばってまとめていく
7:06 AM
っていう道筋もあると思ってて
7:07 AM
現状はどちらも満たしてると思うんですよね
Avatar
Sequence<Element> はでも結局不可能で
Avatar
Generalized Existenailの Any記法と さっきの Sequence<where> の記法とかはそこの方向性の違いであると思う
Avatar
Iterator もあるから
Avatar
上から順番に当てはめるというルールにして、指定しない場合はアンスコとかやれば
Avatar
Sequence<where Element == Int> にしたとして、なんで Sequence<Int> じゃないの?ってなって
Avatar
Sequence<Int, _, _>みたいにできるが…?
Avatar
結局理解が必要そうな気が (edited)
Avatar
果たしてこれはw
Avatar
それに自分でプロトコル作るときは protocol Sequence<Element> { ... } とはできないからやっぱり混乱するだけじゃないかなぁ。
Avatar
結局AssoctypeとGenericsの境界があるので、変数宣言時の記法だけGenericsに寄せると結構厳しい気はしてきた
Avatar
@tarunon associatedtypeって相互に推論されて減ったりしてない?
Avatar
どういうことや
Avatar
えーっと、
Avatar
ああ、指定されなくても決まる場合があると
7:10 AM
でもその場合はデフォルトの挙動でしかないから上から押さえつければ別のものを設定できる
Avatar
Collectionだけでも IndexDiistance, Indices, Iterator, SubSequence
7:11 AM
の4つがあって
7:11 AM
いやいや
7:11 AM
Sequence<T1, T2, T3>
7:11 AM
の表記の問題点は
7:11 AM
左からしか埋められなくて、省略する方が右に限られることで
Avatar
7:11 AM
省略は_だぞ
Avatar
はい
Avatar
別に右に限らなくない?
Avatar
_を適切な個数埋めないといけない
Avatar
それはそうじゃろ
Avatar
今はそうじゃないよね
Avatar
僕の提案はSequence<T>の記法は無理、なのでやるにしても_で埋めるしか無い、という話 (edited)
7:14 AM
assoctypeの制約をwhere以下に書くのはまあ既存のconditionの記法もそうだし理解できるとして、<>が出てくるから似た機能のGenericsが想起されて混乱する (edited)
7:14 AM
結論: 括弧が足りない
Avatar
型名の [ ] はArrayに使っちゃったしなあ
7:16 AM
ブレースはinitの後置クロージャに見えちゃうし・・・
Avatar
Sequence[where .Element == Int]
7:16 AM
Arrayとconfuseするかいな?
Avatar
まあArrayは型名に後置できないからギリギリコンパイラにはわかるだろうけどtypoしたときの混乱がやばそうね
7:17 AM
あれ?丸括弧が残ってんじゃない?w
Avatar
それはinitに見えるのでは
Avatar
あ〜
7:17 AM
なるほど。
Avatar
GenericsとのConfusingはマジで概念レベルでトチるので危険きわまりない、角括弧にして誤解を減らせるのはありそうな気がする
Avatar
結局そうなって初心者が無限に混乱する展開がめっちゃ思い浮かぶ・・・
Avatar
let array: [Sequence[where Element == Int].Type] = [Sequence[where Element == Int].self] んー、なんとかいけるか?
Avatar
Arrayと組み合わせた時の見た目ヤバイですねw
Avatar
objective-cを思い出した
Avatar
ちなみに let a: Int[] = [1] は未だに Fix-it 出してくれるという親切さ。
Avatar
ほんとだw
7:24 AM
直せたw
Avatar
Int[] の時代とかありましたね。 Java から来るとわかりやすかったけど、今となっては何がよかったのか・・・
Avatar
AnyIteratorstruct なんだけど、値型捨て過ぎなのでもう class になった方がいいのでは? let a = [2, 3, 5] let i = AnyIterator(a.makeIterator()) let j = i print(i.next()) // Optional(2) print(j.next()) // Optional(3)
Avatar
AnyIterator自体のコピーは内部のboxの共有になってそうですね。
Avatar
はい。 struct なのに letnext できてることからも。
8:26 AM
nextmutating func じゃないという潔さ。
Avatar
ほんとだ
Avatar
意図的なんだろうけど、もう class にしなかった意味がよくわからない。
Avatar
僕はなんかそこらへんの振る舞いがモヤモヤするしフィールド数でコピーコストが伸びるのが嫌でerasure をclassにする事がよくあります
8:27 AM
ただ、スマートポインタ型としてのイレイジャなのだという解釈であればstructでもいいんですけどね
Avatar
うーん、ただ罠なようにも感じるけどなぁ。
10:36 AM
Although I posted about this topic before, let me post this again because I think it is important and I have received just few replies. Sorry if I missed some discussion about it. In the proposal ( https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619 ), 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...
10:36 AM
過去ログも移行されている
👏 4
Avatar
Sign Up した。
Avatar
github連携でログインできるの良い
Avatar
アクティベーション町になった
Avatar
なんかそれリロードしてLoginしたらいけた
Avatar
うん
10:38 AM
メール来なかった
Avatar
いけたわ、thx
Avatar
unread が可視化されたおかげで見逃しに気づいた
10:40 AM
Sorry, I'm just getting into this conversation late and am by no means experienced in the area, but why can't the one where you don't want the caller to wait for the result be spelled 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...
Avatar
これアイコンが青く光ってるのって
10:41 AM
今見てるって意味かな?
Avatar
アイコンが青く光る??
Avatar
Send me email notifications even when I am active on the site
設定にもこういうのあるし
10:43 AM
ao
10:43 AM
レスごとの未読管理はスクロールするだけで既読になるのか
Avatar
お、ほんとだ、光ってる
Avatar
GitHub経由でSignUpしたらユーザー名がNorio_Nomuraになってしまってモヤモヤする…😕
Avatar
僕もお役所ネームだw
Avatar
GitHubで何度やってもエラーになったので、メールで登録したら結果オーライでmono取れました( ´・‿・`)
Avatar
ID 変更できないの辛い・・・。
Avatar
それ
3:29 AM
githubから本名拾ってIDにセットするの絶対おかしい
Avatar
Username?
Avatar
なんで GitHub の ID じゃなかったんだ?
3:30 AM
Username
3:30 AM
Username Yuta_Koshizawa People can mention you as @Yuta_Koshizawa
3:30 AM
ひどい・・・
Avatar
メンションがそれになっちゃうのか
Avatar
Discourse の仕様なんだろうか。どうにかしてほしい・・・。
3:33 AM
GitHub と異なるってわかりづらすぎる。
Avatar
僕はgithubのnameは omochimetaru なんですけど
3:33 AM
フォーラムのIDは omochi.metaru になっていて
Avatar
Avatar
このドットどこから来たんだ?
Avatar
本名登録してないからじゃない?
3:33 AM
メールアドレスかな?
Avatar
メルアドの @ の左はこれですね
3:34 AM
本名登録ってなあに
Avatar
もしかして GitHub からとってなくて
3:34 AM
@omochimetaru GitHub に < 本名 (edited)
Avatar
Nameの欄は 名字と氏名わかれてないけど
3:34 AM
別にあるんですか?
Avatar
過去に swift-evolution にメール送ったことがある人はメールから自動的にユーザーが作られてて
3:35 AM
GitHub でサインアップしたらそこでひも付けが行われただけなのでは?
Avatar
それなら自分のケースも筋が通るな
Avatar
で、僕や @norio_nomura さんや @tarunon さんは本名をメールに入れてたからそれベースで作られて
3:36 AM
@omochimetaru は入れてなかったから @ の左の omochi.metaru になった。
Avatar
これID新規作成のときしか設定できない
3:36 AM
Github認証だとそこがスキップ
3:36 AM
罠だな
3:36 AM
If you’ve previously sent mail to one of the Swift mailing lists, an account has already been created for you. If you’d like to take control of that account: Click on Sign Up In the Sign Up form, enter the email address that you used on the mailing lists. You can choose to accept the account name that was pre-created for you, or choose a new one You will be prompted to verify your email address. Please file issues/comments/requests at bugs.swift.org under the “Project Infrastructure” compon...
Avatar
@mono さんは過去にメールを送ってないか、もしくは新規生成したせいで過去の自分のメールと紐付けられてないとか。
👀 1
Avatar
新規生成時にIDをセットできるとあります
Avatar
俺もドット消したいなあ
Avatar
このスレにリプライ送っておけば良いかな。
Avatar
Please file issues/comments/requests at bugs.swift.org under the “Project Infrastructure” component for tracking.
3:38 AM
こっちかな?
3:39 AM
ちゃんと新規作成で作ったら紐付けられるっぽいから @mono さんは過去にメールを送ってても同じアドレスだったらセーフそう。
Avatar
Github認証でID設定がスキップは完全に罠だ
3:39 AM
おこだよ
😡 4
3:43 AM
上がってない。あげよう
Avatar
yutailang0119 12/15/2017 3:48 AM
新規作成からでGitHub認証問題なかったけど、前システムの時に登録してた人たちは username 変更しちゃうと今までの @ と紐付かなくて困るって話です? (edited)
Avatar
@yutailang0119 前システムは存在しないです。今まで ML だったので。
3:50 AM
今まで ML に投稿したことがあった人に Username が自動で割り当てられてて
Avatar
yutailang0119 12/15/2017 3:50 AM
あ、MLから自動でユーザー作られてるからってことか
3:50 AM
これでええんやろか
Avatar
GitHub 認証するとそれを変更するタイミングが存在しなかったってことですね。
3:51 AM
@tarunon
who have post
posted では?
Avatar
ども
3:52 AM
中学生より低い英語力なんで添削は助かります
Avatar
yutailang0119 12/15/2017 3:52 AM
なるほどw
Avatar
account id
システム上 Username と呼んでるみたいなのでそっちの方が混乱がなさそうです。
Avatar
yutailang0119 12/15/2017 3:54 AM
username 設定の歯車から変更できそうな動きしてるけど、上の問題に該当する人たちはだめなのかな
Avatar
変更できないですね
Avatar
こんな感じです。歯車がないように見えます。
Avatar
yutailang0119 12/15/2017 3:57 AM
なんと、新規の場合はこんな感じで変更できそう
🙄 1
Avatar
3:57 AM
まあじゃあそのうち治るっしょ
Avatar
Kishikawa Katsumi 12/15/2017 4:06 AM
4:06 AM
昨日サインアップしたけど、デフォルトのままでおそらく期待した動作になりました。
4:07 AM
usernameとNameがGitHubのそれと一致している。
4:07 AM
GItHubでサインアップ。
Avatar
新しいパターンw
Avatar
@Kishikawa Katsumi さんは過去に swift-evolution に投稿したことありますか?
Avatar
Kishikawa Katsumi 12/15/2017 4:08 AM
あ、そういうことか。swift-evolutionは購読しているけど投稿はないです。
Avatar
お、じゃあいまのところ、「github登録 かつ 過去に投稿した」
4:08 AM
の人がこの鉛筆マークが出ない状態になっているw
Avatar
yutailang0119 12/15/2017 4:09 AM
新規の人たちも、投稿したら変更できんくなったりせんかな
Avatar
@tarunon 僕も英語に自信はないですが、とりあえず修正案考えてみました。 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.
👀 1
Avatar
全然違うw
4:11 AM
外出てるし帰ったら差し替えよう
4:11 AM
↑のときは何も残ってなさすぎて衝撃を受けた。
Avatar
今後こういった罠にはまらない様、e-mailのfull nameをnorio_nomuraにしておこうかな…
Avatar
たしかに。僕も設定しました。
From: omochimetaru <omochi.metaru@gmail.com>
Avatar
GitHub 使わずに登録したので希望の id は取れたけど、idの変更は出来ないです。id変更可不可はgithub認証とは関係ないみたい。
Avatar
Avatar
ちなみに過去に投稿したことあります。
🙄 2
4:57 AM
その後メールアドレスを変更したのですが、投稿との関連付けは切れない。また、変更後のアドレスでのMLへの投稿は関連付けられない。
Avatar
I click the Sign In with GitHub and it was failed. However I can login with my email but there is no choosing my account name for me. I want to change my account name from the pre-created one but I can’t There is no button to change my account appear. However I try to create a new account with my secondary email and the button was shown for that account. Can I change my account name for my main account?
5:08 AM
UpVoteみたいなのはないのね
Avatar
そうか、そういえば待ち状態になってリロードしたけどあれが良くなかった可能性があるな。被害者はみんなそうかも。
Avatar
is replying... がリアルタイムで出るのかー。
Avatar
なんかLikeしただけでは効果が薄そうだったので、自分でも投稿してみた。
Avatar
ユーザー名変更できる様にしてもらった。
🎉 3
11:17 PM
管理者権限とかで僕だけが変えられる様にしてもらえたのか、全員がそうなのかは不明です。
11:20 PM
みんなできるみたいです🙂
👍 2
Avatar
yutailang0119 12/16/2017 3:19 PM
flattenネタで解決案を求めています https://qiita.com/yutailang0119/items/2f2a871acb687254d3ed ついでに15日目が空いているので、アンサーをぜひ (edited)
これは Swift Advent Calendar 2017 16日目の投稿です。 なんと昨日15日目が空いてしまっています、誰か埋めて...
Avatar
レベル指定はおいといて、ひとまず
しかし、Swift 3.0以降には flatten() は実装されていません。
についてはなくなったのではなく joined にリネームされました。 [[2, 3], [5, 7, 11]].joined()
Avatar
yutailang0119 12/16/2017 3:28 PM
ほんとですね、知らなかった... どっかで joined() の文字見た気がするのに、無視してました...
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
🙏 1
Avatar
@yutailang0119 Swift で↓のように型付けされてない Array を用いるケース自体が稀な気がします🤔 let array: [Any] = [1, 2, 3, [4, 5, 6], [7, [8, 9]]]
3:56 PM
↑のような JSON を作って JSONSerialization でパースすれば↑のような Array が得られるでしょうが、どのようにネストされているか不定なネストした Array を処理するようなことは実用上ほぼないんじゃないでしょうか。
3:57 PM
一方で、 N 重にネストされた Array をすべてつぶして flatten したいようなケースはあると思います。
3:57 PM
[[[1], [2, 3]], [[4, 5, 6]]][1, 2, 3, 4, 5, 6] とか。これならキレイに書く方法がありそうです。
Avatar
この前質問したネーミングの件ですが、 Datawrite(to:options:) に倣って名詞を後ろにおいてもいいだろうということで write(to:formatting:)write(to:format:) としました。ありがとうございました。 (edited)
12:41 AM
--- それとは別に↓を悩んでます。 次のように、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)
12:43 AM
この extrapolatedBy に与えているのは ExtrapolationMethod 型の値なのですが、次のように宣言されています。 enum ExtrapolationMethod<Pixel> { case filling(Pixel) // 画像の外側を与えられた値で埋める case edging // 画像の外側を最も近いエッジのピクセルで埋める case repeating // 画像の外側を画像の繰り返しで埋める case reflecting // 画像の外側を画像を鏡写しに折り返して埋める } (edited)
12:43 AM
これを、 edge, repeat, reflection に変えた方がいい気がしてるんですがいかがでしょうか。 (edited)
12:48 AM
特に edging を縁取り的な意図で使ってるんですが、無限の大きさを持った縁なので 縁取りのイメージと合わない気が。一方で、今のままだと -ing の統一感はあります。
12:49 AM
OpenGL に倣うと clampingToEdge とかになると思うんですがちょっと長すぎかなと。
Avatar
Kishikawa Katsumi 12/18/2017 4:48 AM
ingじゃない方がいいと思いますね。
4:48 AM
clampingToEdgeとedgeは長いのは気にならないです。
Avatar
ありがとうございます。 extrapolatedBy につながるので、 edge でも意味は通るかなぁとは思うのですが、悩ましいですね・・・。 repeatingreflectingrepeat, reflection にします。 filling-ing でも変じゃないですよね? (edited)
Avatar
Kishikawa Katsumi 12/18/2017 5:08 AM
fillingでも変じゃないです。
🙏 1
Avatar
あああ、思い出した・・・。 repeat が予約語だったから repeating にしたんだった・・・。
1:30 AM
他だと loop とかかなぁ。
Avatar
バッククォートで挟むのは?
Avatar
うーん、使う側は .repeat では済むのか。
Avatar
はい、こまらなそう。
Avatar
画像の繰り返しは repeat の方が一般的かな? CSS や GL も repeat だし。
Avatar
そう思います
1:35 AM
画像じゃないけど Array.initも repeating だし
1:35 AM
値の繰り返しは repeat って言われてる気がする
Avatar
じゃあ諦めて .repeat にします。
Avatar
それ以外だとwrapとか
Avatar
wrap の中身が 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.
1:42 AM
reflection は GL だと mirror だけど mirror は反射するよりも写し取る(同じものを複製する)的な意味が強い気がするから、 reflection でいいかな? (edited)
1:42 AM
なんか別のライブラリで reflect になってた気がする。
Avatar
例によってnumpyからそうじゃないかと思ったんですがGLだとそうなんですね。 wrapって言われると折り返しくらいしか思いつかないので最初見た時なんだこれってなった記憶あります。
1:43 AM
numpyはreflectだったかな
1:44 AM
skimageとかも同じ命名なのですがndarrayをベースに考えられてるはずなので一般の画像処理ライブラリとはずれてるかもしれない……
Avatar
numpy だと constant かぁ。確かに filling(Pixel)constant(Pixel) にしてもいいかも?
1:46 AM
extrapolatedBy: .constant(red) とか。 (edited)
Avatar
fillのほうがわかりやすいと思いますねえ
1:46 AM
numpyはそもそも画像の文脈じゃなくて数学の文脈で設計されたのを画像の表現に応用してるからちょっとズレてくると思う
Avatar
OpenCV とか参考にすればいいのかなぁ。
Avatar
こういうのは想定してるユーザ層が馴染みのあるライブラリを参考にするととっつきやすいと思います
Avatar
BORDER_CONSTANT
1:50 AM
うーん、最もメジャーなのがいまや numpy だと思うんだよなぁ。
Avatar
ちょろっとやるならimagemagickとかPILだと思う
Avatar
ExtrapolationMethodconstantだとちょっと違和感ある気がしますね。 Paddingconstantだとしっくりくるんですが
Avatar
あとSwift的にはCoreGraphicsか。
1:52 AM
numpy は機械学習系の人しかやってないんじゃないですか?
1:52 AM
ちょっと画像をリサイズしようとかグレースケール化しようとか思ってnumpy使うイメージが無い (EasyImageyのユースケースは↑こういうのなのかな?と思っている)
1:53 AM
サービスとかでアップされた画像をサムネイル用に加工するサーバサイドのimagemagickとかが
1:53 AM
めちゃめちゃ触られてると思う
Avatar
PIL は padding とかなさそう・・・
Avatar
How to add padding when using imagemagick to convert an EPS into a PNG? I want to do something like: convert logo.eps -size 128x128 logo.png But want the actual logo to be 96x96px, centered,
1:55 AM
お、ないかと思ったらあるのか。
1:55 AM
color はないなぁ。 color に限らないし。
Avatar
そもそもモードがいろいろ無さそうですね
Avatar
そもそも extrapolatedBypaddingBy にした方がいいかな?
1:56 AM
interpolatedBy とそろえたかったんだけど。
1:57 AM
paddedBy かな?
Avatar
そもそも extrapolatedBy を paddingBy にした方がいいかな?
個人的にはそっちのほうがとっつきやすくなりそう。
Avatar
interpolatedBy.nearestNeighbor とか .bilinear とかが続く。
1:59 AM
padding というタームは浸透してるから paddingBy がいいけど、そうすると interpolatingBy も検討しないといけない・・・。
Avatar
OpenGLはあまり参考にならんなあ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Avatar
resizedTo(width: ..., height: ..., interpolatedBy: ...) とかもあるからなぁ。
Avatar
https://en.wikipedia.org/wiki/Bilinear_interpolation こっちはinterpolationでいい気が
In mathematics, bilinear interpolation is an extension of linear interpolation for interpolating functions of two variables (e.g., x and y) on a rectilinear 2D grid. The key idea is to perform linear interpolation first in one direction, and then...
Avatar
まあたしかにほんとに補間そのものだよね
Avatar
そもそも interpolating にしたら by でいいのかもわからない・・・。
Avatar
はみ出しのほうはまあ補外でああるんだけど
2:01 AM
enum ExtrapolationMethod<Pixel> { case filling(Pixel) // 画像の外側を与えられた値で埋める case edging // 画像の外側を最も近いエッジのピクセルで埋める case repeating // 画像の外側を画像の繰り返しで埋める case reflecting // 画像の外側を画像を鏡写しに折り返して埋める }
Avatar
型名は InterpolationMethod です。
Avatar
関数というより「埋める」気持ちが強く感じられる
Avatar
nearest neighborがinterpolateであるかどうかが肝か
Avatar
こ〜 2次の傾きを維持して伸びていく〜とかあると、補外っぽいんですけど。
2:02 AM
まーreflectingはそんな感じあるか
Avatar
ちなみに↓のような API もある。 subscript(x: Double, y: Double, interpolatedBy interpolationMethod: InterpolationMethod, extrapolatedBy extrapolationMethod: ExtrapolationMethod<Pixel>) -> Pixel
2:03 AM
2次の傾きを維持して伸びていく
そういうのを追加する可能性もある。
Avatar
フーム
Avatar
↓を考えると subscript のラベルは名詞を並べるだけで良さそうだから https://developer.apple.com/documentation/swift/dictionary/2894528-subscript
Avatar
「上のエッジと右のエッジで埋め方を変えたい」とかは無いかなあ
Avatar
subscript(x: Double, y: Double, interpolation: InterpolationMethod, extrapolation: ExtrapolationMethod<Pixel>) -> Pixel とか、 extrapolationpadding とかでいいかもだけど
2:05 AM
うん、それはあり得ると思うんだけど今はサポートしてない。
Avatar
まあそれでも extrapolatedTopBy とかでいいか
Avatar
いや、やるなら ExtrapolationMethod を改造かなと思ってる。
2:06 AM
全方位、縦横別、各方位くらいの三つにわけて
2:06 AM
そこにさらに今の値を渡すようなイメージ。
Avatar
ま〜そのほうがいいのかな〜
Avatar
で、利便性のために ExtrapolationMethodcase にも .repeat とかを用意しておいて .all(.repeat) の意味になるとか。で、 .all(.all(...)) とかはダメだから、 .repeat だけを分離した型も必要になる。
2:08 AM
けど、それを言い出したら interpolation も縦は .bilinear で横は nearestNeighbor で、とかあり得るよね。
Avatar
自力でADT上にショートカットを作ってunionっぽく見せるって感じですね
2:09 AM
そうですねえ
2:09 AM
OpenGLでは拡大と縮小のinterpolationをわけられますしね
2:09 AM
あ、この場合は
2:09 AM
Double Indexだから常に拡大の文脈か
Avatar
ん?縮小もあるよ。
Avatar
えーっと、subscriptの場合は。
Avatar
あー、 GL だと拡大するか縮小するかわからないけど、画像を操作する場合は常に拡大か縮小かはわかるね。
Avatar
resizeメソッドがあるならそこでは拡大縮小で処理変えたいとかありえますね
Avatar
あ、 resizedTo の話ね。 (edited)
Avatar
いや、宛先のサイズがビューのサイズとかなら
2:10 AM
で、送り元がpngのサイズなら
2:10 AM
拡縮のどっちになるかはわからんですね
Avatar
なるほど、操作後のサイズが未知というのはあり得るか。
Avatar
操作元が未知もあるかと、アプリのユーザーがアルバムから写真を指定するとか。 (edited)
Avatar
とりあえず、今の InterpolationMethodExtrapolationMethod はそのままで、必要に応じて DirectedInterpolationMethod とかを追加するのが良さそう。 .both(.bilinerar), .each(x: .nearestNeighbor, y: .bicubic) とか。
2:12 AM
ネーミングの話は別として。
2:13 AM
Dictionarysubscript[_:default:] に倣うなら subscript[_:_:interpolation:extrapolation:] とかかなぁ。
2:14 AM
@omochimetaru サイズ未知の件は、 API 呼び出す前にサイズで切り分けてで最悪いい気が。
Avatar
えーでも縦は伸びるけど横は縮むとかもありますよ
Avatar
resizedTo(width:height:) のラベルが難しい・・・
2:15 AM
それは DirectedInterpolationMethod でカバーできる想定で。
2:15 AM
拡大・縮小で指定するよりも軸で指定する方が筋が良さそう。
2:15 AM
すべての組み合わせを用意すると組合せ爆発がすごそう・・・。
Avatar
そうですねえ・・・
Avatar
これが enum じゃなくて sealed class だったら階層的にサブタイピングでうまいことわけられるんだけどね。
Avatar
なるほど
Avatar
なんかその辺はユーザー側で順番にやってくれって感じがしますが。
Avatar
↓とか? InterpolationMethod SimpleInterpolationMethod NearestNeighbor Bilinear Bicubic DirectedInterpolationMethod Both(SimpleInterpolationMethod) Each(SimpleInterpolationMethod, SimpleInterpolationMethod)
2:19 AM
拡大・縮小を考えるとさらなる入れ子が必要だけど、 enum よりはキレイに整理できそう。
2:19 AM
一応、 open でない public なクラスを使えば Swift でも同じようなことはできる。
2:21 AM
resizedTo(width:height:interpolation:) は変な気がするけどなぁ。 interpolatedBy とかじゃなくても、 write(to:format:) と同じで別に気にしなくていい? (edited)
2:22 AM
To の後に width, height, interpolation が並列に並ぶのも気持ち悪い。
Avatar
そもそも角の外側はどっちが優先かとかも考えないとだめな気がしますけど
Avatar
たしかにwww
Avatar
resized(to: Size, interpolatedBy: InterpolationMethod) とすることもできるけど、そうすると Size の扱いが面倒。
Avatar
じゃあ8つの領域にわけて・・・ ・・・
Avatar
ん?そんなことなくない? extrapolation は軸別に考えられるから
2:25 AM
それで外挿された (Int, Int) の点に対して補間するだけでは?
2:26 AM
軸ごとに指定したらダメか (edited)
Avatar
fillingの場合はだめそうだけど
2:26 AM
repeatingとかはサンプリング座標の変換だからいけそう。
2:27 AM
edgingも座標をmaxで止めてるだけだから軸ごとに処理できますね
Avatar
x 方向と y 方向に別々の extrapolation を考えて一意に定まらないケースがなかなか思いつかない。 filling してもいけそうじゃない?
Avatar
Xはみ出したら赤、Yはみ出したら青だとして
2:28 AM
画像の右上は赤?青?
Avatar
あー、 filling 同士は考えてなかった。ダメだ。
Avatar
ですよね
Avatar
その場合は
2:29 AM
境界が斜めになるのでは (edited)
Avatar
まあ、それでもいいですけど、 123 456 789 で123789を青、46を赤、5を元画像 (edited)
2:29 AM
としたい場合は、やる手段はない
2:29 AM
って事になるけど良いか、駄目か、って話だと思います
Avatar
x, y 別指定に .filling はダメとか。さらに階層が増える・・・。
Avatar
あと斜めの場合はちょうど斜めの上のピクセルはどっちにするのかちょっと悩みますね、混色する?
Avatar
リサンプリングじゃないから .repeat とかと概念的に違うんだよなぁ。
Avatar
こういうの考えていくとプログラマブルシェーダは便利だなあと思えてきた
2:31 AM
クロージャを渡せる case custom(f) があって、fが簡単に書ける道具を散らかしておくのが楽かも
Avatar
混色にできる場合はして、できない場合( Bool とか)は .nearestNeighbor の境界上と同じようにどちらかに寄せるとかかな。
2:32 AM
@omochimetaru .custom も考えてる。
Avatar
customさえあれば細かい場合分けは全部捨てちゃってがんばってクロージャ書いてねで
Avatar
単一ピクセルだと意味ないけど、↓みたいにするときに便利。 image[-100...100, -100...100, extrapolatedBy: .custom(...)]
Avatar
どうにかなりそう
2:34 AM
(細かいってのはさっきから言ってるコーナーケースのことです 単純なfillとかはのこして。
Avatar
interpolation も extrapolation も custom を作ってとりあえずごまかすか。
Avatar
コメントで // TODO: implemenet case custom って書いといて
2:35 AM
困った人は自分で書く
2:35 AM
スタイル
2:35 AM
あ、あれです、customケースがです
2:35 AM
caseを追加するという意味じゃなくて。
Avatar
ん? InterpolationMethod とかに case custom を追加する話じゃないの? (edited)
Avatar
まあ作っておけばいいか。
2:36 AM
いや、なんか、 case custom追加するのは正しい方向だと思うけど、ユーザーが困ってからでいいのかなと思った。
Avatar
それぞれ .custom((Double, Double) -> Pixel).custom((Int, Int) -> Pixel) を追加するだけなので大変ではない。
Avatar
まあそうか
Avatar
あー、
2:38 AM
interpolation の方を
2:39 AM
.custom((Double, Double, (Int, Int) -> Pixel) -> Pixel) にしないとダメそう。
Avatar
2:40 AM
そうか、サンプリング座標変換もあるから。
Avatar
でも外挿と組み合わせないときは (Int, Int) -> Pixel が要らないんだよな。
2:40 AM
面倒だ・・・
Avatar
本質的にややこしいですねえ
Avatar
やっぱ .custom は保留しよう・・・
Avatar
ww
Avatar
extrapolation にしても、 resample するだけなら (Int, Int) -> (Int, Int) にできるしね。
2:41 AM
.filling 以外はこれで表現できる。
2:42 AM
.filling のために ExtrapolationMethod がジェネリックになってるのもややこしいといえばややこしい。
Avatar
あーそれだけなんですね。
2:42 AM
型として分けても良いかもしれませんねえ
2:42 AM
サンプリング補間層と値補間層。
Avatar
でも API として複雑すぎると思うんよね。
2:43 AM
interpolation との組み合わせ爆発もするし。
2:43 AM
enum じゃ階層にしてすべて ExtrapolationMethod のサブタイプとかもできないしね。
Avatar
指定したくなった時に指定できて、デフォルト値がうまく埋まってれば 良いとこ取りができて
2:44 AM
デフォルト引数とかで埋められない場合、構築済みのある種のパターンの値を返す static func があると
2:44 AM
そういう感じにできそう。
Avatar
Int だったら 0 とかそういうこと?
2:45 AM
それは後付した protocolpublic にしないといけない・・・。
Avatar
えーっと
Avatar
enum Foo { case foo case bar case piyo(String) case fuga(Int) static var specificFuga1 = Foo.fuga(1) } Foo.specificFuga1 こんな感じかな
Avatar
サンプリング補間関数 と 値決定関数があったとして、 1層: 座標変換(エッジのピクセルを取るなど) sample: (Double, Double) -> (Double, Double) 2層: ↑の座標がはみ出していたときは 入力Pixelがnil value: (Pixel?) -> Pixel 3層: ↑のPixelを(4つや8つ)受けて nearest neighbour などの適用
2:49 AM
っていうデータパスになっていて
Avatar
よく使うプリセットはstatic varなりstatic funcなりで使いやすいAPIを提供しておいてデータ構造は素直なものになっていれば
Avatar
2の関数については Pixel Protocol に 空の .init() を 制約しておけば、デフォルト値がとれるかな
2:51 AM
さっきの filling だけが2層の関数で、他は1層なんですよね。
Avatar
@omochimetaru そうです。
2:51 AM
が、 Pixel プロトコルを作ってしまうと
2:52 AM
一番良く使う UInt8 とか Float にプロトコルを後付しないといけないし
Avatar
あーでもだめだこれ、はみ出した方向別に色が違うとかができないな 2層は value: (Int, Int, Pixel?) -> Pixel か?
2:53 AM
一番良く使う UInt8 とか Float にプロトコルを後付しないといけないし
ああ〜
Avatar
RGBA<Channel> とかは付けれないし RGBA<UInt8> とかだけに付けるには conditional conformance がいる。
2:53 AM
今も内部的にはそういう目的の _Summable っていうプロトコルを持っていて
2:53 AM
その上に内部的にそれを使う層を gyb で生成して、
2:54 AM
公開された API で見るとプロトコル後付されてないように見せてる。
2:54 AM
conditional conformance がサポートされたら、プロトコル外付けを許容すれば gyb を大分排除できるので検討の余地はある。
Avatar
よく使うプリセットはstatic varなりstatic funcなりで使いやすいAPIを提供しておいてデータ構造は素直なものになっていれば
そうそう、そこで言いたかったのはそういうこと、サンプルコード含め。
Avatar
今は _Summablezero みたいなのを持ってて
2:56 AM
たとえば roteated(by:) では斜めになったときの背景を zero で埋めてる。( gyb で各型ごとに extrapolatedBy: .zero) を付与して呼ぶメソッドを大量生成してる。)
Avatar
Int だったら 0 とかそういうこと?
(でもこの回答が1ステップ先の議論になってた)
2:57 AM
あれ?任意の型のときはどうしてるんですっけ?
2:57 AM
そのzero。
Avatar
任意の型のときは rotated(by:) は使えなくて
2:57 AM
rotated(by:extrapolatedBy:) じゃないと使えない。
Avatar
あ〜
2:58 AM
なるほどお・・・
2:58 AM
ExtrapolationMethodは、Pixel型をPixel型クラスに所属させるためのwitness定義のように振る舞っているわけですね
2:58 AM
Scalaならimplicitに渡されれる型(の型クラスcofnromance)に関する付属情報が明示的にわたされてるわけだ (edited)
2:59 AM
アドホックなwitness。
Avatar
ちなみに、 numeric な型だと rotatedinterpolatedBy 省略で .bilinear が使われるけど、それ以外では .nearestNeighbor が使われるとかなってる。
3:00 AM
本当は .nearestNeighbor ですらなくて、それ相当の計算だけど。 InterpolationMethod が使えるのは _Summable だけだから。( Bool.bilinear しようがない) (edited)
3:01 AM
ただの Numeric でもいけなくて、 UInt8 とか普通に足して平均とったらオーバーフローするから
3:01 AM
必要に応じて一度 IntDouble に変換する処理とかがあって、そのあたりが全部 _Summable で抽象化されてる。複雑・・・。
3:02 AM
でも、実装は複雑だけど、 public な API はシンプルに保ててるはず。
3:03 AM
他にも↓で COW と box 方式の type erasure を使ってたり、 EasyImagy の実装が( gyb や protocol extension 含め) Swift の技の見本市みたいになってる・・・。 https://github.com/koher/EasyImagy/blob/dev-0.4.0/Sources/EasyImagy/AnyImage.swift (edited)
EasyImagy - Makes it easy to process images in Swift
3:06 AM
AnyImage も元は要らなかったんだけど、 image[-100...100, -100...100, extrapolatedBy: ...] の結果を ImageSlice で返そうとすると、 ImageSlice が内部に持つのが Image だけじゃダメになって、 ImageSliceAnyImage を持つ必要に迫られた。
Avatar
見本市w
Avatar
https://forums.swift.org のアカウントがリセットされている?
Swift Forums
5:08 AM
SignUpして変更できた
Avatar
"with GitHub" を押すのは過ちを繰り返すことになるかな?土曜くらいに Username 変更できるようになってたけど。
Avatar
Username葉変更できるけどinitialは拾ってきてくれないですね
Avatar
普通に GitHub 連携して後から変更できた🙂
Avatar
数日前に「消去した」ってメッセージが出てましたよ。>forums (edited)
👍 1
Avatar
Swift Advent Calendar の 12/12 分が投稿されてないようです。そのため、ランキングにも参加できていません。どなたか代わりに投稿しませんか? https://qiita.com/advent-calendar/2017/swift
Taylorじゃない方のSwiftです( ´・‿・`)
Avatar
書きたい…時間あったら…(白目
Avatar
その1が埋まってないならその2の人が引っ越したらいいんでは?
Avatar
ちなみにすでに2つものAdvent Calendar記事遅れてます…
Avatar
その2は穴が5こぐらいあったから両方埋まらないよりはマシ
Avatar
なんとか週末に遅れを取り戻したい
2:43 AM
書けたら書きます
👍 1
Avatar
loveeさんはその2にいるのか。
Avatar
います、1が埋まってたから2の方に登録してました
2:44 AM
でもどうせなら2と別の記事書きたい
Avatar
引っ越しでもいい気も。
Avatar
まあ別に両方書いちゃダメなんてことはないので、週末に頑張って仕上げます
👍 2
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
My first evolution proposal is under review - SE-0193 cross module inlining and specialization: https://t.co/MzUWxtYumh
5:51 AM
slavaにとって実は1発目らしい
5:51 AM
これ読みましたけど abiPublic は実態をストレートにあらわしていて良い命名だと思った
Avatar
internal なメソッドでも @abiPublic でインライン化できるのか。
Avatar
そうです!
6:02 AM
前回の下書きproposalだとinlineableだけで投げられたけど、結局 両方一気に来ましたね。
Avatar
それがないと辛いもんね。
Avatar
だいぶ遅くなったけどなんとか書きました(´ཀ`」 ∠) https://qiita.com/lovee/items/257abf17cccea8293d0f

はじめにのはじめに

大変遅くなって申し訳ないです。この記事は Swift その2 Advent Calendar 2017 23 日...
👏 7
Avatar
Decimal型を有効活用してる方いらっしゃいますか? APIが使いづらいし、表示したいだけならNumberFormatterで事足りるし、 一体こいつの存在意義はあるんだろうか…と思いまして、 みなさんの利用例が気になりました 辛いAPI👇 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.1235
Avatar
Kishikawa Katsumi 12/28/2017 12:38 PM
典型的なのは金額の計算ですね。浮動小数では扱えないのでDecimalを使います。レジの実装とか。あとは電卓など。
Avatar
NSDecimalNumberとは別物なんですか?
Avatar
Kishikawa Katsumi 12/28/2017 12:40 PM
DecimalとNSDecimalNumberはDateとNSDateの関係と一緒じゃないですかね。
Avatar
Doubleで大抵は誤差が出ないだろうけれど、その万一も防止したい場合に使う、という感じでしょうか
Avatar
金額は誤差出ちゃだめな世界なのでDecimalですね
Avatar
Kishikawa Katsumi 12/28/2017 12:41 PM
やってみたらわかりますけどDoubleだと全然合わないですよ。 (edited)
😮 1
Avatar
そもそも浮動小数点は…
Avatar
NSDecimalNumber,BigInt的な精度があるわけじゃないので,精度でなくて使うのやめた,みたいな謎の記憶がある
Avatar
Kishikawa Katsumi 12/28/2017 12:42 PM
BigInteger的には残念ながら使えないですね。覚えてないですけど何兆くらいまでじゃなかったでしたっけ。
Avatar
中身は64bitIntだった記憶
Avatar
NSDecimalNumber, 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.
Avatar
DecimalはReferenceConvertibleではないので、DateとNSDateの関係とは微妙に違いそうですね ただNSDecimalNumber用のenumを使い回してはいるようです https://github.com/apple/swift-corelibs-foundation/blob/ee61823ae71f4c4f9ca157fd290c4b7de915b2a4/Foundation/Decimal.swift
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
Avatar
10進計算だけど表現は仮数部と指数なんで浮動小数ですね
12:46 PM
十進数表記の少数が誤差なく表現できる(桁が足りてれば)
Avatar
Kishikawa Katsumi 12/28/2017 12:46 PM
なるほど、そういう話です?つまりNSDecimalNumberのようにはDecimalは使えない?
Avatar
2進少数では0.1などはそもそも表現できない
Avatar
DecimalNSDecimal で c 構造体 みたいです。
Avatar
Kishikawa Katsumi 12/28/2017 12:47 PM
あ、NSDecimalか。
12:47 PM
NSDecimalを使うことはほとんどないはずなので、その関係だとするとDecimalをほとんど使わないというのは普通だと思います。
Avatar
Decimalが3種類あるのか
Avatar
Kishikawa Katsumi 12/28/2017 12:48 PM
で、私は浮動小数と固定十進の一般的な使い分けの話かと思って話しました。
Avatar
仮想通貨のアプリ作ってる人は何使ってるんだろ
Avatar
Kishikawa Katsumi 12/28/2017 12:48 PM
基本単位が大きいですもんね。
Avatar
無限精度少数を使って適切に丸めるのがセオリーかと
Avatar
Kishikawa Katsumi 12/28/2017 12:49 PM
NSDecimalNumberでは足りなさそう。
Avatar
0.00000012BTCとか結構エグい要求ありますよね
Avatar
https://developer.apple.com/documentation/foundation/nsdecimalnumber?language=objc の注意見ると Decimal は NSDecimalNumber にブリッジと書いてあるな。 (edited)
Avatar
誤差が出ると困る、全部サーバーでやるのかな
Avatar
いや、無限に桁が増えていくとどうしようもないから
12:50 PM
金融の世界では少数何桁以下はどういう計算ではどっちに丸めるとか
12:50 PM
決まってるはず
12:50 PM
BTCに関して言えば桁数の最小単位ある
Avatar
なるほど
Avatar
Kishikawa Katsumi 12/28/2017 12:52 PM
レジの消費税はどっちに丸めるかは店の裁量に任されています。(だから作るのが面倒とも言える)
😫 1
Avatar
ひゃー
Avatar
お、じゃあ、客に対しては切り上げて請求して
12:52 PM
会計上は切り下げて記録しておけば
12:52 PM
1円ずつ脱税できますね
Avatar
まずいですよ!!
12:53 PM
攻殻機動隊を思い出した
Avatar
Kishikawa Katsumi 12/28/2017 12:54 PM
まあ、Doubleの誤差とは別に支店がめっちゃあるとかだったらだいぶ違ってきますね。
Avatar
消費税は基本的に内税での計算のはず。 売り手は決済毎ではなく期間内売り上げに応じた税を払う。
Avatar
あ〜 最後にまとめて8%求めるのか。
Avatar
そういえばAppleが消費税かっ引いてくれてますが、売り上げ1000万以下なら払わなくていいはずで、取り戻したりできるんですかね?
12:55 PM
swift関係なくなってきたw
Avatar
Kishikawa Katsumi 12/28/2017 12:57 PM
消費税の丸めが店の裁量というのは1円以下の端数の話です。
Avatar
も、盛り上がってるとこ済みません… Swiftの話だけまとめると、
  • Decimalは固定小数点数
  • 38桁の精度までは保証するアルゴリズムって点ではNSDecimalNumberと互換性のある型
って感じですね
1:01 PM
と思ったら、 >https://developer.apple.com/documentation/foundation/nsdecimalnumber?language=objc の注意見ると Decimal は NSDecimalNumber にブリッジと書いてあるな ReferenceConvertibleじゃなくてもブリッジできるんですね let dec1 = Decimal(double) // 3.123456000000000512 let n = (dec1 as AnyObject) type(of: n) // __ObjC.NSDecimalNumber.Type
Avatar
いや、どれも浮動小数だと思います
Avatar
_ObjectiveCBridgeable っていう ReferenceConvertible の一個下のレイヤーに準拠してますね。
Avatar
正確にいうなら、内部的には浮動小数点数だけど、桁数固定小数点数に見せるラッパー
1:03 PM
なるほど
Avatar
いえ、見えないと思います
1:04 PM
浮動小数の特性として、でかすぎる数と小さすぎる数を足し合わせると
1:04 PM
表現桁の幅が足りなくなって何も足さなかった結果になるんですが
1:04 PM
それがDecimal族の間でも起きるはず
1:05 PM
Decimal族が提供してる価値は、十進数基数になってることで
1:05 PM
0.1が0.1になることです
Avatar
なるほど
Avatar
FloatとDoubleは2進数少数なので、 0.5や0.25や0.125はあらわせるけど
1:06 PM
0.1や0.12や0.123はあらわせないです
1:07 PM
Decimal族ならあらわせる。
Avatar
Kishikawa Katsumi 12/28/2017 1:12 PM
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)
1:13 PM
^ おもちさんの言ってることってこういう話ですよね? @omochimetaru DecimalはDoubleと同じ結果にはならないみたいですよ。
1:14 PM
123456789000000000.00000000000000000000 1.00000000000000000000 123456789000000000.00000000000000000000 123456789000000000 1 123456789000000001
Avatar
let decimal1 = Decimal(string: "123456789012345678901234567890")! let decimal2 = Decimal(string: "0.0000000000000000000000000001")! print(decimal1) // 123456789012345678901234567890 print(decimal2) // 0.0000000000000000000000000001 print(decimal1 + decimal2) // 123456789012345678901234567890
Avatar
Kishikawa Katsumi 12/28/2017 1:15 PM
おお、おっしゃる通りですね。
Avatar
仮数部の表現精度が38桁あるので、 @Kishikawa Katsumi さんのサンプルだとまだセーフ
Avatar
Kishikawa Katsumi 12/28/2017 1:16 PM
なるほど。
Avatar
let 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!
Avatar
Kishikawa Katsumi 12/28/2017 1:16 PM
私の環境でも確認しました。
Avatar
↑このように、trueになるので、文字列化するときに省略されているのではなくて、情報として消えてる。
😱 1
1:17 PM
言い換えると、 Decimalに 0.0000000000000000000000000001 ずつ足していく無限ループを書くと、どっかで増加が止まるってことですね。
1:19 PM
https://ja.wikipedia.org/wiki/倍精度浮動小数点数
通常の数(正規化された数)の精度は、53ビット相当[1](十進に直すと約16桁)である。
Avatar
1スタートでも38桁超えたら増加は止まる?
Avatar
Double型だと仮数部が16桁しかないですね
1:21 PM
Doubleの指数部は11bitだから-1024〜+1024倍が表現できるけど
1:21 PM
Decimalは > –128 through 127. ってかいてあるから、 指数部が 2^8 で8ビット
1:23 PM
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!
1:23 PM
40桁で増加しなくなった。39桁だとまだ増加した
Avatar
おー もはやガヤしかできないですが面白いです
Avatar
指数部で3bit節約しても仮数部を10進38桁にするには全然ビット数が足りないな?
1:28 PM
https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/Decimal.swift fileprivate var __exponent: Int8 fileprivate var __lengthAndFlags: UInt8 fileprivate var __reserved: UInt16 public var _mantissa: (UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16) 160bit
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
1:29 PM
import Foundation print(MemoryLayout<Decimal>.size) // 20
1:29 PM
20バイトですね。
1:29 PM
Decimal1個でFloat5個分のメモリ容量を取る。
Avatar
let 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)
Avatar
65536 * 1883 + 52501 = 123456789 ですね
1:35 PM
length 2 は mantissa.0, .1 までを使うことを表してて、exponent = 1 だから それに x10 が1個くっついて1234567890になる。
Avatar
なるほど 仮数そういうふうに見るんですね
Avatar
最大値と最小値はこれか 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)
Avatar
と思ったらもう一桁いけた 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は
exponent is an integer from –128 through 127.
だとすると、leastNonzeroMagnitude, leastNormalMagnitude の実装もしや間違ってるのでは https://github.com/apple/swift-corelibs-foundation/blob/ee61823ae71f4c4f9ca157fd290c4b7de915b2a4/Foundation/Decimal.swift#L120
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
Avatar
あれ?ほんとだ、もう一個いけそうですね
2:27 PM
ああ @takasek さんの書いてるテストが実際に-128まで攻めたやつなのかw
2:28 PM
This value compares less than or equal to all positive numbers, but greater than zero.
2:29 PM
他のどんな正の数よりも小さいか等しいがゼロよりは大きい だから
2:29 PM
しかし Decimal.leastNormalMagnitude > truelyLeastDecimal() こうなってしまうので
2:29 PM
明らかにバグですね
Avatar
やった見つけた
Avatar
すげえw
Avatar
↓書いて思ったんですが、 Swift の文字列補間で CustomStringConvertible じゃないものでも文字列に埋め込めるの良くなくないですか?何でもとりあえず文字列にしたいニーズはあるとして、それはデバッグ用にそういう関数を用意すれば良いだけに思います。 https://qiita.com/koher/items/6c855ddbda8797af4605
あけましておめでとうございます。新年早々おもしろツイートがバズっていました。 おっ、nu...
1:38 AM
CustomDebugStringConvertible を分けてる意味がなくなっちゃってる気が。 printAny をとれるのも微妙。
Avatar
omochimetaru 1/9/2018 1:38 AM
CustomStringConvertibleとCustomDebugStringConvertibleとあとなんかOutputPRintableだったかなんかへんなやつがあって
1:38 AM
その3つの判定を動的にやったあと
1:38 AM
更に、そのどれでもない場合に
1:39 AM
dump() と同じような挙動で出力する挙動があって
1:39 AM
それが↑のOptional()の形式に至る
Avatar
OptionalCustomDebugStringConvertible だったと思うから
Avatar
omochimetaru 1/9/2018 1:39 AM
あ、そうなのか。
Avatar
それで『 Optional(2018)年』になってる。
Avatar
omochimetaru 1/9/2018 1:40 AM
挙動として String.init(describing: Any) だったはずなんで
1:40 AM
個人的にはCustomStringConvertibleだけが埋め込めるようにして、
1:40 AM
そうでないものを埋め込みたい場合には String.init(describing: x) って書けばいいんじゃねえかと
1:40 AM
おもってます
Avatar
うん、そう思う。
Avatar
omochimetaru 1/9/2018 1:41 AM
それか "\debug() " みたいなのでもいいけど
Avatar
文字列補間になんでも埋められるのは意図した仕様なのかなぁ。初期の頃に適当にやったのが残ってそう。
Avatar
omochimetaru 1/9/2018 1:41 AM
あ、いや
1:41 AM
Optional は CustomDebugStringConvertible だったと思うから
これってほんとだっけ
1:41 AM
Optional<T> の Tのconformanceに依存するから
1:41 AM
なんかそこが謎の動的判定ロジックが書いてあるんですよ
Avatar
1> let a: Int? = 42 a: Int? = 42 2> a.debugDescription $R0: String = "Optional(42)" 3> a is CustomStringConvertible $R1: Bool = true
Avatar
omochimetaru 1/9/2018 1:42 AM
TがCustomDebugStringConvertibleならOptional<T>もCustomDebugStringConvertibleみたいな。 Conditional conformanceできれいにしたいってコメントが入ってた
Avatar
あれ?
1:43 AM
なんで CustomStringConvertible が true になるんだ??
1:43 AM
4> a is CustomDebugStringConvertible $R2: Bool = true
1:43 AM
5> a.description error: repl.swift:5:1: error: value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'? a.description ^ ?
1:44 AM
5> func debugPrint<T: CustomDebugStringConvertible>(_ value: T) { print(value) } 6> debugPrint(a) Optional(42)
Avatar
omochimetaru 1/9/2018 1:44 AM
Optionalの特別扱いロジック関係のバグな気がする
Avatar
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)
1:46 AM
とりあえず、 OptionalCustomStringConvertible ではないけど CustomDebugStringConvertible ではある(↑)。 (edited)
Avatar
omochimetaru 1/9/2018 1:46 AM
どちらでもないってこと?
Avatar
日本語まちがえたw (edited)
1:46 AM
後者ではある。修正した。 (edited)
1:47 AM
↓を見ても CustomDebugStringConvertible だけ書いてある。 https://developer.apple.com/documentation/swift/optional (edited)
1:49 AM
Conditional Conformance 導入されたらこれも Conditional になるのかな? extension Optional : CustomDebugStringConvertible where Wrapped : CustomDebugStringConvertible { ... }
Avatar
Debug だから、別に String.init(describing) で変換すればいいのか。 (edited)
Avatar
omochimetaru 1/9/2018 1:50 AM
public init<T: TextOutputStreamable> (stringInterpolationSegment expr: T) public init<T: CustomStringConvertible> (stringInterpolationSegment expr: T) public init<T: TextOutputStreamable & CustomStringConvertible> (stringInterpolationSegment expr: T) (edited)
1:51 AM
曖昧さ回避のための&版オーバーロードで中身はTextOutputStreamable扱いだった
1:52 AM
public init<T>(stringInterpolationSegment expr: T) { self = String(describing: expr) } CustomDebugStringConvertibleのケースはこれに行きそう (edited)
1:53 AM
さっきのCustomStringConvertibleについては is だけなぜかtrueになるけど
1:53 AM
ジェネリック関数呼び出しの時の制約解決では false 扱い?
Avatar
istrue はバグな気がする。
1:56 AM
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 }
Avatar
omochimetaru 1/9/2018 1:58 AM
なるほど
1:59 AM
てか、元記事の話なんですけど
1:59 AM
警告が出てるのに無視してるのが最大の問題なのは置いといて
1:59 AM
もし、null安全言語じゃなかったら
2:00 AM
警告を出すこと自体が不可能ですよね?
Avatar
@omochimetaru はい。というか、非 null を区別できないから『Optional(2018)年』自体が起こり得ない。『null年』は起こり得るけど。
Avatar
omochimetaru 1/9/2018 2:12 AM
ですよね。 だから、nullableとnonnullが静的に区別できる機能が言語にあるからこそ、 コンパイラが「nil年」を出す可能性を指摘できるようになった。 それでも無視した。 って状況なので、何も悪くなってないと思う・・・
2:13 AM
「nil年」が出る可能性がある事と「Optional(2018)年」が出る可能性がある事は同一の警告として現れる。 (edited)
Avatar
はい、何も悪くなってないです(良くなってます)。
4:22 AM
でも、最初からコンパイルエラーならこんな問題は起こらなかったし、 String(describing:)debugDescription すればいいんだから、直接埋め込める必要はない気がします。あえて言えば初心者が混乱するくらい??
Avatar
CustonStringConvertibleじゃない場合はコンパイルエラー、半年前ぐらいに着手したけどワーニングがエラーになったまま放置してた
4:23 AM
本来の関係ないワーニング
Avatar
omochimetaru 1/9/2018 4:24 AM
はい、何も悪くなってないです(良くなってます)。
ですよね〜
あえて言えば初心者が混乱するくらい??
コンパイルエラーのメッセージとして 「String(desciribing:) 使ったら?」って出せばいいからそこはダイジョブそう
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
4:32 AM
たとえば BoolValueEnumerable でいいし、 ValueEnumerable な associated value を持つ case があってもその enumValueEnumerable でいい気がする。
4:33 AM
enum Foo { case bar case baz(Bool) }ValueEnumerable になりたかったりしないかな・・・。
Avatar
omochimetaru 1/9/2018 4:34 AM
bar , baz(false), baz(true) の3要素になるってことですか?
4:35 AM
bazを受け付ける変数の型がうまく書けなくないですか?
4:35 AM
結局Fooになっちゃうからbazのcaseで(Bool)を剥がすパターンマッチが必要に。
Avatar
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).
4:37 AM
この一つ目のルールに、 associated value が ValueEnumerable のときは生成で良い気が。 CodableCodable なプロパティを持っている場合と同じように。
4:38 AM
@omochimetaru
bazを受け付ける変数の型がうまく書けなくないですか?
これはどういうこと?
4:38 AM
FooValueCollection が得られれば良いのでは?
Avatar
omochimetaru 1/9/2018 4:39 AM
for x in Foo.allValues { } みたいに書けるようになっても
4:40 AM
あ〜いやいいのかな
4:41 AM
if x == .bar { ... } if case .baz(false) = x { ... } こういう感じか。
Avatar
単に全通り列挙がしたいんじゃないのかな?
Avatar
omochimetaru 1/9/2018 4:42 AM
なんか例えばUIのプルダウンリストを作ったりする時とかがありますね
Avatar
↓とかできたら便利かも? struct Card : ValueEnumerable { let suit: Suit // Suit : ValueEnumerable let number: Number // Number : ValueEnumerable } Card.allValues (edited)
Avatar
omochimetaru 1/9/2018 4:43 AM
それってallValuesの型はなんですか?
Avatar
[Card]
Avatar
omochimetaru 1/9/2018 4:43 AM
あ〜組み合わせ全列挙ってことか
Avatar
正確には Card.ValueCollection
Avatar
allValuesが欲しい場面は結構あって、それは必ずしもenumとは限らないのは確かに
Avatar
omochimetaru 1/9/2018 4:44 AM
Suit x Number が全部取れると
Avatar
組み合わせ列挙とかほしい場面ありますね
Avatar
書いてあった。 To 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.
Avatar
omochimetaru 1/9/2018 4:46 AM
ほんとだ。
4:46 AM
まあこういうのっていきなり一般論ぶちあげると議論が発散するからトピックしぼった提案から投げるパターン多いですよね
Avatar
これって前の Int に精度を明示すべきかどうかみたいな話とも関係してるんじゃないかなぁ。 IntValueEnumerable であってほしくないけど(概念としての整数は無限の要素を持つので) UInt8ValueEnumerable であってほしい。同様に考えると Int32UInt32ValueEnumerable であってほしいけど、 Int を associated value に持つ enumValueEnumerable であってほしいわけじゃなくて、 IntInt32 の使い分けはやっぱり必要な気がする。
4:49 AM
トピックしぼった提案から投げるパターン多い
Never の bottom 化早く・・・
Avatar
omochimetaru 1/9/2018 4:50 AM
おお、たしかに精度無しIntと精度有りIntはそういう違いがあるのか!
4:51 AM
まあ「そのコンパイル時のビット数での要素数になる」って実装もありそうだけど。
Avatar
Kishikawa Katsumi 1/9/2018 4:51 AM
無限を扱うのは特殊ケースだからそのための特別なものがあればいいと思います。Int = Int64にするのが妥当なところじゃないですかね。
4:51 AM
一貫性を考えるならInt無くしてもいい。
4:52 AM
無限の数というのをIntを含むInt8 〜Int64のファミリーとするのは無理がありますね。 (edited)
Avatar
うーん、僕は allValues ができる Int64 とできない Int を区別しておきたいですねぇ。
4:53 AM
Int64 だと countInt で表せないという話は別として)
Avatar
Kishikawa Katsumi 1/9/2018 4:55 AM
どうやってもメモリとか何らかの限界はあるわけで、大きなものが必要ならInt64、Int128, Int256でよくて、そうじゃない純粋に整数の性質を表したIntというのは使うところほとんどないと思います。 (edited)
5:00 AM
いや違うかな。書いてて揺らいできた。
Avatar
うーん、好みの問題かもしれませんが、僕はコードとして単に整数を意図しているのか、それとも精度が重要な意味を持つのかを区別したいですね。単に整数を使いたいときに Int32Int64 かの選択が揺らぐようなのをなくしたいです。
Avatar
Kishikawa Katsumi 1/9/2018 5:01 AM
単に整数を使いたいときに Int32 か Int64 かの選択が揺らぐようなのをなくしたい
5:02 AM
^ これは下は問題にならないわけですよね。どっち使っても収まるのであればどっちでもいいので。で上はやっぱり限界はどこかにある以上、決まってないと使いづらいですね。外への入出力にも使えないし。
5:03 AM
とさっき書いたときまではこういう意見でした。
Avatar
外への入出力を伴うときに、明示的に Int32 等に変換して使いたいイメージですね。
5:03 AM
あと、 Int にはビット演算とかオーバーフローとかもしたくないです。
Avatar
Kishikawa Katsumi 1/9/2018 5:03 AM
ただ文字列とかは長さの限界を意識することはほとんどないので、もう少し性能が上がったらそれでもいいのかもしれないとも思います。
5:06 AM
確認なんですけどInt64ないしはInt128だけしかなかったら良いと思いますか?
5:06 AM
単に整数を使いたいときに Int32 か Int64 かの選択が揺らぐようなのをなくしたいというのは私はそれでいいと思っています。
5:07 AM
無限の大きさを持つ数というのは別の問題が出てくるはず。
Avatar
Int64ないしはInt128だけ
良いと思わないです。選択のゆらぎの問題は確かにそれで防げますが、それは例が十分じゃなかったです。
(edited)
5:08 AM
DB に保存するエンティティを考えると難しいですね。さすがに「文字列とかは長さの限界を意識することはほとんどない」としても整数でそれをやるのは辛いでしょうし。
5:10 AM
DBの入出力は IntXX でやって、アプリ用に Int を使った型に変換するのか、それともエンティティレベルで Int にして、 DB に保存するときにエラーにしてしまうのか。
Avatar
Kishikawa Katsumi 1/9/2018 5:11 AM
私はIntみたいなプリミティブなものはそれでしょうがないと思います。無限の数は何らかのデータ構造の型でやれば良いのではないでしょうか。
Avatar
Swift の Int に Java の BigInteger とか Ruby の整数のような無限精度になってほしいわけではないですが、コードの書き手が単なる整数を意図しているのかそうではないのかを型として区別しておきたいという感じですね。
Avatar
Kishikawa Katsumi 1/9/2018 5:14 AM
十分に小さいから32でも64でもいい、32では入らないけど64あれば十分、それ以上という以外の意図で何か重要なことがありますか?
Avatar
たとえば、 UInt8 だとオーバーフローを利用した計算とかもよくやると思うんですけど、 Int32 ではそれは OK だけど Int ではやりたくないです。そこは明示的に Int32 に変換してから処理したいです。
Avatar
Kishikawa Katsumi 1/9/2018 5:15 AM
それはおっしゃる通りInt32を使うべきだと思います。
5:16 AM
私は最初は論点はIntが実行環境によって変わることを問題にしていたと思っていて、そこは私も同意です。
Avatar
Int が実行環境によって精度が変わるかどうかは別として、 Int32Int64 より strict な型がほしいという感じですね。
Avatar
Kishikawa Katsumi 1/9/2018 5:17 AM
なるほど。そこじゃないですか。
Avatar
たとえ Int が 32 bit に固定されていたとしても、 Int に対してオーバーフローを利用した演算はしたくないです。
5:18 AM
感覚的なもので具体的なメリットを挙げづらいですが、そこを区別していないことによって被るデメリットがある気がしています。
Avatar
Intが無限長で有限長を使いたいならInt32然りInt64を使う、というのが個人的には一番しっくり来る
5:19 AM
効率の良いプログラムを書きたいなら長さを指定して考えよう、という世界観
Avatar
Kishikawa Katsumi 1/9/2018 5:19 AM
IntがBigIntのような名前ならいいと思います。
Avatar
@tarunon うーん、そこは僕は違ってて、 Int が現実的に 32bit や 64bit なのには不満はないです。無限精度にはなってほしくない。
5:21 AM
乏しいデメリットですが、さっきの ValueEnumerable の例で言えば func combination<T: ValueEnumerable, U: ValueEnumerable>(_ a: T.Type, _ b: U.Type) -> [(T, U)] みたいな関数があったときに
5:21 AM
UInt8Int32Int64ValueEnumerable だけど Int は違ったら
5:22 AM
combination(Int, Bool) みたいなのを防げます。
5:23 AM
でも、 combination(UInt8, Bool) はやりたいですし、 combination(Int32, Bool) も同様に認められるべきだと思います。
Avatar
Kishikawa Katsumi 1/9/2018 5:24 AM
その例でも私はやっぱりIntをIntファミリから外してBigIntなりの別の型の方がいい気がしますが、それでは問題がありますか? (edited)
Avatar
僕は IntBigInt (無限精度)になってほしいわけではなくて、今のままであってほしいと思います。
5:26 AM
そして、コード中のほとんどの Int は単に整数であってほしいだけだと思うので、基本的には制限された Int を使って
5:26 AM
Int32 特有の操作をするときだけ明示的に Int32 に変換して使えたらいいんじゃないかと思います。
Avatar
整数としての性質を使いたいだけなら protocol の BinaryInteger 使えばよい、という話ではない? (edited)
Avatar
Int は最もよく利用する型なのでパフォーマンスも求められると思います。 BinaryInteger として existential で扱うのは許容できないかと。たとえば、 countInt を返しますが、これは整数を表していると思います。しかし、これが BinaryInteger になるのは許容できないのではないかと。
Avatar
Kishikawa Katsumi 1/9/2018 7:12 AM
^ 意見が一致してる気がしますね。何が違うんだろう。
Avatar
僕は今の Swift の仕様に概ね満足しているのでいいのですが、 IntUInt~ が使えるのとかは違和感を感じますね。
Avatar
しっくりきた
Avatar
1> let n: UInt = 0 n: UInt = 0 2> ~n $R0: UInt = 18446744073709551615
7:13 AM
↑これはできなくていいんじゃないかと思います。
7:13 AM
これがやりたいなら、 3> ~(UInt64(n)) $R1: UInt64 = 18446744073709551615 とすべきかと。
7:14 AM
@Kishikawa Katsumi さんと僕の意見の違いは、 @Kishikawa Katsumi さんはそもそも Int のビット数を固定しなかったのが良くなかったという意見なのに対して、僕はそれでよかったと思ってるところでしょうか。そして、その裏には、 Int は整数だからという気持ちがあります。
Avatar
Kishikawa Katsumi 1/9/2018 7:15 AM
あと私はIntはInt32かInt64だと思っているところでしょうね。
Avatar
Int のビット数が固定されないことで、↑のようなビット演算が良くない行為となり、明示的な変換が求められます。ただ、もう少し踏み込んで Int には ~&+ 等はなくてよかったと思います。
Avatar
Kishikawa Katsumi 1/9/2018 7:16 AM
上の例は私はIntはInt64なので別になんの問題もないように見えています。
Avatar
僕の中では 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)
Avatar
omochimetaru 1/9/2018 7:23 AM
え、マジすか?
Avatar
結局どこかには限界があって、通常の演算では 64 ビットだろうがオーバーフローすることはないですし、程度問題だと思います。
Avatar
Kishikawa Katsumi 1/9/2018 7:25 AM
実際には無限ではないという方が普通に感じるので、 Int はほぼ無限精度整数というのがわからないですね。それは特殊用途ではないですか?
Avatar
「気にしなくてよい」はウソかもですね。 (edited)
7:27 AM
本当は逆で、 BigInteger で何であれ気にしないといけない、かもしれません。 (edited)
7:28 AM
ただ、 99% くらいの用途では問題にならないので、 Int だろうが BigInteger だろうがあまり関係なくどちらも整数と思えるという感じです。
7:29 AM
@omochimetaru irb とか python の REPL で(一つ減らして) 2 ** (2 ** (2 ** (2 ** 2))) と入力すると楽しいことになります。
Avatar
omochimetaru 1/9/2018 7:31 AM
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 => Float
7:31 AM
ほんとだ。まあその前の段階で死ぬほど桁数がでかいから やったらメモリ食いつぶして死ぬのかな
Avatar
宇宙のすべての物質をつかってメモリ作っても全然足りないと思う。 < 2 ** (2 ** (2 ** (2 ** (2 ** 2)))) (edited)
Avatar
omochimetaru 1/9/2018 7:35 AM
irb(main):035:0> a.to_s.length => 19729
7:35 AM
2^65535はほぼ2万桁あった
7:36 AM
BignumじゃなくてBigDecimalでも試したけど同じ結果になりました・・・
Avatar
観測可能な宇宙の原子総数が 10^80 個程度なのでまったく足りない。
7:38 AM
2^65535 を表すのが、じゃなくて 2^(2^65535) を表すのが
Avatar
巨大数の中だとまだ小さい気がする
Avatar
ですね。僕が言いたかったのは、一見できそうな演算でも簡単に BigInteger の限界を突破するということです。
Avatar
RSA暗号とかも、すぐにぶっ飛びますよ 何も考えずに実装すると 実際にはうまくやりくりする方法がありますが
Avatar
@sonson そういうのは BigInteger が必要そうですねぇ。
Avatar
実際には,対数上で分解してやるとかの方法でやってたはず・・・・
Avatar
対数上で因数分解なんかできるんですか? log mn = log m + log n を利用してとか?
Avatar
RSAで使われる離散対数の対象となる数は,factorizeできるので,それで確か,桁あふれを防ぐっていうのを自分で実装したことがある
👀 2
2:10 AM
RSAの基本原理は,以下の数式 (平文)^E mod N = (暗号文) (edited)
2:13 AM
このとき,A * B mod C = ((A mod C ) * (B mod C) ) mod C が成り立つので・・・・みたいな
2:13 AM
Swiftと関係なくてごめん
2:15 AM
これで最後・・・この辺の基本原理は,結城さんの暗号技術入門を読むといいです.あと,RSA暗号の数学的な証明は,ネットにいっぱい転がっています.ただ.証明おっかけるの大変ですが・・・・.
👀 1
👍 1
Avatar
気にすんなと言われたので加速. 離散対数の基数を計算するのは(つまり平文を計算する),計算時間的に不可能. しかし,EとNをうまく設定してあげると, (平文)^E mod N = (暗号文) (暗号文)^D mod N = (平文) が成立します. このEが公開鍵で,Dが秘密鍵です. NとEから,Dを推定することは,計算時間的に不可能です. しかし,Nは,実は素数pとqの積から計算されており,そのNを作る二つの素数pとqが逆算されてしまうと, Dが,NとEから計算されてしまいます. 量子コンピュータがRSAの根底を揺るがすと言われるのは,量子コンピュータNの素因数pとqを実時間内で計算できる可能性を秘めているからです. もしそうなると,RSA暗号は,暗号文と鍵を一緒に送っていることになってしまうのです. (edited)
2:47 AM
余談 過去,debianのOpenSSLが生成するpとqがshortくらいのサイズで計算するバグが発生. サイズが小さい整数だと,brute forthで,素因数分解できてしまいます. このため,秘密鍵が一瞬で計算できてしまい,どえらいセキュリティ問題が発生したことがあります.
Avatar
楕円関数だと量子コンピュータでの解読ができるかはわからないからマシみたいな話は聞くものの全然わかってない…
Avatar
omochimetaru 1/10/2018 2:50 AM
昔勉強する機会があったけど、pとqから mod (p * q) 上で 平文と暗号がいったりきたりするEとDを構築するところがいまいち直感的に納得できなかった
Avatar
離散対数は,環なので,それを使う.
Avatar
omochimetaru 1/10/2018 2:50 AM
「素数pとqを決めればうまい手順でそのような特性をもつEとDが構成できる」って天下り的になった
Avatar
離散対数は,環なので,それを使う.
一番分かりやすかった
Avatar
それは,離散対数と,フェルマーの小定理から,導かれる.
2:51 AM
俺も,あんまわかってないけど
2:51 AM
いま証明しろと言われてもできないw
Avatar
量子コンピューター以降は量子コンピューター以外の暗号は破壊されました、とか普通に有り得そうだなーとか想像してる
Avatar
Etheriumとかも楕円暗号ベースだし,そっちに移って行くかもね でも,基本は離散対数なので,おんなじなんじゃねーとか小並感的におもっている.
Avatar
omochimetaru 1/10/2018 2:53 AM

!!注意事項!!

本記事は、国内の量子情報の市販本を読んで、私なりに理解した情報を、敢えて専門書には書いていない用語も使ったプローチで解説を試みています。正確ではない記述もあり、ご批判はあるとは思います。その点を差し引いて、お読...
Avatar
@omochimetaru
「素数pとqを決めればうまい手順でそのような特性をもつEとDが構成できる」って天下り的になった
同じく。大学で RSA 習って計算もしたはずだけど↑以外忘れてしまった。
Avatar
omochimetaru 1/10/2018 2:54 AM
とりあえずこれよんでqbit増えるまではセーフやなって最近思った
Avatar
あと,量子コンピュータは,基本アナログコンピュータなので,統計的にしか結果がでない.
2:55 AM
しもた・・・仕事せんと
Avatar
平文よりも導出しやすいニセの平文を積んだ暗号が、量子コンピューター対策にメジャーになる世界観
2:55 AM
状態として平文よりも安定した状態があればそっちが導出されるからーみたいな
Avatar
omochimetaru 1/10/2018 2:57 AM
たまに数学の話題に転がる事多いし #math 作ってみました。
Avatar
AnyIteratorSequence なのってなんでですか? https://developer.apple.com/documentation/swift/anyiterator
Conforms To IteratorProtocol, Sequence
(edited)
Avatar
omochimetaru 1/11/2018 2:33 AM
サボれるようにじゃないですか?
2:33 AM
for x in (AnyIterator { hoge() }) {} これができたら楽
Avatar
↓まったく 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()) // 5
Avatar
sequenceでちゃんとやりたいならAnySequence { AnyIterator { hoge() } }になるのかな
Avatar
@omochimetaru それだったら IteratorProtocol : Sequence もほしくならない?
Avatar
omochimetaru 1/11/2018 2:36 AM
@koher Sequenceは実は1回きりの列挙しか保証しない
Avatar
@omochimetaru それだと SequenceIteratorProtocol の責務が同じにならない?
Avatar
omochimetaru 1/11/2018 2:37 AM
責務がおなじになるかは次のレベルの議論なのでいったんおいといて
2:37 AM
のところにそうかいてある
2:38 AM
だから、「責務を果たせていない」は、↑の例だけでは、主張できてないと考えます。
2:38 AM
(他になにかおかしいことがあるかもしれないけど、少なくともその例はセーフ)
2:40 AM
struct Countdown: Sequence, IteratorProtocol { var count: Int mutating func next() -> Int? { if count == 0 { return nil } else { defer { count -= 1 } return count } } }
2:40 AM
↑こうやると、 makeIterator が self の return が自動実装される、とか、そういう話も。
Avatar
うーん、そうなのか。そうすると IteratorProtocol との役割分担がよくわからない・・・。
Avatar
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にしてそれを返すのも良いのか。
2:42 AM
でもIteratorを返すと複数回呼んだ時に使用中のが返ってきたりする可能性も読み取れるような。 でもSequecne自体も複数回走査が保証されてないなら……
Avatar
omochimetaru 1/11/2018 2:43 AM
next() が mutating func で makeIterator は nonmutating func って違いはあるけど うーん。
Avatar
@koher
それだと Sequence と IteratorProtocol の責務が同じにならない?
Arrayの場合で考えると走査の状態を保持する外部のオブジェクトを生み出すことができるのがSequenceって言えそうですね。 一般のSequenceについては状態をどうするかは不定なのでAnyIteratorのように自身を返すようになってても良いと。
Avatar
SequencemakeIterator で消費されることがありなら、 extension IteratorProtocol { func makeIterator() -> Self { return self } } 的な実装が可能で、すべての IteratorProtocol の実装は Sequence として振る舞えることになる。
Avatar
SequenceとIteratorProtocolを同時実装したらmakeIteratorは自動実装されるらしい http