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は自動実装されるらしい https://developer.apple.com/documentation/swift/sequence#2849767 (edited)
3:01 AM
@koher が言ってるのはこれを更に進めてIteratorProtocolがSequenceとして振る舞えていいんじゃないかってことですよね
Avatar
はい。ただ、 Swift の仕様で相互に参照するプロトコルが作れるか自信がないです。
Avatar
「任意のIteratorをSequenceとして扱える」というのと「全てのIteratorはSequenceである」は大分違う
Avatar
omochimetaru 1/11/2018 3:02 AM
SequenceとIteratorProtocolを同時実装したらmakeIteratorは自動実装されるらしい
@t.ae#5802 うん、11:37に書いた。
Avatar
後者はちょっと乱暴かなぁ
Avatar
先にかかれてましたね。
Avatar
protocol MySequence { associatedtype Iterator: MyIterator func makeIterator() -> Iterator } protocol MyIterator: MySequence { associatedtype Element func next() -> Element? } extension MyIterator { func makeIterator() -> Self { return self } } MyPlayground.playground:3:20: Type may not reference itself as a requirement 実装都合な気もしてきた
Avatar
@tarunon IteratorProtocolSequence でないけど AnyIteratorSequence である理由はなんでしょうか?
Avatar
手抜きとしか
3:12 AM
なんかSwiftコアメンバーは暗黙的な変換が大好きなように見える (edited)
Avatar
omochimetaru 1/11/2018 3:12 AM
Swiftコアメンバーは暗黙的な変換が大好きなように見える
ww
Avatar
@t.ae
実装都合な気もしてきた
むー、単に実装できないからそうなってるだけなのか。
3:13 AM
それなら、それはそれで理解はできる。
Avatar
そもそもあるProtocolと別のProtocolを相互参照するなら一本化するべきなのでは
4:06 AM
分ける意味あんまないですよね
Avatar
omochimetaru 1/11/2018 4:09 AM
IteratorProtocol is Sequence と Seuqnece が makeIterator で IteratorProtocol を作れる のは微妙に違うから一本化はできない
4:09 AM
IteratorProtocol is Sequence かつ Sequence is IteratorProtocol になるんだったら一本化できるけど。
Avatar
いやできるっしょ
4:11 AM
あれ
Avatar
omochimetaru 1/11/2018 4:11 AM
Sequence 一般が 複数回イテレーションできる事を保証していないだけで、
Avatar
Recursive ConstraintはSwift4だとまだか?
Avatar
omochimetaru 1/11/2018 4:12 AM
複数回イテレーションしても一貫した結果がえられるSequenceを実装することが禁止されてるわけじゃないから
4:12 AM
そういうのを実装する場合には makeIterator で、 Sequence から 別のオブジェクトとしてのIterator を生成する事に意味がある
Avatar
いや別に、Iterator = Selfである必要はないだけで
4:15 AM
Elementの型さえ一致していればその系も表現出来るのだから、 protocol MySequence { associatedtype Element associatedtype Iterator: MySequence where Iterator.Element == Element func makeIterator() -> Iterator func next() -> Element? } こういう風にできると思う
4:15 AM
てか、Recursive Constraint来てたら、さっきのMySequence/MyIteratorもコンパイル通ると思ったけど
4:15 AM
あーーー
4:16 AM
そっか、Sequenceがnext持ってるのは変だわ、たしかに
Avatar
omochimetaru 1/11/2018 4:16 AM
nextはmutating funcだね
4:17 AM
うん、nextとmakeIteratorを交互に呼んだ場合に振る舞いが自明でない 1回キリのイテレーションしか保証はされてないから一般には破綻しないけど、 なんどもイテレーションできるSequenceを実装したときに謎になる
Avatar
@t.ae Swift4.1ならコンパイル通りましたね
4:18 AM
MySequence/MyIterator
Avatar
なるほど。
Avatar
お、じゃあ AnyIteratorSequence なのに IteratorProtocolSequence じゃない理由がない?
Avatar
AnyIteratorがSequenceなのが変だと思うけど
Avatar
といってSequenceのほうにメソッドが色々生えてるのでIteratorだと使いにくい。 AnySequenceにinit追加したら良いんじゃと思うんですがどうでしょう? extension AnySequence { init(iterator: @escaping ()->Element?) { self.init { return AnyIterator(iterator) } } }
Avatar
AnyIteratorがSequenceなのが変だと思うけど
僕もこちら側の意見です。 Sequence がイテレータ経由で consume されるのも微妙な気が。
Avatar
for で回したいんだったら for inT: IteratorProtocol を許容するようにした方がシンプルな気もするけどなぁ。
Avatar
zipとかもあるんでfor in だけできても微妙な気が
Avatar
あー、 map とかもできるのかと思ったら単に AnyIteratorSequence だからできるだけだった。
6:42 AM
うーん、 AnyItearator については使い捨てで操作したいこともあるし、かといって AnyIterator AnySequence で包むのはオーバーヘッドがあるからしかたないのかなぁ。 (edited)
Avatar
AnySequenceで包むのは〜の誤りですか?
Avatar
ああ、そう。
6:51 AM
何をもって分かれてるんだろう
Avatar
omochimetaru 1/11/2018 6:54 AM
Zip2Iteratorは直接構築しなくて
6:54 AM
Zip2Sequenceが内部で実装としてもってる型なんじゃない?
Avatar
https://github.com/apple/swift/blob/9361a6b66f6f8351e89c090f604d7e1f42e2a045/stdlib/public/core/Zip.swift#L148-L153 SequenceではSequenceで持ってIteratorではIteratorで持つというのは分かるんですが
swift - The Swift Programming Language
6:57 AM
僕が引っかかったのはzipのイテレータだとSequenceとして不適当な場合があるのかってことですね
Avatar
omochimetaru 1/11/2018 6:59 AM
makeIterator() するたびに最初から列挙し直すためでは?
6:59 AM
正しく動くのは zipされるSequence2つが、再列挙に対応している場合に限るけど。
7:00 AM
ああそうか、IndexingIterator が Sequence でもいいのは、
Avatar
そうですね。その制限があるんでZip2IteratorがSequenceじゃない必要がないんじゃないかと
Avatar
omochimetaru 1/11/2018 7:00 AM
IndexableなCollectionから生成される時点で
7:00 AM
再列挙が常に正しいからだ。 (edited)
7:01 AM
その制限があるからZip2IteratorがSequenceだとおかしくならない?makeIteratorでselfを返すと再列挙できない (edited)
Avatar
let a = [0, 1, 2] var i1: IndexingIterator<[Int]> = a.makeIterator() print(i1.next()) // 0 var i2: IndexingIterator<[Int]> = i1.makeIterator() print(i2.next()) // 1 再列挙してないみたいです (edited)
Avatar
omochimetaru 1/11/2018 7:03 AM
ほんとだ。
7:03 AM
じゃあこれもAnyIteratorと同じで楽にできるようになってるだけか・・・ (edited)
Avatar
その制限があるからZip2IteratorがSequenceだとおかしくならない?makeIteratorでselfを返すと再列挙できない
そもそも再列挙できなくてもいいのがSequenceという話では
Avatar
omochimetaru 1/11/2018 7:03 AM
それでいいならZip2IteratorもSequenceでも良いわなあ
7:03 AM
いや
7:03 AM
できなくてもいいじゃなくて
7:03 AM
ソースが対応しているならできたほうがいいってこと
7:04 AM
できなくてもいいけど、できるならできたほうがより良い
Avatar
それはそうですね。
Avatar
omochimetaru 1/11/2018 7:04 AM
zipの場合は、ZipSequenceで抱えてるソース1とソース2が再列挙できるSequenceなら、最初からやりなおせたらいい
7:04 AM
でもIndexedIteratorでよくわかんなくなったわ。
Avatar
お、
7:10 AM
let a = [0, 1, 2] var i1: IndexingIterator<[Int]> = a.makeIterator() print(i1.next()) // 0 var i2: IndexingIterator<[Int]> = i1.makeIterator() print(i2.next()) // 1 print(i1.next()) // 1 分岐はしているみたい
7:11 AM
IndexingIteratormakeIteratorで途中状態を考慮したIteratorが帰ってくるというのは別に悪くないようにも思えますねぇ
Avatar
omochimetaru 1/11/2018 7:15 AM
イテレーターっていうのがそもそもそういう概念の事では
7:16 AM
mutating func next() からもわかるとおり、場所を保持する。
7:16 AM
ただsequenceとしてアクセスして.makeIteratorしたときの振る舞いは自明でない・・・
Avatar
IndexingIterator は意図がよくわかんないけど、
7:21 AM
Zip2IteratorZipSequence 経由で生成するから、逆に Iterator から Sequence を作りたいユースケースがないんじゃない?
Avatar
omochimetaru 1/11/2018 7:22 AM
IndexingIteratorもCollectionから作るし自作はできないっぽい? initがみえない
Avatar
AnyIterator の場合は Sequence を作りたくなるユースケースが想定されて、しかも AnySequence でラップするには無視できないオーバーヘッドがあって仕方なく Sequence になってるのかと。
7:22 AM
IndexingIterator はわかんない。
🤔 1
Avatar
そこのオーバーヘッドってそんな大きいんですかね
Avatar
omochimetaru 1/11/2018 7:30 AM
まあmakeIteratorを呼び出すのは一回だけで、その後はIteratorオブジェクトしか関与しないから
7:30 AM
イテレーションするようなシナリオにおいては最初の1回だけってのは小さいよね
7:30 AM
オブジェクトの生成は生じるし確実に無駄ではあるけど。
Avatar
うーん、イテレーション自体を考えたら無視できるってのはそうかもしれないけど、無駄にヒープにアロケートするのは微妙ではあるよね。
Avatar
omochimetaru 1/11/2018 7:33 AM
そうですね。
Avatar
API上の利便性でこうなってるなら、 AnySequence で包んでから使う方がいいと思うけど。 (edited)
Avatar
omochimetaru 1/11/2018 7:33 AM
なんか僕の感覚だと初級プログラマが混乱しないようにそうしたにおいがする
7:34 AM
AnySequence で包んでから使う方がいいと思うけど。
同意
7:34 AM
Promiseのthenみを感じる。
Avatar
えー、 IteratorProtocolSequence を混ぜるのは余計混乱するのでは?
Avatar
omochimetaru 1/11/2018 7:34 AM
混ぜないほうがいいってことです
Avatar
ああ、 AnyIterator の話じゃないのか。
7:36 AM
Sequence は基本的には makeIterator を複数回実行できることを想定しながらも、 consume するものにも使えるというのはまあいい気がしてきた。
Avatar
static func initの裏技(by @lovee )、自身の型を返してサブクラス作るとセグフォ出ますね。
10:51 AM
class My { static func `init`(arg: Void) -> My { return MyMy() } } class MyMy: My { } My(arg: ()) (edited)
Avatar
omochimetaru 1/11/2018 3:18 PM
お~
Avatar
protocol initなしでワンチャンあるか?と思ったけど無かった
Avatar
@hiragram RxのPrimitiveSequence.flatMapのoverloading、何かしら作業してたかしら
Avatar
まだなんも
Avatar
スレに書き込みあったから便乗しといた https://github.com/ReactiveX/RxSwift/issues/1206#issuecomment-358182422
⚠️ If you don't have something to report in the following format, it will probably be easier and faster to ask in the slack channel first. ⚠⚠️ Please take you time to fill in the fields below. If...
Avatar
+1しといた
Avatar
別に+1しろってことではないんだがw
3:20 AM
議論に参加してねということです
Avatar
する
Avatar
した
Avatar
えらい
Avatar
I encounter that situation almost every day.
これはちょっと盛った
Avatar
正直ワロタ
Avatar
いや、でも実際毎日asObservable asCompletableしてるかもしれない
Avatar
オレオレflatMap作ってないの
Avatar
つくってない
3:35 AM
つくるかあ
Avatar
どうせ追加されるから作って損はないと思うし
3:35 AM
追加されなかったら作るの必須だからどっちにしてもやるしかない
Avatar
「本家にあるやつなのか、自分で作ったやつなのか」がパッと見でわからなくなるのはなんか嫌なんだよな
Avatar
アンスコでもつけとけ
Avatar
このオペレータ壊れてるやんけキレたろと思ってキレかけたら自分で作ったやつだったとか
3:36 AM
アンスコはありありのあり
Avatar
それか、extension作ればいいんちゃうか
3:36 AM
observable.my.flatMapみたいな
Avatar
他に結構な数のオペレータ作ってしまってるからエイヤで移行するのも手間だしこれは my 無くてこっちはあるとかそんなんは地獄っぽいのでアンスコがコスパ良いかなーって感じする
Avatar
アンスコならリファクタリングで済むから安いっすね
Avatar
3のプロジェクトを4に移行していたらこんなのがでてきました。 let a = [0: true, 1: false] // Error: `filter` is ambiguous // let x = a.filter { $0.value }.sorted(by: { $0.key < $1.key }) // Equivalent let x1 = a.filter { $0.value } let x2 = x1.sorted(by: { $0.key < $1.key}) 4からDictionaryfilterが二種類になったみたいで、 分割して書いた場合は優先順位が付くけどsortedが続いた場合は型推論で両方通るのでambiguousになる?みたいです
6:01 AM
こう書くとか let x = (a.filter { $0.value } as Array).sorted(by: { $0.key < $1.key }) ソートを先にするとかで対応できますがいまいち……
Avatar
きびしいw
6:02 AM
prefixで死んだのと同じっぽいですね
6:02 AM
やはり高階型が必要…
Avatar
sortedがついた場合も優先順位働かせることはできそうですけど やっぱ中間の型が隠れてるのは良くないとかいう判断なんでしょうかね。 (edited)
Avatar
4.1 では通るみたいです。
6:13 AM
型推論のランキング方法が変更されたのかも。
Avatar
お、まじですか
Avatar
CondConf関係でしょうか
Avatar
わからん。 https://bugs.swift.org/browse/SR-6634
Pavel Yaskevich, I wonder if this is related to the ranking changes you made?
とあるので、何かしらの変更があったのは確かみたいです。
Avatar
でてきたのがsortedだったのでそのまま書きましたがcountの例のほうがより問題に近かったですね。
Avatar
https://bugs.swift.org/browse/SR-1996 そのものっぽいのを見つけました。
6:33 AM
あ、values に対する filter だから違うか。
Avatar
ちょっと違いますね というかcountだと通るというよく分からない状態 に let a = [0: true, 1: false] let xx = a.filter { $0.value }.count
🤔 1
Avatar
enum E { case A(Int, String) case B(String, Float) } func foo(e: E) { switch e { case .A(_, let str): // something. fallthrough case .B(let str, _): print(str) } } これが通るようになるらしいです。 https://github.com/apple/swift/pull/14041/files#diff-3f455e97fae02f7b158f90077919c17fR140
This is the simplest / most-restrictive version of this feature. The previous case that we're falling from must have a superset of the bindings of the case we're falling into and all the to-case bi...
Avatar
protocol変数だと死にそうだ
Avatar
そのバグは解消されていたような。
Avatar
解消されたというか
6:48 AM
セグフォ→コンパイルエラーになりました、だったような
Avatar
セグフォ→コンパイルエラー→解消 に最近なったという意味で。
Avatar
maji
6:50 AM
1/16の4.1スナップショットはまだだった。
Avatar
残念ながら 4.1 には入らないと思います。5.0 待ち。
2:52 AM
Sequenceに辞書順比較入ってるのめっちゃ便利だ
2:52 AM
Data型で使えた。
2:53 AM
いまバイナリ列を順序比較したかった。
Avatar
String< はこれで実装されているわけではない? This method implements the mathematical notion of lexicographical ordering, which has no connection to Unicode. If you are sorting strings to present to the end user, use String APIs that perform localized comparison.
3:15 AM
↑ "localized comparison" って、ローカライズ環境によって String< の順序変わるの??
Avatar
omochimetaru 1/25/2018 3:16 AM
a と Aとかじゃないですか?
3:16 AM
キャラクターコード順だと apple banana Apple だけど期待される文字列ソートは apple Apple banana になりそう (edited)
Avatar
ASCII は A が a より早いのでは?
Avatar
omochimetaru 1/25/2018 3:17 AM
それでもいいです そうじゃなくてw
3:17 AM
AとBの前後順。
Avatar
はい、わかります。
Avatar
omochimetaru 1/25/2018 3:17 AM
(a|A) < (b|B)
3:18 AM
なんかまえに @norio_nomura さんが文字列のソート順が Linuxだと違うとか
Avatar
いろいろ疑問があるけど、まずそれは Character の順序やんね?
Avatar
omochimetaru 1/25/2018 3:18 AM
ふんでたな
Avatar
その Character の順序が (a|A) < (b|B) になってたら
3:19 AM
StringlexicographicallyPrecedes もその順になるのでは?
Avatar
omochimetaru 1/25/2018 3:19 AM
たしかに。この例だとCharacterのSequenceにおいてlexicographicallyだから不適切だ。
3:20 AM
Unicodeって文字列のソート順規定もあった気がする
Avatar
$ swift Welcome to Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2). Type :help for assistance. 1> let a: Character = "a" a: Character = { _representation = smallUTF16 { smallUTF16 = 97 } } 2> let b: Character = "B" b: Character = { _representation = smallUTF16 { smallUTF16 = 66 } } 3> a < b $R0: Bool = false (edited)
3:20 AM
マジかw
3:22 AM
var ss = ["apple", "Apple", "banana"] ss.sort() print(ss) // "["Apple", "apple", "banana"]\n" ss.sort { (a, b) in a.lexicographicallyPrecedes(b) } print(ss) // "["Apple", "apple", "banana"]\n"
3:22 AM
↑とりあえずまずはこう
3:23 AM
@_inlineable @_versioned internal static func compare( _ left: _StringGuts, to right: _StringGuts ) -> Int { defer { _fixLifetime(left) } defer { _fixLifetime(right) } #if _runtime(_ObjC) // We only want to perform this optimization on objc runtimes. Elsewhere, // we will make it follow the unicode collation algorithm even for ASCII. // This is consistent with Foundation, but incorrect as defined by Unicode. // // FIXME: String ordering should be consistent across all platforms. if left.isASCII && right.isASCII { let leftASCII = left._unmanagedASCIIView let rightASCII = right._unmanagedASCIIView let result = leftASCII.compareASCII(to: rightASCII) return result } #endif return _compareDeterministicUnicodeCollation( _leftUnsafeStringGutsBitPattern: left.rawBits, _rightUnsafeStringGutsBitPattern: right.rawBits) }
3:23 AM
すごいFIXMEあった
Avatar
www
// FIXME: String ordering should be consistent across all platforms.
Avatar
omochimetaru 1/25/2018 3:24 AM
これはw
Avatar
あと疑問なんだけど、 Unicode のコードポイントの順序を比較できるのはいいとして、 Character って書記素クラスタだから何によって順序付けされてるの? a < B であることからそもそもコードポイントでないんだろうけど。
Avatar
omochimetaru 1/25/2018 3:26 AM
そこが、Unicodeで決まってる気がするんですよね
Avatar
書記素クラスタの順序?
Avatar
omochimetaru 1/25/2018 3:26 AM
そこまではわからないけど
3:26 AM
aとAが仲間だよ、とか、そういうコードポイント以外の情報。
Avatar
そこが Unicode 決まってたら、 Java の String の順序とかぐちゃぐちゃになってそう・・・
Avatar
omochimetaru 1/25/2018 3:27 AM
とりあえずnon-objcで追ってみよう libicu に帰着しそうだが
3:27 AM
/// Compares two slices of strings with the Unicode Collation Algorithm. @inline(never) // Hide the CF/ICU dependency @effects(readonly) public // @testable static func _compareDeterministicUnicodeCollation(
3:28 AM
Unicode Collation Algorithm というキーワードが出てきた。
3:28 AM
Collationは 「ガ」と「カ+濁点」を正規化したりするやつかな
3:28 AM
どちらも見た目上は1文字のガに見える。 (edited)
Avatar
ん??↑の例、 banana じゃなくて Banana じゃないといけない気が。
3:29 AM
3> ["apple", "Apple", "banana", "Banana"].sorted() $R2: [String] = 4 values { [0] = "Apple" [1] = "Banana" [2] = "apple" [3] = "banana" }
Avatar
omochimetaru 1/25/2018 3:29 AM
var ss = ["apple", "Apple", "banana", "Banana"] ss.sort() print(ss) // ["Apple", "Banana", "apple", "banana"]\n" ss.sort { (a, b) in a.lexicographicallyPrecedes(b) } print(ss) // ["Apple", "Banana", "apple", "banana"]\n"
3:29 AM
たしかに・・・
3:29 AM
普通に大文字が前だった。
Avatar
どうやっても辞書順無理なのかw
Avatar
omochimetaru 1/25/2018 3:30 AM
結局辞書にならんのかい
Avatar
そうすると、単純にはコードポイントの順になってそうだけど、書記素クラスタはどうなってるのかな?コードポイントのシーケンスとして lexicographicallyPrecedes 的な?
3:31 AM
/// Compares the strings via the Unicode Collation Algorithm on the root locale. /// Results are the usual string comparison results: /// <0 the left string is less than the right string. /// ==0 the strings are equal according to their collation. /// >0 the left string is greater than the right string. int32_t swift::_swift_stdlib_unicode_compare_utf16_utf16(const uint16_t *LeftString, int32_t LeftLength, const uint16_t *RightString, int32_t RightLength) { // ICU UChar type is platform dependent. In Cygwin, it is defined // as wchar_t which size is 2. It seems that the underlying binary // representation is same with swift utf16 representation. // On Clang 4.0 under a recent Linux, ICU uses the built-in char16_t type. return ucol_strcoll(GetRootCollator(), reinterpret_cast<const UChar *>(LeftString), LeftLength, reinterpret_cast<const UChar *>(RightString), RightLength); } (edited)
3:33 AM
他にもutf8まじりのオーバーロードとかったけどutf16同士だとここになる ここでSwiftから見ると C 関数の _swift_stdlib_unicode_compare_utf16_utf16 が C++ で実装されてて ucol_strcoll の呼び出しに帰着してる これは外部のlibicuのシンボルじゃないか (edited)
Avatar
4> ["👨‍👩‍👧‍👦", "👨", "👩"].sorted() $R3: [String] = 3 values { [0] = "👨" [1] = "👨‍👩‍👧‍👦" [2] = "👩" }
Avatar
omochimetaru 1/25/2018 3:34 AM
コメントにroot locale ってあって、 GetRootCollator() とか書いてあるし、設定みたいなものには依存しない気がする
Avatar
👨👩👧👦 (edited)
3:36 AM
Facebook では父母の位置が反転するらしい。ヤバイ。
3:37 AM
↓(👨👩👧👦)をつないでるのに。 U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 (edited)
3:39 AM
ICU comes with a large set of already predefined collators that are suited for specific locales. Most of the ICU locales have a predefined collator. In worst case, the default set of rules, which is equivalent to the UCA ordering, is used.
3:40 AM
ICUはライブラリとしてロケールごとのcollationを規定しているがデフォルトではUCA順序になる(RootLocale?
3:40 AM
Unicode® Technical Standard #10 UNICODE COLLATION ALGORITHM
Avatar
ロケールごとに文字列の順序決まってるって色々ヤバそうな感じがする・・・
Avatar
omochimetaru 1/25/2018 3:41 AM
そこがよくわかんないですね。
3:41 AM
具体的にJPとENで入れ替わるパターンを知りたいな。
Avatar
ドイツ語とかでÄとか考えたときに、 A の後に入れたいとかあるのかな?
Avatar
omochimetaru 1/25/2018 3:41 AM
金正日を表記するようの金の文字は前にあるとかかね
3:42 AM
あれはユニコードには無いのかな 北朝鮮の文字コード体系には存在するらしいが
3:42 AM
あ〜
3:42 AM
ありそうですね>Aのポチつき
Avatar
同じ文字を複数言語で使ってる場合に順序が衝突することはありそう。
3:42 AM
日本語の漢字と中国語の漢字で順序を別にしたいとか。
3:43 AM
そもそも漢字の順序って何?って思うけど。
Avatar
omochimetaru 1/25/2018 3:43 AM
Language Swedish: z < ö German: ö < z Usage German Dictionary: of < öf German Phonebook: öf < of Customizations Upper-First A < a Lower-First a < A
Avatar
ただ、法でも字の順序を決めるとかもありえるかも。
3:43 AM
ヤバw < ↑の例 (edited)
Avatar
omochimetaru 1/25/2018 3:43 AM
Collation varies according to language and culture: Germans, French and Swedes sort the same characters differently. It may also vary by specific application: even within the same language, dictionaries may sort differently than phonebooks or book indices.
3:44 AM
ドイツ語とフランス語で同じ文字でも違う順番になるし
3:44 AM
同じ言語でもフォンブックとブックインデックスで違う?
Avatar
Locale 情報が static に存在してるのって気持ちわるいんだよなぁ。
Avatar
omochimetaru 1/25/2018 3:44 AM
なに??
Avatar
ロケールを渡さなくてもデフォルトロケールに基いてソートされるってことでしょ?
Avatar
omochimetaru 1/25/2018 3:45 AM
電話帳と本の索引で辞書順の並びが変わる言語があるって書いてあるけど何を言ってるかさっぱりわからない・・・
3:46 AM
Language Swedish: z < ö German: ö < z Usage German Dictionary: of < öf German Phonebook: öf < of Customizations Upper-First A < a Lower-First a < A
3:46 AM
German DictionaryとGerman Phonebook の例っぽいけどどういうことなんだ
Avatar
電話帳と本の索引で辞書順の並びが変わる言語がある
ひどいw
3:47 AM
まあ、文字の順序が法で決められてなければ分野によってバラツキがあるまま発展したとかありそう。
Avatar
omochimetaru 1/25/2018 3:47 AM
あるのかもしれないけどなんで電話帳が違うんだ・・・
3:48 AM
Table 2. Comparison Levels Level Description Examples L1 Base characters role < roles < rule L2 Accents role < rôle < roles L3 Case/Variants role < Role < rôle L4 Punctuation role < “role” < Role Ln Identical role < ro□le < “role”
3:49 AM
Table 4. Context Sensitivity Contractions H < Z, but CH > CZ Expansions OE < Œ < OF Both カー < カア, but キー > キア
3:49 AM
日本語で伸ばし棒の音が前の音のアイウエオで変わるみたいな事かこれ
Avatar
omochimetaru 1/25/2018 3:49 AM
このドキュメント、読むのしんどすぎてダメだ・・・
3:50 AM
つまりどうなってるのかに辿り着く前にパンクする・・・
3:50 AM
@norio_nomura 以前触れてたやつ、まだOPEN issueなんですね、まあ、コードもFIXMEだったし。
3:51 AM
ObjCの振る舞い全部捨ててICUに統一したらいいのに。
3:51 AM
互換性で爆発するかしら・・・
Avatar
カー < カア, but キー > キア これ確かに日本語ネイティブだから意識してないけどヤバイな。
Avatar
norio_nomura 1/25/2018 3:51 AM
ICUに依存しない実装のPRが出てるけど、パフォーマンスが出ないみたい。https://github.com/apple/swift/pull/13877
Avatar
omochimetaru 1/25/2018 3:52 AM
var ss = ["カア", "カー", "キイ", "キー"] ss.sort() print(ss) // ["カア", "カー", "キイ", "キー"] ss.sort { (a, b) in a.lexicographicallyPrecedes(b) } print(ss) // ["カア", "カー", "キイ", "キー"]
3:52 AM
特に考慮されないモードのようだ。
Avatar
日本生まれの Ruby でもダメだった。 puts "カー" < "カア" # false puts "キー" < "キア" # false
Avatar
omochimetaru 1/25/2018 3:58 AM
ICUに依存しない実装のPRが出てるけど、パフォーマンスが出ないみたい。https://github.com/apple/swift/pull/13877
なるほど StringNormalization.swiftがたされるんですね
Avatar
norio_nomura 1/25/2018 4:00 AM
ICUの初期化パラメータを変えて、Darwinの挙動に近くするPRを以前書いたけど「ICUへ依存しない実装へ変えるべき」とか言われてマージしてもらえなかった。 https://github.com/apple/swift/pull/8769
This PR changes to use default collator instead of root collator. http://icu-project.org/apiref/icu4c/ucol_8h.html said about ucol_open()'s locale parameter as: loc The locale containing the requ...
Avatar
これパフォーマンス出る実装できるんですか?直感では何も思いつかない
Avatar
omochimetaru 1/25/2018 4:01 AM
@tarunon ICUと同等のパフォーマンスは出るんじゃ?
4:01 AM
public func _compareStringsPreLoop( selfUTF16: UnsafeBufferPointer<UInt16>, otherUTF16: UnsafeBufferPointer<UInt16> ) -> _Ordering {
4:03 AM
UTF16で見て違いが出るところを見つけて、その場所からこんどはセグメントの始まりまで巻き戻して・・・
4:04 AM
lexicographicalでいける場合はいけるけど、そうじゃない場合に // Pathological case: multi-segment expanders ruin segment-by-segment // processing.
4:04 AM
pathlogical caseとやらが最悪系
Avatar
ふむふむ
Avatar
omochimetaru 1/25/2018 4:05 AM
// NOTE: Multi-segment expanders are (at least up til Unicode 10) always the // beginning of a normalization segment (i.e. they are starters).
4:05 AM
unicode10とか書いてあるしまさに絵文字結合とかが入った世代だろうか
4:06 AM
private func _compareStringsPathological( selfUTF16: UnsafeBufferPointer<UInt16>, otherUTF16: UnsafeBufferPointer<UInt16> ) -> _Ordering { var selfIterator = NormalizedIterator(selfUTF16) return selfIterator.compare(with: NormalizedIterator(otherUTF16) ) } (edited)
4:06 AM
いろんなファストパスこけた場合の最終汎用系がこれか
4:09 AM
そのIteartorの中で normalizeがされて・・・ internal func _tryNormalize( _ input: UnsafeBufferPointer<UInt16>, into outputBuffer: UnsafeMutableBufferPointer<UInt16> ) -> Int? { var err = __swift_stdlib_U_ZERO_ERROR let count = __swift_stdlib_unorm2_normalize( _Normalization._nfcNormalizer, input.baseAddress._unsafelyUnwrappedUnchecked, numericCast(input.count), outputBuffer.baseAddress._unsafelyUnwrappedUnchecked, numericCast(outputBuffer.count), &err ) guard err.isSuccess else { // The output buffer needs to grow return nil } return numericCast(count) }
4:09 AM
__swift_stdlib_unorm2_normalize まできた。
4:10 AM
あれ
4:10 AM
unorm2_normalize
4:10 AM
の呼び出しに行っちゃった
4:10 AM
これはICUだから
4:10 AM
ICUに依存しない
というわけではない?
4:11 AM
ICU自体は使うけど、ソート順序に関しては依存しないってことかな?
4:11 AM
Unicodeのnormalizeとcollationは違う概念っぽいな
4:13 AM
normalizeのほうが小さい道具なら、ICUに全部任せてたのを一部Swiftで自前で書いたという感じだけど、
4:13 AM
それでパフォーマンスが出てないなら、ロジックが悪いか、SwiftがまだC++に追いつけて無い部分があるのか
4:14 AM
ほとんどのテストが80~90%ぐらいに性能低下しちゃってるんだなあ
Avatar
norio_nomura 1/25/2018 4:16 AM
あれ?まだ依存してましたか。てっきり依存しない実装かと勘違いしていました。失礼。
Avatar
omochimetaru 1/25/2018 4:16 AM
collationでの依存はなくなったけどnormalizeでは依存してるという感じに見えます。
4:18 AM
Apple勢同士のPRだとあんまり議論の詳細が書いてないからよくわからんですなあ
Avatar
norio_nomura 1/25/2018 4:22 AM
ICU依存云々は僕の記憶がどこかで書き換わっていたぽい。 https://github.com/apple/swift/pull/8769#issuecomment-294310129 から引用。 > @dabrahams Sorry, I didn't read the string manifesto. > Hm, it seems that the string manifesto says "Swift string sorting will not be compatible with > Foundation sort order". > Is that correct with that understanding? Yes, non-localized String sorting will not work the same way in Swift as it does in Foundation. We intend to try very hard to keep localized sorting in sync, though. なんか詳細忘れちゃったな…
This PR changes to use default collator instead of root collator. http://icu-project.org/apiref/icu4c/ucol_8h.html said about ucol_open()'s locale parameter as: loc The locale containing the requ...
4:25 AM
Foundationの挙動はUnicodeに一部従ってないから、SwiftのStringはUnicodeに従った挙動にすべきとString Manifestoでは言っていて、つまりString Manifestoが実装されるとFoundationとStdlibの文字列比較の挙動は違ってくる。とかだったかしら?
Avatar
omochimetaru 1/25/2018 4:27 AM
ふむふむ
Avatar
norio_nomura 1/25/2018 5:24 AM
Avatar
omochimetaru 1/25/2018 5:28 AM
norio_nomura [12:54 PM] ASCIIに関しては一部の記号の扱いがFoundationとUnicodeで違うぽい。 [12:54 PM] で、大文字小文字のどちらが前に?ってのは、Unicodeでも「カスタマイズできるようにするべき」って書かれてる。 http://unicode.org/reports/tr10/#Case_Comparisons (edited)
5:29 AM
そうそう、このやりとりをぼんやりおもいだしていましsた
Avatar
omochimetaru 1/25/2018 5:44 AM
Recently, I proposed the idea of adding the ability to implement the "class cluster" pattern from Cocoa (Touch) in Swift. However, as we discussed it and came up with different approaches, it evolved into a functionality that I believe is far more beneficial to Swift, and subsequently should be the focus of its own proposal. So here is the improved (pre-)proposal: # Factory Initializers The "factory" pattern is common in many languages, including Objective-C. Essentially, instead of initializi...
5:44 AM
factory init のプロポザル出てた
5:45 AM
ん??12月ってこれ3年前の12月だ!
Avatar
’分かりにくいですよね
Avatar
omochimetaru 1/25/2018 5:45 AM
右のところみないときづけんな。
Avatar
右端じゃなくて、枠内の日付表示の Dec '15 の 15 も 2015 年みたい。
Avatar
omochimetaru 1/25/2018 6:02 AM
!!!!
6:02 AM
15日かと思ってたwwww
Avatar
’分かりにくいですよね
というコメント自体が分かりにくかったか
Avatar
www
6:03 AM
そうなのかこれw
Avatar
omochimetaru 1/25/2018 6:03 AM
@t.ae きづかねえ→「'」
6:03 AM
ジャップ芸をしてしまった・・・
Avatar
カーソルを日付に合わせてぢっとしていると、真の日付が表示されるぞ
Avatar
omochimetaru 1/25/2018 6:04 AM
@tarunon ほんとだ。裏技だ。
Avatar
超能力者向けか?
Avatar
omochimetaru 1/25/2018 6:04 AM
クリックでもいいのか。
6:04 AM
まあでもフォーラムになってめっちゃよくなったわ
Avatar
FWIW, even in Swift2, factory initializer is possible. I've post a gist here: https://gist.github.com/rintaro/9eadc2720ac8be6a7898 It's pretty hackish though 🙂 ···
Avatar
omochimetaru 1/25/2018 6:05 AM
いろいろいいところあるけどアイコンのおかげで人物対応が記憶できるの大きいな
6:08 AM
@noescape 懐かしい
Avatar
omochimetaru 1/25/2018 7:52 AM
struct Cat : CustomStringConvertible { var name: String var description: String { return name } } var a: Cat = .init(name: "たま") var b: Cat? = .init(name: "くろ") // [1] print("\(a)") // [2] print("\(b?.description ?? "")") // [1] にたいして [2] の記述量が多く理不尽に感じる。 // 「noneなら空文字列」という事だけが言いたいだけなので、 // 例えば以下のように書きたい。 print("\(b ?? "")") // でもこれは ?? の両辺の型としておかしいので・・・ // 例えば \() を2引数関数のようにみなして print("\(b, "")") // などと書けるようにするとか?
7:53 AM
最近の Optional(2018) から思っている事↑
Avatar
Kishikawa Katsumi 1/25/2018 7:54 AM
\(b, defaultValue: "") の方がそれっぽいかなあ。 (edited)
7:54 AM
でも良いアイデアと思いますね。
Avatar
print("\(b, "")") は現状でも書けちゃうという。 "\((b, ""))" と解釈される。
Avatar
omochimetaru 1/25/2018 7:57 AM
!!! > 現状でも書けちゃう
Avatar
Kishikawa Katsumi 1/25/2018 7:57 AM
Tupleになっちゃうのか。
Avatar
omochimetaru 1/25/2018 7:57 AM
@Kishikawa Katsumi たしかに。Dictionaryのやつとかもそんな雰囲気ですし、そうですね
7:57 AM
これが必要だと思う理由もう一個あって、
Avatar
Kishikawa Katsumi 1/25/2018 7:57 AM
直したのにまだtypoしてるな。
Avatar
omochimetaru 1/25/2018 7:57 AM
.description になるか、 .debugDescription になるか、 (3) になるか (4) になるか
7:58 AM
(3, 4は省略 、とにかく4しゅるいある)
7:58 AM
\(a) ってかいてるときは気にする必要が無いのに (edited)
7:58 AM
デフォルトを与えようとしたときにはそれが露出するのもアンバランスだと思うからです
Avatar
これって大分進んだ議論な気がしていて、まずは文字列補間で CustomStringConvertible 以外使えないようにすることが必要そう。
👆 1
Avatar
途中まで作業してほったらかしで申し訳ない気持ち
Avatar
omochimetaru 1/25/2018 8:00 AM
@koher @tarunon ですね、そっちの路線に行くならこれは寄り道です。現状を前提にマシにしていくなら、という方向で考えてます。
Avatar
Optional where Wrapped: CustomStringConvertibleなXにX ?? Stringのオペレーターを追加するとスッと書けそう
Avatar
omochimetaru 1/25/2018 8:02 AM
そうだね、でもそれ若干おかしなことになってない?
8:02 AM
文字列補間のことを一旦忘れて考えると、 ただのXはそのままではStringにならなくて .description がいるのに (edited)
8:02 AM
Optional<X> は String にもっていくショートカットがあることになる
Avatar
確かに
8:05 AM
それが文字列補完でしか使えないなら兎も角外に露出してるのは気持ちが悪いね
Avatar
omochimetaru 1/25/2018 8:05 AM
そうそう。
8:05 AM
僕のさっきのだとあくまで文字列補間の流れでの拡張だからそういう副作用は無い。
Avatar
foo?.description ?? "" は必要最小限の表記な気が。
8:06 AM
あとは extension 生やして foo.description(default: "") くらい? (edited)
Avatar
omochimetaru 1/25/2018 8:07 AM
optionalじゃないときは "\(foo)" だけで書けるのに、というモチベーションは変わらないですねえ
Avatar
↓に倣えば。 subscript(key: Dictionary.Key, default defaultValue: @autoclosure () -> Dictionary.Value) -> Dictionary.Value { get set } https://developer.apple.com/documentation/swift/dictionary/2894528-subscript
Avatar
Kishikawa Katsumi 1/25/2018 8:08 AM
メソッドやSubscriptはfooがnilの時は
8:08 AM
呼ばれないから難しいんじゃないかな。
Avatar
optionalじゃないときは "(foo)" だけで書けるのに
Optional なのに空文字列に変換したいという特殊なニーズだから仕方ないんじゃないかなぁ?
Avatar
omochimetaru 1/25/2018 8:09 AM
koher が書いてるのは Optional型自体のメソッドじゃないですか? .map などと同じ。
Avatar
↓ですね。 extension Optional where Wrapped : CustomStringConvertible { func description(default defaultValue: String) -> String { return self?.description ?? defaultValue } } (edited)
Avatar
String(describing: )でいいんじゃないかと思ったんですがこの引数の型なんだろ……
Avatar
Any
Avatar
omochimetaru 1/25/2018 8:10 AM
@t.ae Anyだし、それは "Optional(2018) " になるだけだよ (edited)
Avatar
あれそれはならないんじゃなかったっけ
Avatar
ドキュメントにSubjectって書いてあるんですがAnyのエイリアスなんですかね?
Avatar
なるんだっけ
Avatar
Kishikawa Katsumi 1/25/2018 8:10 AM
Optionalの方を拡張するのもいいですけど、Fooにも両方拡張しないと使い勝手が悪くないです? (edited)
8:10 AM
いや、いいのか。
8:11 AM
OptionalじゃなければDefaultValueはいらないですね。
🙂 1
Avatar
omochimetaru 1/25/2018 8:11 AM
print("\(String(describing: b))") // "Optional(くろ)\n" var c: Cat? = nil print("\(String(describing: c))") // "nil\n" (edited)
Avatar
Kishikawa Katsumi 1/25/2018 8:11 AM
まあOptionalのCustomStringConvertibleをなくすのが一番スッキリではありますね。
Avatar
OptionalはCustomDebugStringConvertibleですね
8:12 AM
CustomStringConvertibleではないです
8:12 AM
(ややこしや)
Avatar
omochimetaru 1/25/2018 8:12 AM
www
Avatar
Kishikawa Katsumi 1/25/2018 8:12 AM
じゃあOptionalでCustomStringConvertibleを新しく実装するようになればいいのか。
Avatar
OptionalはCustomDebugStringConvertibleですね CustomStringConvertibleではないです (ややこしや) でもこれってよく考えるとそうなっていてほしくて、文字列に変換できちゃうと困るけど、デバッグ時には文字列にしたいんですよね。
Avatar
Kishikawa Katsumi 1/25/2018 8:13 AM
"Optional(xxx)"じゃないやつ。
Avatar
なので、CondConf以後の世界では、extension Optional: CustomStringConvertible where Wrapped: CustomStringConvertible を自分で定義する、のはアリかもしれません。
8:13 AM
僕はやらないけど
Avatar
OptionalCustomStringConvertible だと "Optional(2018年)" の温床になるのでダメだと思います。
Avatar
omochimetaru 1/25/2018 8:13 AM
それだと none の場合の表記がアドホックに定義できないし。
Avatar
そうだね、今やりたいのは .none のときに "" にしたいって話だからまた違う。
Avatar
omochimetaru 1/25/2018 8:14 AM
noneのときどうするかってのはコンパイラに怒られながらその場その場で決めていくものな感
Avatar
Conditional Conformance があっても、 extension Optional : CustomStringConvertible where Wrapped : CustomStringConvertible はまずそう。
Avatar
Kishikawa Katsumi 1/25/2018 8:15 AM
私はInterpolationはこのまま置いといて、型が作用するTemplate表記みたいなものの方がいいと思っています。 (edited)
Avatar
omochimetaru 1/25/2018 8:15 AM
extension String { init<X>(describing: Optional<X>, default: String) } ↑こういう選択肢も・・・・
8:15 AM
ただ Optional<X> 自体をデバッグダンプする場合と曖昧になるんだよな。
Avatar
infix operator ??? func ???<T>(lhs: Optional<T>, rhs: String) -> String { return lhs.map(String.init(describing:)) ?? rhs } let a: Int? = 0 print("\(a ??? "empty")") let b: Int? = nil print("\(b ??? "empty")") (edited)
8:16 AM
では?
Avatar
omochimetaru 1/25/2018 8:16 AM
型が作用するTemplate表記
@Kishikawa Katsumi これは、どんなものですか?
Avatar
Kishikawa Katsumi 1/25/2018 8:16 AM
いわゆるprintfなんですけどコンパイル時に間違いがわかる。
Avatar
omochimetaru 1/25/2018 8:16 AM
バックスラッシュパーレン \( ) とは別に用意する?
Avatar
Kishikawa Katsumi 1/25/2018 8:17 AM
フォーマッタを渡してカスマイズできるとか。
Avatar
一番良く使われるのが "\(foo)" である以上、それで CustomStringConvertible でないものを弾けないと "Optional(2018年)" を防ぎきれないと思うんですよねぇ。
Avatar
Kishikawa Katsumi 1/25/2018 8:17 AM
("% % %", a, b, c) <= なんかこんな感じの。
Avatar
omochimetaru 1/25/2018 8:17 AM
@t.ae それは @tarunon が最初に書いてくれた例に近くて、 文字列補間と関係ないところでもその演算子が使えちゃうのがdirtyに思うんだよね。
Avatar
露出するのはそうですね。
Avatar
Kishikawa Katsumi 1/25/2018 8:19 AM
String Interpolationは大して便利でもないけど、中途半端に書きやすいからそっち使おうとするので、
8:19 AM
同等程度に書きやすくて便利なものがある方がいい。
Avatar
omochimetaru 1/25/2018 8:20 AM
あ〜
Avatar
Kishikawa Katsumi 1/25/2018 8:20 AM
foo?.description ?? "" このように書くのは全く正しいけど、長いからこう書きたくないってことなので。 (edited)
Avatar
omochimetaru 1/25/2018 8:20 AM
単純な文字列化したいときにも "\(a)" って書いちゃうケースを考えているんですね。 (edited)
8:21 AM
なんかこういうケースを考えてました↓ return "User(name=\(name), petCat=\(cat))"
Avatar
今の話で思い出したけど、↓で警告も出ないのイケてないから CustomStringConvertible でないものを文字列補間に突っ込んだら警告がいいと思うんですがどうでしょう? struct Foo {} let foo = Foo() print("\(foo)") // Foo() (edited)
Avatar
omochimetaru 1/25/2018 8:22 AM
あ、でもこれもまあ String(format: "") 的に書くことができるか。
8:22 AM
個人的には書式置換よりも文字列補間の方が良いと思っていて、そっちを洗練させたいんですよね。
8:22 AM
理由は、流れで読んだときにどこに何が埋め込まれるかわかりやすいからです。 書式だと、プレースホルダと値の対応が左と右に分離していてわかりにくい。
Avatar
Kishikawa Katsumi 1/25/2018 8:23 AM
プレースホルダと値の対応が左と右に分離していてわかりにくい。
8:23 AM
それは同意です。
Avatar
@koher それはそのとおりだと思っていて、半年ほど前に実現しようとコンパイラをいじって,そのままほったらかしになってます 😿
Avatar
おお、そうなんですね
Avatar
だれかやってくれ~
8:23 AM
先にプロポーザル投げちゃってもいいのかな
Avatar
omochimetaru 1/25/2018 8:23 AM
今の話で思い出したけど、↓で警告も出ないのイケてないから CustomStringConvertible でないものを文字列補間に突っ込んだら警告がいいと思うんですがどうでしょう?
それはそれで同意で、 @tarunon を応援していた
Avatar
@tarunon Pitch だけなら良さそう
8:24 AM
Proposal 作るときは実装もいるけど
8:24 AM
機能の @d_date さんみたいに Pitch だけなら OK かと。
Avatar
途中までやったんだけど、コンパイルエラーになるべきところがオレオレワーニングで上書きされて涙を流した
😭 1
Avatar
omochimetaru 1/25/2018 8:24 AM
別のトピックとして、 String(format: "") が ObjC 由来で、 Swifty な標準がほしいという気持ちありますね
Avatar
Kishikawa Katsumi 1/25/2018 8:24 AM
自分が書きたいっていうのでなければ、アイデアとして放流したら誰かが助けてくれるのでは。
Avatar
ピッチの機運高まってきた
8:25 AM
やるか~
Avatar
omochimetaru 1/25/2018 8:25 AM
@d_date がハードル下げてくれた感ある。
🙏 1
Avatar
ここで揉んでforumに投げられるフローありがたいです🙏
🙂 2
Avatar
いきなりぶっこむと考え違いとか抜け漏れがありそうですし、英語で不毛な議論するの辛いですしね。
Avatar
今日はいつものメンバーの興味深い会話が Twitter で行われている模様。 https://twitter.com/omochimetaru/status/960373117376872448
@hiragram その2 「2行以上あるときに目に止めて内容をチェックすべき」よりも良い状態になる。 unwrapの利用を促進することで「guardがあるところにはただ死ぬ以外の何かが必ずある」 ことになる。
🙂 1
Avatar
Avatar
きっとあとでtogetterにまとめられて見やすくなる👀
Avatar
リプライたどるだけで良いのでは
4:46 AM
結論のでたツイートをここに貼れば全員幸せになれるよ
Avatar
第三者がメンションナシで絡んできてからがtogetter
Avatar
あ、スレッドだった
Avatar
ところでTwitter公式まとめ機能ができてたのでそれでも良い気がする(Toggetterの人ごめんね)
4:49 AM
使いやすいかは知らない
Avatar
class Foo { init!() { return nil } } init! 定義できるのに今更気づいたのですが、完全に使いどころがわからない。 (edited)
Avatar
激ヤバトラップだ
Avatar
ちょっと考えられるのが、 convenience init から self.init() で呼べるっていうのだけど、それにしても (edited)
6:46 AM
init?()self.init()! で呼べるし。
6:47 AM
廃止したほうがいいんじゃないか。
6:52 AM
func foo() -> Int! も一緒ですね。廃止して欲しい。
Avatar
どっちもObjCブリッジングで入り用になりそうな気がしますねぇ
Avatar
norio_nomura 2/5/2018 6:56 AM
CHANGELOG.mdに記述がありますね。 ### 2014-10-09 (Xcode 6.1) * Objective-C `init` and factory methods are now imported as failable initializers when they can return `nil`. In the absence of information about a potentially-`nil` result, an Objective-C `init` or factory method will be imported as `init!`. 今でもあるのかな?
Avatar
なるほどー。アトリビュートついてないObjCのブリッジングはそうせざるを得ないということなのですね。
Avatar
norio_nomura 2/7/2018 8:51 AM
func f(_ value: Int?) {} @available(*, deprecated) func f(_ value: String?) {} f(nil) // error: ambiguous use of 'f' deprecatedが付いてたら優先順位を変えてambiguous回避出来て欲しい。
Avatar
unavailable はどうでしょう?
Avatar
norio_nomura 2/7/2018 9:56 AM
nil以外だとambiguousにならないので、残せるなら残したいのです。
Avatar
前RxSwiftが踏んでましたね
Avatar
omochimetaru 2/7/2018 11:32 AM
ライブラリが型設計を改善するときにオプショナルが絡んでるだけで踏みそう
Avatar
RxSwiftが踏んだのは、defaultValueをnilにしていて、それ以外のラベルが全く同じ場合だった
1:13 PM
deprecated,unavailableで優先してくれれば発生しない問題ではある
Avatar
norio_nomura 2/7/2018 1:27 PM
unavailable指定はambiguous回避出来ますが、書き換え強制になっちゃうんですよね。
Avatar
async な関数って inout で渡された引数にアクセスできるのは最初の await までだけになるのかな?
2:13 PM
↓のページ内を inout で検索してもヒットしない・・・。 https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619
Concrete proposal for async semantics in Swift
Avatar
omochimetaru 2/9/2018 4:30 PM
そもそも使えないんじゃないですかねえ
4:32 PM
そもそもinout引数はエスケープもできないし。 func aaa(_ x: inout Int) -> () -> Void { func bbb() { x = 3 } return bbb } var t: Int = 3 aaa(&t)
4:33 PM
Swift:: Error: nested function cannot capture inout parameter and escape return bbb ^ Swift:: Error: expression resolves to an unused function aaa(&t) ^~~~~~~
Avatar
最初の await までは使えてほしいなぁ。
Avatar
@omochimetaru ↓これは @escaping でもできるっぽい。当然 @escaping しようが同期的な範囲でしか使えないけど。 func update<T>(_ value: inout T, _ operation: @escaping (inout T) -> ()) { operation(&value) }
Avatar
SourceKitにlibSyntaxのシリアライズデータを返す機能が追加されてたみたいだけど、どう活かすのだろう? https://github.com/apple/swift/pull/14000
The enhanced SourceKitd requests are EditorOpen and EdtiorReplaceText. In these two requests, the clients can specify a flag "key. enablesyntaxtree = 1" to get a serialize libSyntax tree with the r...
Avatar
omochimetaru 2/12/2018 1:40 PM
libSyntaxの呼び出しがSourceKitAPI経由になるPRもこの間入ってたのでそのための口じゃないですかね
Avatar
omochimetaru 2/12/2018 2:08 PM
それはそれとして、libSourceKitの内部的な下請けの処理も、libSyntax用の実装に差し替わっていくのかもしれないですけど。
Avatar
norio_nomura 2/12/2018 2:18 PM
良く知らないのですが、libSyntaxってそんな用途を考えられた感じなのですか?
2:19 PM
初見ではそんな感じには見えなかったのですが。
Avatar
omochimetaru 2/12/2018 2:20 PM
基本的にはパーサー部分を綺麗に作り直すプロジェクトだと思ってます
Avatar
norio_nomura 2/12/2018 2:23 PM
そうなんだ。
2:26 PM
SwiftSourceKitClientとか出来るのか。
Avatar
@d_date ご存知かもしれませんが、 Proposal の Status が "Awaiting implementation" になってます。 https://github.com/apple/swift への実装の PR との紐付けが必要かと。↓のように Proposal に Implementation の項目が必要です。 * Implementation: [apple/swift#13361](https://github.com/apple/swift/pull/13361) https://github.com/apple/swift-evolution/blob/master/proposals/0195-dynamic-member-lookup.md After reflecting on the evolution process during both the Swift 3 and Swift 4 releases, the Core Team felt that we could strike a balance with not diluting attention from ABI stability while still enabling a broader range of proposals compared to Swift 4 by **requiring that all proposals have an implementation** before they are officially reviewed by the Core Team. https://forums.swift.org/t/swift-5-start-your-engines/6456
swift - The Swift Programming Language
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Hi everyone, The proposal phase for Swift 4 is now officially over, and the release is now in endgame engineering convergence for an expected release later this year. Swift 4 has turned out to be one of the highest quality, well-rounded releases of Swift, and I am grateful to everyone in the community who made this release come together! Now it is time to turn our attention to Swift 5. I have just posted updates to the README.md file on the swift-evolution repository, which outlines the core...
Avatar
@koher ありがとうございます!実装中です🙏 (edited)
🙂 1
1:11 AM
返信先まちがったw
🙃 1
Avatar
#swift-zatsu から移動。
8:31 AM
Kotlin なら break: () -> Never 作れそう。
8:32 AM
どうしても今の Swift で async/await 相当のことできないと辛くなって、 Promise 改造して↓を作ったけど、 https://github.com/koher/AsyncK
AsyncK - An alternative of async/await in Swift
8:34 AM
非同期ループできないと辛いから↓ asyncFor を作って、 break() -> Never にできないか考えたけどダメだった。 func asyncFor<S: Sequence>(_ sequence: S, _ operation: @escaping (S.Element, _ break: @escaping () -> ()) -> Async<Void>) -> Async<Void> https://github.com/koher/AsyncK/blob/master/Sources/AsyncK/Async.swift#L80
AsyncK - An alternative of async/await in Swift
Avatar
Swift コンパイラかしこい。↓はコンパイルエラーになるけど、 AProtocol: class にしたらエラーなくなる。 protocol AProtocol { var value: Int { get set } } struct B<T: AProtocol> { private let t: T init(_ t: T) { self.t = t } func get() -> T { return t } } class A: AProtocol { var value: Int init(value: Int) { self.value = value } } func foo<T: AProtocol>(a: T) { let b = B<T>(a) b.get().value += 1 // ここでコンパイルエラー print(b.get().value) } foo(a: A(value: 2))
Avatar
omochimetaru 2/22/2018 5:28 AM
右辺値(get()の返り値)が値型の時はプロパティアクセスが左辺値として使えないけど 参照型の時はプロパティアクセスが左辺値として使える というルールが、プロトコルのclass制約に対して考慮されているんですね
Avatar
はい、そうです。
Avatar
omochimetaru 2/22/2018 5:30 AM
get() の代わりに subscript にすると、subscript は右辺値じゃなくて左辺値を返すから、 b のmutabilityが伝搬して、 このままなら var b が必要、 : class が付くなら let b で OK 、になるかな
Avatar
subscript だと引数がいるから computed property がいいかも
Avatar
omochimetaru 2/22/2018 5:33 AM
たしかに
Avatar
一応注意喚起しておくと class 制約は AnyObject と同意になり、 class は deprecated です。 https://github.com/apple/swift-evolution/blob/master/proposals/0156-subclass-existentials.md#class-and-anyobject
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 2/22/2018 5:36 AM
deprecated・・・!?
⁉ 1
Avatar
: AnyObject でまったく同じ意味になるので、機能が同じものを残しておく必要は無いということですね。
Avatar
omochimetaru 2/22/2018 5:37 AM
To reduce source-breakage to a minimum, class could be redefined as typealias class = AnyObject and give a deprecation warning on class for the first version of Swift this proposal is implemented in.
5:38 AM
あれ〜 気づかなかったな まだ警告は出ない?
Avatar
まだ出ないみたいですね
Avatar
同じく気付いてませんでした。前に見たけど忘れてたのかなぁ・・・。最近はずっと : class してた気がする。
Avatar
AnyObject、振る舞いが特殊すぎてなかなかこう
Avatar
omochimetaru 2/22/2018 5:43 AM
特別な存在
Avatar
いやまじで
5:43 AM
BuiltIn.AnyObject、凶悪
Avatar
omochimetaru 2/22/2018 5:44 AM
そこらへんの特別扱いがあるから、値型と参照型が言語の中で同じようなノリで使える
5:45 AM
厳密にしてしまうと、C++やRustみたいに参照型の取扱が型システム側で陽に露出して、アプリを書くのには面倒になる
Avatar
AnyObject と言えば、 Swift の関数(クロージャ)は参照型だけど ===AnyObject に対してしか使えなくて関数の同一性の比較ができないのどうにかならないのかな?
5:47 AM
厳密にしてしまうと、C++やRustみたいに参照型の取扱が型システム側で陽に露出して、アプリを書くのには面倒になる
うーん、参照型と値型を混ぜて扱うの、挙動のイメージが人間の(僕の?)認知能力を超えててヤバイ気がするんだけどなぁ。
5:48 AM
protocolinterface 作って、 protocol は値型、 interface は参照型と分けてしまってもいいんじゃないかという気がする。
Avatar
protocol MyProtocol: AnyObject { } class Foo: MyProtocol { } func foo<X>(_ v: X) where X: MyProtocol {} func bar<X>(_ v: X) where X: AnyObject {} let a: MyProtocol = Foo() let b: AnyObject = Foo() // foo(a) // 🙅 // bar(a) // 🙅 bar(b) // 🙆
5:49 AM
これなんやが
5:50 AM
例のProtocol変数はExisitential~の件で色々調べてて行き当たって
5:51 AM
AnyObject とは一体…ってなったやつ
Avatar
おおお・・・
5:51 AM
いや、でも Any も同じ?
Avatar
omochimetaru 2/22/2018 5:52 AM
bの型のAnyObjectは本当の型としてのAnyObjectで、 MyProtocol : AnyObjectやwhereのAnyObjectは型制約のAnyObjectで、 aの型のMyProtocolはExistentialだから自身を満たさないw
Avatar
これは本当に難しい
Avatar
omochimetaru 2/22/2018 5:53 AM
難しいね・・・
Avatar
public typealias AnyObjectってなってるのがね
Avatar
omochimetaru 2/22/2018 5:53 AM
b: AnyAnyObject って感じだよね
Avatar
事実上の振る舞いとしてはpublic class SwiftObjectのタイプエイリアスなんだろうなというのはわかる
5:54 AM
つまり、protocolの制約に使えるという特殊ルールを付加されたクラス型、そして汎ゆるクラス型のスーパータイプでもある。
😇 1
5:55 AM
Anyも確かに似たような振る舞いしますね。
Avatar
うーん、↑を考えると protocol Foo: AnyObject より protocol Foo: class の方がいい気がする・・・。
🙌 3
Avatar
omochimetaru 2/22/2018 5:55 AM
もう遅いw
😭 1
Avatar
さっきの Proposal にその辺りの議論まで書かれてるのかな?
Avatar
因みにこれですね、@objc が入ると更に大変なことになる
Avatar
omochimetaru 2/22/2018 5:56 AM
// foo(a) // 🙅 // bar(a) // 🙅 もうこのまま突き進んでこれが通る方に倒したい
Avatar
それExistentialじゃなくなるw
Avatar
omochimetaru 2/22/2018 5:57 AM
自動Erasure方式
Avatar
暗黙的にopenするのやばそう
5:57 AM
まあでも関数呼び出しは既に暗黙openingやし
Avatar
普通の protocol の existential ですでにそうなのが・・・
Avatar
import Foundation @objc protocol MyProtocol: AnyObject { } class Foo: NSObject, MyProtocol { } func foo<X>(_ v: X) where X: MyProtocol {} func bar<X>(_ v: X) where X: AnyObject {} let a: MyProtocol = Foo() let b: AnyObject = Foo() foo(a) // 🙆 bar(a) // 🙆 bar(b) // 🙆
😇 1
5:58 AM
@objc protocolは最早何でもあり (edited)
5:59 AM
そっか、この視点から見るとAnyObjectは振る舞いとしては@objc protocolに限りなく近い (edited)
Avatar
omochimetaru 2/22/2018 6:00 AM
@objc が付いた protocol は型として使うとExistentialじゃなくなる?w
Avatar
Existentialじゃないっぽいですね
Avatar
タイトルしか読んでないけど↓で変わったりしないのかな? https://forums.swift.org/t/objective-c-interoperability-eliminate-nsobjectprotocol/9947
Hi all, TL;DR I propose to completely eliminate the NSObject protocol (called NSObjectProtocol) from Swift, leaving only a deprecated typealias (to AnyObject) as a backward-compatibility shim. Motivation The Objective-C NSObject protocol, imported into Swift as NSObjectProtocol, is more harmful than helpful in Swift: The API it provides is not particularly useful in Swift, either because the functionality is better expressed via Swift language features (is and as? rather an isKind(of:) or c...
Avatar
omochimetaru 2/22/2018 6:01 AM
そのスレ気になってるけどヤバそうで読んで無いわ・・・
Avatar
%10 = open_existential_ref %9 : $Animal to $@opened("00DAD0B2-1796-11E8-B1A7-8C85902C8E53") Animal // users: %12, %12, %11 %11 = witness_method [volatile] $@opened("00DAD0B2-1796-11E8-B1A7-8C85902C8E53") Animal, #Animal.bark!1.foreign : <Self where Self : Animal> (Self) -> () -> String, %10 : $@opened("00DAD0B2-1796-11E8-B1A7-8C85902C8E53") Animal : $@convention(objc_method) <τ_0_0 where τ_0_0 : Animal> (τ_0_0) -> @autoreleased NSString // type-defs: %10; user: %12 %12 = apply %11<@opened("00DAD0B2-1796-11E8-B1A7-8C85902C8E53") Animal>(%10) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Animal> (τ_0_0) -> @autoreleased NSString // type-defs: %10; user: %14
6:04 AM
open_existential_ref って書いてあったわ、 @objc protocol
Avatar
omochimetaru 2/22/2018 6:05 AM
なるほど
Avatar
@takasek さっきの #swift-zatsu の話
3:48 AM
完全にワークアラウンドなんだけど
3:48 AM
class ReadWrite { } class ReadOnly: ReadWrite { } protocol IO { associatedtype Manifest: ReadWrite = ReadOnly } func foo<P>(_ arg: P) where P: IO, P.Manifest: ReadWrite { // ReadWrite }
3:49 AM
こんな風にassociatedtypeにFantomTypeを埋め込んでデフォルト型を定義しておくと
Avatar
omochimetaru 2/23/2018 3:49 AM
メンション先あってる? (edited)
Avatar
意図した型以外は弾けるようになってる
3:49 AM
あれ
3:49 AM
ごめん、 @lovee だったw
😇 2
Avatar
omochimetaru 2/23/2018 3:50 AM
typealiasで明示的にManifestをReadOnly ReadWriteに設定していない型だけ通るようになるのか (edited)
Avatar
えっと
3:51 AM
明示的にManifestをReadWriteにしないと
3:51 AM
自動でReadOnlyになるんだな
3:51 AM
assoctypeはGenericsと違ってデフォルト型が定義できる
Avatar
omochimetaru 2/23/2018 3:52 AM
デフォルトのゆるい型は駄目にして
Avatar
ん?ちょっと辺だった待ってw
Avatar
omochimetaru 2/23/2018 3:52 AM
指定した狭い型のための定義を用意する?
Avatar
class ReadOnly { } class ReadWrite: ReadOnly { } protocol IO { associatedtype Manifest: ReadOnly = ReadOnly } func foo<P>(_ arg: P) where P: IO, P.Manifest: ReadWrite { // ReadWrite } class UserDefaults: IO { } foo(UserDefaults()) // 🙅 (edited)
3:52 AM
これが正しい
Avatar
omochimetaru 2/23/2018 3:52 AM
@lovee がやりたいのは型パラメータ T が Optional では無いって条件みたいだけど適用できる?
3:53 AM
@tarunon 方式だとある具象型についてManifestを設定しないといけないから、駄目な気がする。
Avatar
それはそう
3:53 AM
うーん
3:53 AM
TがOptionalでない、はちょっと無理筋な気がしていて
3:54 AM
SwiftのOptionalはnullabelじゃなくて型なので
3:54 AM
そもやりたいことを考えたほうが良さそう。
Avatar
omochimetaru 2/27/2018 1:57 AM
classのmutating funcが無いと書けないやつがあるのはそうだかど
1:57 AM
書けなくても良いのでは @koher
Avatar
まあユースケースは確かにイマイチ思いつかないですね、どういう状況でしょう? 🤔
Avatar
イミュータブルクラスでは自身の更新を新規インスタンスを生成して再代入で行いますが
1:59 AM
var foo = ImmutableFoo() foo = foo.update(...)
2:01 AM
これを var foo = ImmutableFoo() foo.update(...) でできて代入が不要になります。 immutable なのに mutating なのは名前がややこしいですが、 immutability は失われてないです。
2:01 AM
イミュータブルクラスで mutating func を使えても、 self 自体の置き換えはできてもインスタンスの状態は変更できないのでインスタンスの immutability は保たれます。 (edited)
2:02 AM
まあ、値型使えばいいんですが。
Avatar
理屈は確かにそうですが、ただ class 自身が自分のオブジェクトを書き換えるのはどういうシチュエーションなのかが気になるんですね 🤔
Avatar
↑のシチュエーションはどうですか?
2:03 AM
Swift でイミュータブルクラスを作るシチュエーション自体があまりないかもしれませんが。
Avatar
omochimetaru 2/27/2018 2:04 AM
うーん・・・
Avatar
そもそも値型だろうと self 置き換えがあまりないのかな?
Avatar
omochimetaru 2/27/2018 2:04 AM
もしclassにmutating funcとnonmutating funcがあったとしたら
2:04 AM
ふつうにユーザーが想像するのは
2:04 AM
self書き換えを示すアトリビュートではなくて
Avatar
型システムの都合上classにするしかないが値型相当の取り扱いをしたい、というのはあり得るかなー
Avatar
omochimetaru 2/27/2018 2:05 AM
stored propetyの変更を許すかどうか
2:05 AM
っていうアトリビュートであることが期待されますよね。
Avatar
@tarunon ですねー。 Promise とかそれで class にしてます。
Avatar
そもそもclassだと複数の変数から参照されるから、 self 書き換えというのがいまひとつどれを書き換えているのか。
Avatar
@omochimetaru うん。 self 置き換え可能と、プロパティを書き換え可能は独立した機能な気がしてる。
Avatar
そういう場面でmutating funcは欲しいかもしれない。Rxだとsinkぶん投げて新しいObservable毎回作ってますが、そういう系でほしい場面はあるかも?
Avatar
プロパティの書き換え可能は class にとっては暗黙的に保証されてるけど、それとは別に var に格納されているときに self を書き換えられるという機能があり得るような。
Avatar
@hironytic 確かに 🤔 全部ってなるとなんかバグりそうな気がしないでもない
Avatar
omochimetaru 2/27/2018 2:07 AM
全部は原理的に実装不可能でしょうね 呼び出し元のvarだけかと。
Avatar
まあ、全部はないですよね。 varlet の両方から参照されていることもあるから。
Avatar
mutating func というか inout self をしたい。
Avatar
もしどうしてもやりたいんだったら、 protocol extension で 出来るので可能といえば可能なのですが、僕はそのAPIはちょっと気持ち悪いです。
Avatar
factory init術だ
Avatar
omochimetaru 2/27/2018 2:09 AM
既存仕様の傷口を広げられるようにしたいかどうか、みたいな感じ
2:10 AM
protocol existentialで扱ってる時は実際そうなるからな・・・
2:11 AM

導入

Swift には struct と class があります。 struct のメソッドには func ( nonmutating func の省略表記 ) と mutating func がありますが、 cla...
Avatar
おお、ほんとだできた。 protocol CharacterProtocol { init(name: String, hp: Int) var name: String { get } var hp: Int { get } mutating func update(hp: Int) } extension CharacterProtocol { mutating func update(hp: Int) { self = Self.init(name: name, hp: hp) } } class Character: CharacterProtocol { let name: String let hp: Int required init(name: String, hp: Int) { self.name = name self.hp = hp } } var character = Character(name: "ゆうしゃ", hp: 153) character.update(hp: character.hp - 10)
Avatar
//: Playground - noun: a place where people can play import UIKit protocol SelfRewritable { var id: Int { get set } init(id: Int) mutating func increaseID() } extension SelfRewritable { mutating func increaseID() { self = Self(id: self.id + 1) } } class User: SelfRewritable { var id: Int required init(id: Int) { self.id = id } } var user = User(id: 0) user.increaseID() user.id
2:15 AM
同じことやろうとしてたw
🙃 1
Avatar
var foo = Foo() var bar = foo bar.update(...) ってやったら、 foobar は別のものを指すようになるってことですよね。
Avatar
多分だけど、classのmutating funcの正しい動きは、「そのアドレスを参照する全ての変数でアドレスを変更」ではなく「mutating funcを呼び出した変数のアドレスを変更」がやりたいこと
2:17 AM
なので出来るようにしても壊れないんじゃないかなーと思うのだけれども。
Avatar
omochimetaru 2/27/2018 2:18 AM
壊れないことは壊れないと思います
Avatar
update がmutating funcかどうかがパッと見た目にわからないから、ぼくはそれは嫌かなー。
Avatar
なんかここの動作を保証したいなら、protocol: valueType が欲しいかな、mutating func 入れたい場合は
Avatar
微妙さはあると思いますが、同じことは値型にも言える気がするんですよね。 < update がmutating funcかどうかがパッと見た目にわからないから
Avatar
いや、値型はもともと共有されないので。
Avatar
omochimetaru 2/27/2018 2:20 AM
@lovee そこなんですけど、protocolとして扱うっていうのは、そもそも値的だと捉えるべきなんかなと最近思います
Avatar
イミュータブルクラスの場合、値型と同じだと思うんですよね。
Avatar
割りとある
Avatar
Mutableなクラスの場合は、共有している状態でupdateすることがあるじゃないですか。でも、言語的に、MutableなクラスかImmutableなクラスかもわからないので。
Avatar
class + convertible protocolで作ってstruct/enumとかはconvertible protocolに流すのが最近のワイのトレンド
Avatar
値型的だけど実装の都合上クラスにせざるを得ないときに、値型と同じように振る舞わせたい( API をそろえたい)ケースがあり得る気がしています。
Avatar
Immutableなクラスに限定すれば値型と同じようなものというのには同意します。
Avatar
たとえば↓のようなメソッドが標準ライブラリに追加されたとして extension Array { mutating func update(_ operation: (inout Element) -> ()) }
2:24 AM
Optional にも同じものを追加することはできますが、
2:24 AM
class で実装された Promise は同じような API を持っているのに update を追加できません。
2:25 AM
僕も積極的にほしいというほどじゃないんですが
Avatar
omochimetaru 2/27/2018 2:25 AM
classをラップしたCoWなstructを作るのは?
Avatar
現象を切り分けて整理するとそういうケースがありうるなと。
Avatar
omochimetaru 2/27/2018 2:26 AM
今話してるシチュエーションが、Arrayそれ自体の実装において起きてることな気がする。
Avatar
で、今の mutating funcinout self が混ざってしまっているのは、異なるものを一緒くたにしてしまっている気がします。
2:27 AM
@omochimetaru struct ラップはあり得るけど、 Array の場合はミュータブルだからラップが必要だけど、 Promise の場合イミュータブル的に振る舞うから、本来不要なラッパーができるのが微妙かなぁ。
Avatar
omochimetaru 2/27/2018 2:27 AM
一緒くたにしてるのはそう思います、値型に限って一緒くたにしてもいけるやろ!っていう機能ですよね
2:29 AM
不要なラッパーは増えるけど、言語機能の複雑さを増やさずにすみます @koher
Avatar
値型に限って一緒くたにしてもいけるやろ!っていう機能ですよね
うん。今さらどうにもできないけど、本来であれば分けておくことでシンプルにできた気がする。
Avatar
omochimetaru 2/27/2018 2:36 AM
classの実装でもstored propertyの変更を防止した実装ができるようになるけど
2:36 AM
その場合、プロパティでクラスのインスタンスを持つ場合に
2:37 AM
変数の型に対して参照不変性とオブジェクト不変性を記述しないといけないので
2:38 AM
mutating var cat: Cat var cat: Cat mutating let cat: Cat let cat: Cat
2:38 AM
を使い分けるプログラミングみたいになりますね
2:39 AM
c++がコレ。
Avatar
んほー
2:41 AM
よく見るやつだ
Avatar
@omochimetaru self 置き換えはまた別じゃない?
Avatar
omochimetaru 2/27/2018 2:45 AM
@koher self置き換えができない変数の型がないと、structでnonmutatingのなかでプロパティのself書き換えが起きたら困る
Avatar
mutating funcself 置き換えができないようにして、それとは別に self 置き換えがあって区別できるのがいいかなと。そしたら、前者は var な値型のみ、後者は var ならクラスでも使えるようになる。
Avatar
omochimetaru 2/27/2018 2:49 AM
ああなるほど
2:50 AM
じゃあletなクラスがmutating funcを呼ぶことは許すわけですね
2:50 AM
現状に対する追加的な仕様としてはまとまりますね
Avatar
↑の mutating func が構文のことではなく(今の Swift の class のインスタンスメソッドと同じように) Stored Property を変更可能なメソッドのことならそうです。
Avatar
omochimetaru 2/27/2018 3:23 AM
はい struct は今と同じ class には 新たに mutating func と update func を導入 class は今まで func で stored property が変更可能だったがこれを禁止 stored property の変更は mutating func の中でのみ可能に変更 update func では実装文中で self への代入が可能 mutating funcとupdate func は同時指定可能 (mutating update func がある) という仕様にして class Cat { ... } var cat: Cat に対しては mutating func は呼び出し可能、 update func は呼び出し可能 let cat: Cat に対しては mutating func は呼び出し可能、 update func は呼び出し不可能 これまでの struct の mutating func については、暗黙に mutating update func とする とすれば var / let 変性は update func の呼び出しを制限するものとして互換性が通る。
3:28 AM
この拡張のメリット ・class実装時においてもstored propertyの変更を静的にチェックされたコードが書ける ・self変更の概念がstruct/classで共通化されてわかりやすくなる
Avatar
僕のイメージは↓です。↑の update func という構文を踏襲するなら。
  • mutating func は値型にのみ使用可能で Stored Property を更新可能、 self 置き換えは不可能、変数のような可変な lvalue に対してのみ呼び出し可能
  • update func は値型にも参照型にも使用可能で self 置き換えが可能、変数のような可変な lvalue に対してのみ呼び出し可能
(edited)
3:30 AM
protocolmutating funcclass でどうなるかは考え中。
Avatar
omochimetaru 2/27/2018 3:32 AM
値型の場合、全てのstored propertyを書き換える事でself書き換えと同じ効果が発生させられるので、update func と mutating func を分ける意味が無いのでは?
Avatar
メモリ的な意味では値型はプロパティーの書き換えとselfの書き換えは等価ですが、ただ例えばどうしてもイニシャライザーを通して生成したいもの( Range とか)ですと update func と mutating func の区別は生じる気がしないでもない 🤔
3:36 AM
RangelowerBoundupperBound は let 宣言なので
Avatar
omochimetaru 2/27/2018 3:36 AM
なるほど!
Avatar
逆に言うと mutating func を呼び出しても let プロパティは変更されないことが保証できるようになるね。
Avatar
omochimetaru 2/27/2018 3:45 AM
struct Stone {} let stone: Stone に対する stone の mutating func は呼び出せないのでは? それを呼び出せるようにするってことですか?
Avatar
@omochimetaru struct Character { let name: String var hp: Int mutating func foo() { self = Character(name: "Hoge", hp: hp) } } var character = Character(name: "ゆうしゃ", hp: 153) character.foo() print(character.name) // "Hoge" (edited)
Avatar
omochimetaru 2/27/2018 3:51 AM
あーそういうことか
3:51 AM
self代入経由でのlet強制変更テクニックを無くせる
Avatar
どうでもいいこと言いますと、サンプルコードとしては問題ないですが、ただ Character はそもそも値型ではなく参照型で作るべきなのでは?と思わなくもないですね
3:53 AM
値型だと Character が代入されるたびにコピーされてしまうのでw
Avatar
↑を struct でやるのが僕の try! Swift のワークショップなのです😇
Avatar
あとこの際、mutating funcとupdate func の区別をどうやって宣言で切り分けるのかも気になりますね…structですと、letで宣言するとnameもhpも変更できず、逆にvarで宣言するとどっちも結果として変更できる仕様になってしまいますので
Avatar
let var じゃたりない... const<おいすー^^
Avatar
@lovee ↓みたいなのをイメージしてます。 update は単語が微妙だったので replacing にしてみました。 struct Character { let name: String var hp: Int mutating func a() { self = Character(name: "Hoge", hp: hp) // NG } replacing func b() { self = Character(name: "Hoge", hp: hp) // OK } mutating func c() { self = Character(name: name, hp: 42) // NG hp = 42 // OK } replacing func d() { self = Character(name: name, hp: 42) // OK } } (edited)
4:01 AM
mutating replacing func もありです。
Avatar
はい、それは問題なく理解できますが、ただきになるのは var character: Character の方の宣言ですね…
4:02 AM
どうやって charactera()c() が呼べて b()d() が呼べない、もしくはその逆の保証をするのかですね…
Avatar
var character だと mutatingreplacing も呼べる想定ですね。 (edited)
Avatar
はい、ですがその場合ですと mutatingreplacing の区別をする意味がなくなるのでは?というところです
Avatar
実装のわからない mutating func をコールした場合に let プロパティが書き換えられてしまうことがないことを保証できます。
Avatar
omochimetaru 2/27/2018 4:04 AM
@lovee mutating func の中からは mutating func しか呼べない、replacing func の中では stored propery の var が変更できない、など、実装時の安全性が上がる
Avatar
また、これだと replacing funcclass でも使えます。
Avatar
むしろ replacing は参照型限定にした方が実装の意味がある気がします 🤔
Avatar
omochimetaru 2/27/2018 4:05 AM
それだと僕の案に近いですね
Avatar
値型に replacing 導入しても、結局 var だとその実装が呼べる呼べない区別ができなくなってしまいますので
Avatar
うーん、↓を防ぎたいニーズはむしろ現実的にありそうな気がしています。再代入以外で let プロパティが書き換えられてるのって直感に反しませんか? struct Character { let name: String var hp: Int mutating func foo() { self = Character(name: "Hoge", hp: hp) } } var character = Character(name: "ゆうしゃ", hp: 153) character.foo() print(character.name) // "Hoge"
4:07 AM
replacing func を呼ぶ場合は &character.foo() とか特殊な構文にしてもいいかも?
Avatar
@koher そのコードで防ぎたいことはわかりますが、ただ結果として値型ですとそもそも var 宣言使うと replacingmutating も使えるし、逆に let 宣言使うと replacingmutating も使えなくなって、区別ができなくなってしまうのが気になるポイントです
Avatar
なので、 replacing func の呼び出しは inout のように変化を付けたいですね。
Avatar
値型に対して letvar 以外の第3の宣言が必要になってくると言語仕様がどんどん複雑に… 🤔
4:10 AM
inout character: Character 的な宣言です?
4:10 AM
あ違うか、inout letinout var にしないとですね 🤔
Avatar
いや、 &character.foo() 的な。
4:10 AM
コール側ですね。
Avatar
要はそれがコール側でもそもそも var じゃないと &character 使えないですね (edited)
Avatar
replacing func は使えないようにしたいけど mutating func は使いたいというニーズはほぼないと思うんですよね。
4:11 AM
いや、あるかもしれないですが、それはまた別の話だと思います。
Avatar
omochimetaru 2/27/2018 4:11 AM
@koher extension Int { mutating func double() { self = self * 2 } } var i = 3 &i.double() こう? (edited)
Avatar
@omochimetaru そんな感じ。
4:12 AM
だけど、
4:12 AM
今は inoutmutating と等価だから、 & で被るのは微妙かも。
Avatar
omochimetaru 2/27/2018 4:12 AM
僕は @lovee さんとは逆で、struct ユーザ側で replacing と mutating を分けるのは変な気がする
4:13 AM
Int みたいな型を考えたときに、 self 全体変更と部分変更を区別して考えるのは
4:13 AM
内部のデータ構造の実装詳細が露出してることになる
4:13 AM
structは部分も全体も内部実装に隠蔽されているのが良い
4:13 AM
classの場合は、「stored propery」の書き換えと、保持してる側のポインタの書き換え は、現状でも明確に区別が必要なことだからOK
Avatar
@omochimetaru でもそもそも根本的な問題として、現状の仕様として let 宣言使う以外 &i を防ぐ手段がない、というのば私が言いたいことですね
Avatar
@lovee さんの replacing できないけど mutating できる第三の変数みたいなのもあり得るけど、それの意味するところは再代入できるけどプロパティの更新はできる変数と定数の中間のものを作りたいということになるから (edited)
4:15 AM
それを検討する価値はあると思うんですが、 replacing func とは直交する話な気がします。
4:15 AM
(結果的にそれが mutating 可と replacing 不可を実現するのであって、概念としては直交してる気がします。)
Avatar
まあ @koher さんが言ってるのはプロパティーの再代入と自分自身の再代入を区別したい、という話はわかりますが、ただ現状値型の場合それが等価になってしまいますので、せいぜいソースコード上で i.foo() と書くか、&i.foo() とかくかの区別だけしかできない、というのが私の懸念点ですね
4:28 AM
ですので @omochimetaru さんの主張で replacing を参照型だけのものにするか、もしくは値型にも replacing を導入するのあら、何らかの宣言レベルでの区別が欲しいというのが私の考えです
4:29 AM
ただどっちもSwiftの仕様をさらに複雑化しているのが否めない感が 🙃
Avatar
↓これは let プロパティを更新する挙動をするので利用者を驚かせてしまうと思うんですが、 var character = Character(name: "ゆうしゃ", hp: 153) character.foo() print(character.name) // "Hoge" ↓これだと驚かないと思うんですよね。 var character = Character(name: "ゆうしゃ", hp: 153) character = Character(name: "Hoge", hp: character.hp) print(character.name) // "Hoge"
4:31 AM
なので、 var 自体ができることをどうこうしたいというわけではなくて
4:31 AM
メソッドコールのスタイルで let プロパティが書き換えられてしまうことを防ぎたいということです。
Avatar
letに関しては一番外側がletじゃなければ大して意味ないよなというのは気づいて理解してるつもりだけど
4:32 AM
わからないとわからないのか。
4:32 AM
4:32 AM
理解してないと混乱してしまうのか
Avatar
なので &character.foo() のようにコール時に明示的な区別がされれば OK だと思います。
Avatar
omochimetaru 2/27/2018 4:33 AM
@tarunon 自分の直感がローレイヤのメモリモデルの方にあるから自分は驚かないけど、人によるのかなと思った。
Avatar
似たようなことは inout ですでに行われていて、もし↓のコードが & なしでコールできたらユーザーを驚かせてしまうと思うんですね。 var a = 2, b = 3 swap(&a, &b) print(a) // 3 print(b) // 2
Avatar
なので &character.foo() のようにコール時に明示的な区別がされれば OK だと思います。
それを突き詰めると、そもそも値型でメソッドを呼んだら自分自身のプロパティーが変わった、ということ自体も明確にして欲しいという欲求が出てきてしまいそうな気が… 🙃
Avatar
プロパティを変えられるかどうかはプロパティを var で宣言するか let で宣言するかで区別しているので
4:35 AM
var のプロパティが変更されることは当然あり得ると思うんですが、 let のプロパティが変更されるのは直感に反しませんか?
Avatar
omochimetaru 2/27/2018 4:36 AM
letのプロパティが変更されてるんじゃなくて、letのプロパティを持つ struct 全体が差し替わっている
4:36 AM
結果的に、そのletの場所が変わったようにも見える(同一視できる)
Avatar
僕も前は↓の意見でしたが、ちょっと意見が変わってきています。 https://qiita.com/omochimetaru/items/7265e440418b38088ccb

記事について

この記事は potatotips#39 という勉強会で発表した内容を再掲したものです。スライドの画像と、喋った言葉を載...
Avatar
omochimetaru 2/27/2018 4:37 AM
struct全体が可変であることはstructを持ってるvar側で表明してること
Avatar
メモリ上の挙動を考えればその通りだけど、
4:38 AM
その考え方でいくと、せっかく言語が提供している( struct のプロパティで) varlet かを区別する機能を殺してると思うんですね。
Avatar
大事なのは一番外側がletかvarかで
4:39 AM
内側は大してアテにならない
Avatar
omochimetaru 2/27/2018 4:39 AM
init経由するときに制約がかけられるという実装側での意味がありますね
4:40 AM
structのプロパティでletにできる意味。それ以外は無意味。
Avatar
initでvalidationした値はletに入れると安全とかありますね、確かに
Avatar
omochimetaru 2/27/2018 4:40 AM
たとえletであっても、ユーザー側でextensionを使ってsetterを生やせる。ただし、そのsetterの実現にあたってinitを経由する制約だけは残る。
4:41 AM
原則の意見は↑のスライドと変わってないけど、考慮すべき例外条項がなんなのか、という点については考え続けていて、↑に至った。
Avatar
mutating funcreplacing func を分ければ「たとえletであっても、ユーザー側でextensionを使ってsetterを生やせる。」も同じものは提供できなくなります。 replacing func のコールで & 必須だと。
Avatar
omochimetaru 2/27/2018 4:43 AM
ですね
Avatar
まあ確かに i.foo() より &i.foo() の方がわかりやすい、というのはわかりますが、そこまでやるならやはり inout var i 宣言が欲しいかな、と思います
4:45 AM
でないとせっかく目立つものを作ったのにコンパイルレベルで保証できないってのはなんか悲しい (edited)
Avatar
そうですね〜。僕も自分の言ってることが本当に意味のある区別なのかイマイチ確信が持ててないですが、直感的に意味がある気がしています。いい例を思い付いたらまた書きますね🙂
Avatar
i += 1 // i = i + 1 だから、 i.=foo() // i = i.foo() とか(いや、やりたいことと違う)。
Avatar
例えば参照が古き良き ->だったら (edited)
6:52 AM
i=>foo() // i = i -> foo() とかワンチャンあったかも(ない)
Avatar
norio_nomura 3/1/2018 5:16 AM
Swift 4.1でメソッドオーバーロードの判定が賢くなってた。 protocol P1 { init() } protocol P2 { init() } struct S { func a<T: P1>(_ type: T.Type) -> T { return a(type) ?? type.init() } private func a<T>(_ type: T.Type) -> T? { guard let p2Type = type as? P2.Type else { return nil } return p2Type.init() as? T } } extension Int: P1 {} S().a(Int.self) // Swift 4.1より前は無限ループ
Avatar
4.1、型推論も賢くなってますね
Avatar
omochimetaru 3/1/2018 4:02 PM
funcのaが<T: P1>で、private funcのaが<T>で・・・、
4:03 PM
無限ループしないってことは、上のaの中で呼んでるaはprivateの方が呼び出されるってことですか?
4:04 PM
上のaの中で呼んでるaも、上のaになるのが正しいと思いました、制約がキツイ方を優先するから。何か見落としてる??
Avatar
Optional<T> 期待になるから private 側が呼び出されてるってことっぽい。
Avatar
omochimetaru 3/1/2018 4:35 PM
あ〜、??の左辺だからか。ということは、4.0では、 T に推論した上で Optional<T> への暗黙のアップキャストが推論されるアレだったのが、変わったということですか!
4:48 PM
手元の4.0環境だと (inject_into_optional implicit type='T?' location=a.swift:12:16 range=[a.swift:12:16 - line:12:22] (call_expr type='T' location=a.swift:12:16 range=[a.swift:12:16 - line:12:22] nothrow arg_labels=_:
4:49 PM
a(type) のところの call_exprがTで、その一個上に inject_into_optional があるからそうっぽい
4:49 PM
4.1だと inject_into_optionalが無くて call_exprが T? になっているのかな。
Avatar
omochimetaru 3/1/2018 5:12 PM
[omochi@omochi-MB2 infer]$ export TOOLCHAINS=org.swift.3020180227a [omochi@omochi-MB2 infer]$ swift --version Apple Swift version 4.1-dev (LLVM c4ec2ab808, Clang af436f313e, Swift 5f2f440067)
5:12 PM
snapshot 2/27の4.1で試したけど同じように落ちた・・・
Avatar
omochimetaru 3/1/2018 11:07 PM
@norio_nomura#8334 試した4.1はどれですか?
Avatar
norio_nomura 3/1/2018 11:16 PM
Xcode 9.3 beta 3のPlaygroundもswift-4.1-DEVELOPMENT-SNAPSHOT-2018-02-28-aのREPLも落ちないです。 (edited)
Avatar
omochimetaru 3/1/2018 11:17 PM
あれ〜 会場ついたら改めてやってみます。
Avatar
↑普通に動いた。おもちのXcode壊れてるんやない?
12:28 AM
↑なんか違う?
Avatar
昨日のDev版が壊れた?
Avatar
norio_nomura 3/2/2018 12:35 AM
それはswift-DEVELOPMENT-SNAPSHOT-2018-02-27-aですね。
12:36 AM
masterのスナップショット。
12:39 AM
swift-4.1-branchのスナップショットならorg.swift.3020180227aではなくorg.swift.4120180227aなはず。
Avatar
omochimetaru 3/2/2018 12:42 AM
そっちもやってみます!
Avatar
omochimetaru 3/2/2018 1:15 AM
あ〜いけました org.swift.4120180228a だと実行できた。
1:18 AM
(call_expr type='T?' location=a.swift:12:16 range=[a.swift:12:16 - line:12:22] nothrow arg_labels=_:
1:18 AM
予想通り式自体が aのT がT? で推論されて、暗黙キャストが無くなった (edited)
1:19 AM
推論候補探索の優先度付けが変わったって事かな
Avatar
Data の↓の引数が UnsafeRawBufferPointer じゃないのってなんでなんですっけ? init(bytes: UnsafeRawPointer, count: Int) https://developer.apple.com/documentation/foundation/data/1780158-init (edited)
Avatar
でもわざわざ NSData とは別に Data を作ったわけで、 RawBuffer でもよかった気がするんですがいかがでしょう?
8:44 AM
もしかして、 Data の導入とポインタ系の整理のタイミング問題でそうなってしまったとか?
Avatar
UnsafeRawBufferPointer 版が無いのは UnsafeRawBufferPointer が出てきたときに Data 側対応が漏れているだけだと思います。
Avatar
なるほど。
8:47 AM
じゃあ、これと↓に Buffer 版を追加しようという提案はあり得そうですね。 https://developer.apple.com/documentation/foundation/data/1780455-init
Avatar
アリだと思います!
🙂 1
Avatar
さくっと https://github.com/apple/swift-evolution/blob/master/proposals/0138-unsaferawbufferpointer.md の addendum としてフルプロセス通さずに実装される可能性もありそう。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
なるほど。どちらにしても一度 evolution に pitch として投げてみると良さそうですね。
👍 1
Avatar
これはバグでしょうか?多分 [array] が再現のポイントです。それがなければ通ります。 func foo<R, T>( array: [T], operation: (Int) throws -> R ) rethrows -> R { return try array.withUnsafeBytes { [array] _ in return try operation(array.count) } } error: repl.swift:5:16: error: call can throw, but the error is not handled; a function declared 'rethrows' may only throw if its parameter does return try array.withUnsafeBytes { [array] _ in ^ repl.swift:5:38: note: call is to 'rethrows' function, but argument function can throw return try array.withUnsafeBytes { [array] _ in ^ (edited)
Avatar
それがなければ通ります。
手元環境 Xcode Version 9.2 (9C40b) だと error: overlapping accesses to 'array', but modification requires exclusive access; consider copying to a local variable です。
(edited)
9:43 AM
いずれにしてもこのエラー(call can throw, ...)はバグっぽい。 (edited)
Avatar
探してみて類似のものがなければレポートしておきます🙂 (edited)
Avatar
@rintaro
手元環境 Xcode Version 9.2 (9C40b) だと
↑のコード、投稿後すぐに修正したんですが、コード修正前じゃないでしょうか? https://wandbox.org/ で Swift HEAD 4.2-dev だと [array] なくせば通りました。
Avatar
おー、そうだったみたいです。9C40b で通りました。
🙏 1
Avatar
レポートしました。実は初めてな気がする・・・。 https://bugs.swift.org/browse/SR-7120
🎉 3
Avatar
omochimetaru 3/8/2018 5:08 AM
Hi, I am thinking about writing a Protocol Devirtualizer Pass that specializes functions that take Protocols as arguments to transform them with concrete types instead of protocol types when the concrete types can be determined statically by some compiler analysis. This is the first step of the transformation that I am proposing. My goal is to extend this to eliminate the original function implementation and also to remove the corresponding protocol type (by deleting it from the witness t...
5:09 AM
@ukitaka ↑プロトコル devirtualize の最適化の実装の話し合いのスレがあった。 フォーラムでアルゴリズムの相談してからPR出す、みたいなのもあるんですね
Avatar
おー、specializeされてるなら具体型が静的にわかるから最適化できるってことかな、まさにこの前話してたようなやつっすね!
Avatar
omochimetaru 3/8/2018 5:32 AM
(まだ詳細は見てないので後で見ます)
Avatar
もう実装もあるんですね https://github.com/apple/swift/pull/13991
Protocol Devirtualizer Pass that specializes functions that take Protocols as arguments to transform them with concrete types instead of protocol types when the concrete types can be determined sta...
Avatar
これは面白い。PR単位なら何となくわかる気がした
2:01 AM
Array.withUnsafeMutableBufferPointerがbodyにinout UnsafeMutableBufferPointerを渡すんだけど
2:01 AM
defer { _precondition( inoutBufferPointer.baseAddress == pointer && inoutBufferPointer.count == count, "${Self} withUnsafeMutableBufferPointer: replacing the buffer is not allowed") (work, self) = (self, work) }
2:01 AM
inoutを用いて書き換わってるとエラーになる。
Avatar
チャネル変わってない?
Avatar
omochimetaru 3/13/2018 2:02 AM
話題分けた
Avatar
なるほど。
2:02 AM
これって単に「 inoutout を除いたもの」として、 @escaping なクロージャにキャプチャされるのを防ぐために使われてるのかな?
2:03 AM
そうだとしても、 withUnsafeBufferPointer がそうなってないのが謎だけど。
2:16 AM
元は、保持するバッファそのものを書き換え可能なAPIだったぽい。
Avatar
元は、保持するバッファそのものを書き換え可能なAPIだったぽい。
ヤバげな感じだしますね・・・。
Avatar
omochimetaru 3/13/2018 2:18 AM
This results in a a massive speedup and could in principle be applied to other bulk array mutations. Swift SVN r18926
2:19 AM
僕もやっとinoutがついた瞬間のコミットに辿りついた (edited)
Avatar
norio_nomura 3/13/2018 2:26 AM
そっちの方がそれっぽいか。どちらにしろ、もうinoutじゃなくても良さそうだけど、escapingに渡すのを防げてるのは好都合ですね。
2:31 AM
withUnsafe*Pointer系は全部そうなってても良い気がする。
Avatar
ですよね。 withUnsafeMutableBufferPointer だけそうなのがよくわからない。
2:34 AM
そして、ポインタ自体の書き換えを禁止するなら、やっぱり inoutout なし版( @escaping に渡すのを防ぐだけ)がほしい。
Avatar
たまたま見つけたんですが import UIKit protocol SomeChild where Self : UIViewController { func doSomething() } extension SomeChild { func doSomething() { print(self.title) } } class ChildViewController: UIViewController, SomeChild {} class ParentViewController: UIViewController { var children: [SomeChild] = [ChildViewController()] var child: SomeChild = ChildViewController() } let parent = ParentViewController() parent.child.doSomething() parent.children.forEach { $0.doSomething() } childにアクセスすると問答無用でEXC_BAD_ACCESSになる
11:34 AM
extension側に where句 付けると問題なし protocol SomeChild { func doSomething() } extension SomeChild where Self : UIViewController { func doSomething() { print(self.title) } }
Avatar
オッこれは…
11:39 AM
Existentialが壊れてるじゃないですか!大好物です
😱 2
Avatar
Kishikawa Katsumi 3/16/2018 11:39 AM
EXC_BAD_ACCESSって理由はStackoverflowですか?
11:40 AM
違うな。
Avatar
witness tableの実装からobjc_msgSend見てて
11:41 AM
Selector見つからないからホゲホゲになってる気がする
11:45 AM
Xcodeがしんだ
Avatar
OjbC起因かとも思い試しにLinux版でも試すとBAD_ACCESSでますね class Object {} protocol SomeChild where Self : Object { func doSomething() } extension SomeChild { func doSomething() { print(self) } } class ChildObject: Object, SomeChild {} class ParentObject: Object { var children: [SomeChild] = [ChildObject()] var child: SomeChild = ChildObject() } let parent = ParentObject() parent.child.doSomething() parent.children.forEach { $0.doSomething() }
Avatar
Existentialなのかwitnessなのか問題を切り分けるのに
Avatar
existentialに入れてる事とSelf制約の2点かな?
Avatar
Generics実装作ったらそっちは動いた
11:47 AM
import UIKit protocol SomeChild where Self : UIViewController { func doSomething() init() } extension SomeChild { func doSomething() { print(self.title as Any) } } class ChildViewController: UIViewController, SomeChild {} class ParentViewController<C: SomeChild>: UIViewController { var children: [C] = [C()] var child: C = C() } let parent = ParentViewController<ChildViewController>() parent.child.doSomething() parent.children.forEach { $0.doSomething() }
11:48 AM
クラス制約プロトコルのExistentialが壊れていて、witnesstableからobjcランタイムを参照して死
11:48 AM
と言う流れな気がしたがーもうちょい
Avatar
モアイさんがLinuxで再現してるからオブシーは関係ないかと
Avatar
デフォルト実装である必要はない class Object {} protocol SomeChild where Self : Object { func doSomething() } class ChildObject: Object, SomeChild { func doSomething() { print("hello") } } class ParentObject: Object { var children: [SomeChild] = [ChildObject()] var child: SomeChild = ChildObject() } let parent = ParentObject() parent.child.doSomething() parent.children.forEach { $0.doSomething() }
11:50 AM
class Object {} protocol SomeChild where Self : Object { func doSomething() } class ChildObject: Object, SomeChild { func doSomething() { print("hello") } } let c: SomeChild = ChildObject() c.doSomething() // 😇
11:50 AM
最小コードはここかな
11:50 AM
クラス制約プロトコルのExistentialは壊れていてメソッドを呼び出せません!完
11:51 AM
報告しよう @moaible
Avatar
な、なるほどJIRAにチケット登録すれば良いんでしたっけ?
Avatar
Yes!
11:52 AM
ん?なんかそもそも変だぞ
11:52 AM
class Object { var x: Int = 1 } protocol SomeChild where Self : Object { func doSomething() } class ChildObject: Object, SomeChild { func doSomething() { print("hello") } } let c: SomeChild = ChildObject() c.x // Compile Error c.doSomething() SomeChildはObjectを満たしているはずだが、xを呼び出せない
11:53 AM
Existentialだからか?でもこれは…
Avatar
let c: SomeChild & Object = ChildObject() って書くと動く。
Avatar
ですね
Avatar
protocol SomeChild where Self : AnyObject { func doSomething() } class ChildObject: SomeChild { func doSomething() { print("hello") } } let c: SomeChild = ChildObject() c.doSomething() 最小これか。まあこれは protocol SomeChild: AnyObject { って書けば良いじゃんて話ですが。
11:55 AM
とにかくバグはバグだと思いますね。
Avatar
これSelf:AnyObject:AnyObjectで動き変わるんすね
11:56 AM
前者は__SwiftObjectということになってるのかな
11:56 AM
後者はclass
Avatar
witness テーブル 読みにいってるんだけど実際は vtable でした、か、逆か。
11:58 AM
そんな感じのことが起こってる気がする。
Avatar
class前提プロトコルをextensionした時に
Avatar
TYPE MISMATCH IN ARGUMENT 0 OF APPLY AT expression at [<REPL>:12:1 - line:12:15] RangeText="c.doSomething()" argument value: %13 = open_existential_addr immutable_access %6 : $*SomeChild to $*@opened("25C7E87E-2911-11E8-A83E-0242AC110002") SomeChild // user: %14 parameter type: $@opened("25C7E87E-2911-11E8-A83E-0242AC110002") SomeChild
Avatar
本来witness-tableに行くはずのものがvtableに乗ってるみたいな (edited)
11:58 AM
そういうのが有り得そう
Avatar
protocol … where Self: …っていう書き方、最近まで知らなかった。
Avatar
ひらりぷろとこる
12:01 PM
あーーー
12:01 PM
この間ですね、この記法のプロトコル使ってバグふんでたんですが、最小コード見つけられなくて諦めてたのがある
12:01 PM
もしかしたらこれ参考にすれば最小見つかるかもしれない
12:02 PM
雰囲気は、制約をすべて満たしたはずなのにコンパイルが通らなくなる感じです。
Avatar
とりあえず作りました、こんな感じで良かったのか... https://bugs.swift.org/browse/SR-7214
👏 5
Avatar
This code crashes. But this code works. の方が良いと思う。
🙏 1
12:32 PM
あと、タイトルの文字列が何をやると出るものなのか説明したほうがよし
12:32 PM
(コマンドライン
🙆 1
Avatar
class制約付きprotocolのexistentialが一般に壊れてる事がわかった方がいいかも
🙆 1
Avatar
Swift 4.1 でも Optional: Hashable where Wrapped: Hashable になってないみたいですがなぜでしょう?
Avatar
omochimetaru 3/19/2018 8:17 AM
Optional : Equatable とか Array : Hashsable はなってるんですっけ?
Avatar
https://github.com/apple/swift/pull/14527 まだマージされてないです。
As a followup to SE-0143, this adds conditional conformance to Hashable to the following types in the standard library: Optional Array, ContiguousArray, ArraySlice Dictionary Range, ClosedRange An...
💡 1
Avatar
お、なるほど。 Equatable はもう実装されてるようなので、もし Hashable も同じようにするならもう実装済みだろうと思いこんでました。
Avatar
omochimetaru 3/20/2018 5:34 AM
func makeFunc<A, R>(argType: A.Type, returnType: R.Type, body: @escaping (A) -> R) -> (A) -> R { return body } makeFunc(argType: Int.self, returnType: String.self) { String($0) }(3) makeFunc(argType: (Int, Int).self, returnType: (String, String).self) { (String($0.0), String($0.1)) }((1, 2)) makeFunc(argType: Void.self, returnType: Void.self) { _ -> Void in print(33) }(()) // error makeFunc(argType: ().self, returnType: Void.self) { _ -> Void in print(33) }(()) // error makeFunc(argType: Void.self, returnType: ().self) { _ -> Void in print(33) }(()) print( ().self is Void.Type ) // false print( Void.self is ().Type ) // true
5:34 AM
()Void は違うものだった?
Avatar
print(().self is ().Type) // false print(Void.self is Void.Type) // true
❗ 1
5:36 AM
()の扱いが特殊そう?
Avatar
()はVoidのインスタンスとしても使えるらへんになんかありそう
Avatar
omochimetaru 3/20/2018 5:37 AM
たしかに。Void は型だけで値に使えないし。
Avatar
print(().self is ()) // true
Avatar
print(().self == ()) // true 何だこれは
Avatar
omochimetaru 3/20/2018 5:41 AM
// error だけど 引数のところは許された・・・ makeFunc(argType: (), returnType: ()) { _ in print(33) }(())
Avatar
expression が許されている箇所で () を型としては扱えないようです。
5:42 AM
let a = [()]() // error
Avatar
omochimetaru 3/20/2018 5:44 AM
値の () と 型の () があるのか
Avatar
omochimetaru 3/20/2018 5:47 AM
FIXMEだ
Avatar
()が型である必要って今何かあるんですっけ? 前は()->Voidで必要でしたけど (edited)
Avatar
omochimetaru 3/20/2018 5:50 AM
この関数おもしろいな
Avatar
(Int) -> () 型を禁止するわけにはいかないからでしょうか。
Avatar
omochimetaru 3/20/2018 5:50 AM
// Fold 'P & Q' into a composition type if (auto *binaryExpr = dyn_cast<BinaryExpr>(E)) {
5:51 AM
最初は演算子の&で来るんやね
Avatar
この関数おもしろいな
この関数泥臭くて大好き。
😄 1
Avatar
右辺はもうVoidでいいと言うかもともと()->()みたいな書き方しなかったですね……
Avatar
TypeCheckウッ
5:52 AM
そういえばObjCとの兼ね合いは、そもそもObjC関数に二重Optionalは実装出来ないからoverrideしようとしたらそこでエラーが出てコンパイルできないので結果としては問題なさそうな雰囲気だった。大統一実装は難しくて手こずってる
5:52 AM
↑二重Optional override問題の話
Avatar
omochimetaru 3/20/2018 5:53 AM
overrideできる型変換は親クラスがObjCだったときでも大丈夫な変換だけに制限されているってこと?
Avatar
@objcな関数や変数をoverrideすると、overrideしたそれも@objcの扱いになっているっぽくて
5:55 AM
@objcではネストしたOptionalは許可されないので、コンパイルエラーになる
Avatar
omochimetaru 3/20/2018 5:55 AM
二重Optionalのオーバライド禁則は純粋なSwiftクラスでも駄目なのはobjcに引っ張られてる?
Avatar
いやそこは普通のSubtypingとoverrideの実装が別れてて、片方は未実装だっただけなんだと思う
5:56 AM
実装追加した例のPRでは全部のテストケースがパスしていて
Avatar
omochimetaru 3/20/2018 9:29 AM
I would like to propose the elimination of the Review phase of the evolution proposals. Instead I propose the Core team to discuss privately and announce the decision for each proposal. Motivation The Review phase gives the false impression of a...
9:29 AM
「レビューフェーズやめてコアチームで話し合って結論出して」スレ
Avatar
言いたいこと分からなくもないけどとりあえずラトナーの返事にハートつけといた
Avatar
omochimetaru 3/20/2018 9:36 AM
わかる
Avatar
Kishikawa Katsumi 3/20/2018 10:27 AM
まあうまくバランスをとって運営しないといけないので難しいんだけど今のところ私は必要なコストだと思います。もっとSwiftが広く多くの人にいろいろな場面で使われるようになったらまた違う意見を持つかも。
Avatar
いろいろなフェーズがあって、例えばABI安定化する前と後とかそういう重要なタイミングで適切なレビューフローも変わってくると思う
Avatar
そもそもVoidって空タプルのtypealiasじゃなかったですっけ 今違う?
Avatar
そのはずですよ。
Avatar
そうだったのか、しらなかった
4:23 AM
だから()は型にも値にもなる、なるほど。
Avatar
あー、いや正確には ()型 の typealias であって、()値 と ()型 は違います。
Avatar
let hoge: () って書けましたっけ?
Avatar
yes
Avatar
かけるのか
Avatar
tupleの値の表記が(1, 2)で、型の表記が(Int, Int)なのだが、これが空になるとどちらも()になるので混乱する
Avatar
let void: Void = ()って書いておいて、型ならVoid、値ならvoidを使うようにすれば楽になりそうだと一日考えて思った。
Avatar
let void = () func xxx() -> Void { return void } こういうことです? グローバルにあるのも違和感なので extension Void { static var void: Void = () } func xxx() -> Void { return .void } こんなかんじですかね(extensionかけないけど)
Avatar
よさそう
4:34 AM
voidはGlobalでも良いかなとは思います
4:35 AM
let void: Void = () func nop<T>(_ arg: T) { } func undefined<T>() -> T { preconditionFailure() } この辺大好き (edited)
Avatar
(型の()を排除する方向に持っていくほうが筋が良い気がする)
Avatar
型排除だけならSwiftLintがデフォで入ってて、Voidにしろ君がいたはず
Avatar
let () : () = ()
😇 5
4:36 AM
パターンもアルヨ
Avatar
Tupleの変数宣言時の分解と型と値の3パターンだ
Avatar
omochimetaru 3/22/2018 4:37 AM
www
Avatar
分解先が0個だから意味は無いけどコンパイルは通る
Avatar
let () : Void = ()
4:38 AM
destructuring assignmentなのかとおもったけどこれでも通る……
Avatar
let (a): Int = (0) これが通るから不自然ではないか。 (edited)
🙄 1
Avatar
めっちゃ面白い事に気がついた protocol Foo { } struct FooStruct: Foo { } protocol FooProtocol: Foo { } protocol Bar { func accept(_ foo: FooStruct) func accept<X>(_ foo: X) where X: FooProtocol } class BarImpl: Bar { func accept<X>(_ foo: X) where X: Foo { } }
8:06 AM
このコンパイルが通る
8:06 AM
protocolで定義されたoverloadをprotocolのimplのタイミングで共通化できる、すごい (edited)
Avatar
なんか色々と問題を引き起こしそうな・・・
8:10 AM
広げて包含してるだけだから問題ないかなぁ・・・。
Avatar
問題は無いですね
8:11 AM
Witnesstableが問題なければ
Avatar
↑これGenericsがマッチするのはOKだけど、Existentialにまで膨らまして解決できるものじゃなかったので
8:19 AM
TC.subtype周りじゃないところで解決されてるっぽいことが想像出来る
8:25 AM
Subclassもダメなので、Generics周りかな
8:27 AM
仕様じゃなくて偶然の産物、つまり半分バグの可能性もあるな
Avatar
ジェネリクス関係なくできた。色々いじってる間にジェネリクスになってた😅 protocol Root {} protocol Foo : Root {} protocol Bar : Root {} protocol A { func accept<F : Foo>(_ foo: F) func accept<B : Bar>(_ bar: B) } extension A { func accept<F : Foo>(_ foo: F) { print("Foo: \(foo)") } func accept<B : Bar>(_ bar: B) { print("Bar: \(bar)") } } class B : A { func accept<R : Root>(_ root: R) { print("Root: \(root)") } } struct FooImpl : Foo {} struct BarImpl : Bar {} B().accept(FooImpl()) B().accept(BarImpl()) (edited)
8:34 AM
↓これはエラー protocol Root {} protocol Foo : Root {} protocol Bar : Root {} class A { func accept<F : Foo>(_ foo: F) { print("Foo: \(foo)") } func accept<B : Bar>(_ bar: B) { print("Bar: \(bar)") } } class B : A { override func accept<R : Root>(_ root: R) { print("Root: \(root)") } } struct FooImpl : Foo {} struct BarImpl : Bar {} B().accept(FooImpl()) B().accept(BarImpl())
8:36 AM
お、ジェネリクスじゃなくてもできた。 protocol Root {} protocol Foo : Root {} protocol Bar : Root {} protocol A { func accept(_ foo: Foo) func accept(_ bar: Bar) } extension A { func accept(_ foo: Foo) { print("Foo: \(foo)") } func accept(_ bar: Bar) { print("Bar: \(bar)") } } class B : A { func accept(_ root: Root) { print("Root: \(root)") } } struct FooImpl : Foo {} struct BarImpl : Bar {} B().accept(FooImpl()) // Root: FooImpl() B().accept(BarImpl()) // Root: BarImpl() (edited)
8:37 AM
あれ?
8:38 AM
ダメだった。 let a: A = B() a.accept(FooImpl()) // Foo: FooImpl() a.accept(BarImpl()) // Bar: BarImpl()
8:40 AM
あー、デフォルト実装付けてわかりづらくなってただけだった・・・
8:40 AM
accept がジェネリックだったらちゃんとオーバーライドできてた。
8:41 AM
Existentialにまで膨らまして解決できるものじゃなかったので
の通りだった。
Avatar
そもそもこういうオーバーライドができるんですね。。 しかも広げるほうも狭めるほうもできてしまうぞ。。 protocol Root {} protocol Foo : Root {} // 1 class A { func accept<R : Root>(_ root: R) { } } class B : A { override func accept<R : Foo>(_ root: R) { } } // 2 class A2 { func accept<R : Foo>(_ root: R) { } } class B2: A2 { override func accept<R : Root>(_ root: R) { } }
Avatar
え、狭める方どうなってるんでしょう??
Avatar
なんか...普通に壊れている気がしますね 😅
Avatar
やば、バグでは protocol Root {} protocol Foo : Root {} // 1 class A { func accept<R : Root>(_ root: R) { } } class B : A { override func accept<R : Foo>(_ root: R) { } } // 2 class A2 { func accept<R : Foo>(_ root: R) { } } class B2: A2 { override func accept<R : Root>(_ root: R) { } } struct RootImpl : Root {} struct FooImpl : Foo {} let b: B = B() // b.accept(RootImpl()) // コンパイルエラー let a: A = b a.accept(RootImpl()) // OK (edited)
8:48 AM
↓ヤバすぎww protocol Root {} protocol Foo : Root { func foo() } // 1 class A { func accept<R : Root>(_ root: R) { } } class B : A { override func accept<R : Foo>(_ root: R) { root.foo() } } // 2 class A2 { func accept<R : Foo>(_ root: R) { } } class B2: A2 { override func accept<R : Root>(_ root: R) { } } struct RootImpl : Root {} struct FooImpl : Foo { func foo() { print("foo") } } let b: B = B() // b.accept(RootImpl()) // コンパイルエラー let a: A = b a.accept(RootImpl()) // 実行時エラー
8:50 AM
master からビルドした最新の swift でもダメだった。。。 (edited)
Avatar
omochimetaru 3/22/2018 9:24 AM
protocol AnimalProtocol { func speak() -> String } protocol CatProtocol : AnimalProtocol { func nya() -> String } class AnimalEater { func accept<X : AnimalProtocol>(_ x: X) {} } class CatEater : AnimalEater { override func accept<X : CatProtocol>(_ x: X) { print(x.nya()) } } class Dog : AnimalProtocol { func speak() -> String { return "bow wow" } } let catEater = CatEater() let animalEater = catEater as AnimalEater let dog = Dog() animalEater.accept(dog) // file:///Users/omochi/work/playground/iOSGround.playground: error: Playground execution aborted: error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x0). // The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation. (edited)
9:25 AM
あらあら
Avatar
戻ってきたらめっちゃおもろいことになってた
Avatar
omochimetaru 3/22/2018 9:25 AM
随分前に @norio_nomura が、override判定のところでwhere句の考慮がおかしいの見つけてたけど、それがまだ壊れてるっぽい
🤔 1
Avatar
norio_nomura 3/22/2018 9:40 AM
今日調べてたStringProtocol.hasPrefix(_:)が似た状況かも。 https://github.com/apple/swift/commit/f9b3e14137ac2f50e93aa2c1db28511e05f88e75
…14390)
  • Use Swift-native Character iteration for hasPrefix/Suffix
  • Remove old tests for removed C shims
9:41 AM
requirementが public protocol StringProtocol … { … func hasPrefix(_ prefix: String) -> Bool で、実装が extension StringProtocol { … public func hasPrefix<Prefix: StringProtocol>(_ prefix: Prefix) -> Bool { になってる。 (edited)
Avatar
おお
9:42 AM
あそっか
9:42 AM
funcのoverrideが通常のサブタイピングと同一でないの
Avatar
norio_nomura 3/22/2018 9:42 AM
Stringはジェネリックになってない。 extension String { … public func hasPrefix(_ prefix: String) -> Bool {
Avatar
ここかもしれない、そしてGenericsのサブタイピングに関しての制御を見た記憶がないぞ…
Avatar
omochimetaru 3/22/2018 9:43 AM
オーバーライドのGeneric制約、バーリトゥード説
Avatar
てかそれをするためにはGenericsに関してinとoutがないとだめですよね
9:44 AM
いやでもoveloadを丸めるのは正しく動いてる?これは
Avatar
omochimetaru 3/22/2018 9:45 AM
こっち向きは正しいよ String is StringProtocol だから、継承先で広く受けるのはOK
Avatar
正しくて、ちゃんと動いてる
9:45 AM
僕がTCで読んだのはちょうどclassのoverrideのところで
9:46 AM
protocolのimplとclassのoverrideは別、前者は正しいっぽいが後者は…
Avatar
omochimetaru 3/22/2018 9:48 AM
protocol ValuePrinter { func print(_ x: Int) func print(_ x: String) } protocol IntOrString { func asInt() -> Int? func asString() -> String? } extension Int : IntOrString { func asInt() -> Int? { return self } func asString() -> String? { return nil } } extension String : IntOrString { func asInt() -> Int? { return nil } func asString() -> String? { return self } } class OmniValuePrinter : ValuePrinter { // oneshot double override! func print<X: IntOrString>(_ x: X) { if let i = x.asInt() { Swift.print(i) } if let s = x.asString() { Swift.print(s) } } } let printer = OmniValuePrinter() as ValuePrinter printer.print(3) printer.print("a")
9:49 AM
おもしろいねえ・・・ TypeScript式オーバーロードを後付できる・・・ (edited)
Avatar
norio_nomura 3/22/2018 9:54 AM
ジェネリックで範囲を広げてプロトコル準拠とか出来たのね。
9:57 AM
その辺りの挙動、apple/swift内にテスト入ってないかな?
Avatar
protocolの方はわかんないですけど、classの方は入ってないっすね
Avatar
swift - The Swift Programming Language
10:03 AM
このあたりも近そう
Avatar
swift - The Swift Programming Language
Avatar
decl/** に構文単位でいっぱいあるのか。
Avatar
そうそう
10:05 AM
decl/class/override.swiftにGenerics周りは、ない
Avatar
おお、ありがとうございます。
Avatar
なるほど!
Avatar
おおー
Avatar
生成されたバイナリを見ると、ちゃんとprotocolに必要なメソッドが生成されてるぽい。 $ nm /Users/norio/Library/Developer/Xcode/DerivedData/ObjectEncoder-cvflgtjlegddrlbosxxjagoaqewr/Build/Products/Debug/ObjectEncoder.framework/ObjectEncoder|xcrun swift-demangle … 00000000000305e0 t _protocol witness for Swift.SingleValueDecodingContainer.decode(Swift.String.Type) throws -> Swift.String in conformance ObjectEncoder.ObjectDecoder.Decoder : Swift.SingleValueDecodingContainer in ObjectEncoder 000000000002f000 t _protocol witness for Swift.SingleValueDecodingContainer.decode(Swift.Bool.Type) throws -> Swift.Bool in conformance ObjectEncoder.ObjectDecoder.Decoder : Swift.SingleValueDecodingContainer in ObjectEncoder 0000000000030430 t _protocol witness for Swift.SingleValueDecodingContainer.decode(Swift.Double.Type) throws -> Swift.Double in conformance ObjectEncoder.ObjectDecoder.Decoder : Swift.SingleValueDecodingContainer in ObjectEncoder 0000000000030280 t _protocol witness for Swift.SingleValueDecodingContainer.decode(Swift.Float.Type) throws -> Swift.Float in conformance ObjectEncoder.ObjectDecoder.Decoder : Swift.SingleValueDecodingContainer in ObjectEncoder …
Avatar
Kishikawa Katsumi 3/27/2018 5:15 AM
A.swift class A: AProtocol { init() {} } fileprivate protocol AProtocol { var value: String { get } } extension AProtocol { var value: String { get { return "" } } }
5:15 AM
B.swft struct B { fileprivate static var a = A() static var v: String { get { return a.value } } }
5:17 AM
^ というのを適当なiOSプロジェクトに書いたとき、リンクエラー(AProtocolがB.swftからは見えないので、a.valueが見つからない)になるんですけど、コンパイルエラーになるべきだと思うのですが、どうでしょうか?
5:18 AM
Xcode 9.2と、2/16時点の4.1およびdev snapshotで確認しました。 (edited)
Avatar
エラーになるべきだと思います。
Avatar
Kishikawa Katsumi 3/27/2018 5:25 AM
@rintaro コンパイルエラーですか?
Avatar
はい、 error: 'value' is inaccessible due to 'fileprivate' protection level が正解かと。
Avatar
Kishikawa Katsumi 3/27/2018 5:28 AM
ありがとうございます。バグレポート送ります。
❤ 1
5:30 AM
簡単なプロジェクトだとメインターゲットのビルドでリンクエラーなんですけど、別のプロジェクトだとテストターゲットをビルドしたときだけリンクエラーになったりするんですよね。それはよくわかりませんでした。
Avatar
テストターゲットだけリンクエラーになる場合、メインターゲットはそのプロパティ/メソッドが普通に呼べてしまうということですか?
5:32 AM
もしメインターゲットでそのメソッドを不正使用していないのであれば、リンクしようとしないので素通りするのは理解できます。 (edited)
Avatar
Kishikawa Katsumi 3/27/2018 5:34 AM
発生したのはレビューがメインのプロジェクトなので実際に呼んでるかどうかは改めて確認しますね。
5:36 AM
おかしいと思ったのはUnit TestではAProtocol、A、Bとも直接的にも間接的にも使用してないので、これはそもそももっと以前にエラーになるはず?と思ったのです。
Avatar
Avatar
これまさにこの問題だと思うんですけど、Xcode 9 で直っているって書いてる。
Avatar
Kishikawa Katsumi 3/27/2018 5:38 AM
試します。
5:40 AM
Xcode 9.2で再現しますね。
Avatar
1年前か。
5:41 AM
tarunonに聞いたらデバッグビルドのときtestable importのために本来見えないものが見えるようになってるのではみたいなことを言ってたのこの話だったっけ。
Avatar
5:42 AM
そんなこと言ったっけ。。。。
Avatar
wmo だとリンク前にインライン化されてリンクエラーにならないっていう落ちっぽい。
Avatar
それは別の話だったかなー。debugだと通ってreleaseだと通らないみたいなバグっぽいのも前に引いたことある。
5:43 AM
それこそ去年のtryswiftで話したとかだったから記憶あやふやだー
Avatar
エラー $ swiftc A.swift B.swift -emit-library -module-name MyMod 通る $ swiftc A.swift B.swift -emit-library -module-name MyMod -wmo (edited)
Avatar
Kishikawa Katsumi 3/27/2018 5:44 AM
リリースビルドだとどっちもビルドできますね。
5:44 AM
なるほど。
Avatar
wmoってなんですか?
Avatar
whole module optimization
Avatar
whole module optimizieか
5:45 AM
おお
Avatar
Kishikawa Katsumi 3/27/2018 5:51 AM
テストターゲットを含めたビルド(⌘+Shift+U)だけで起こるプロジェクトもその時はDebugビルドだから、か。
Avatar
その可能性が高そうですね。
Avatar
ちょっと思い出した。
debugだと通ってreleaseだと通らないみたいなバグっぽいのも前に引いたことある。
これ逆で、何故かreleaseビルドだと通るんだけどdebugビルドだと通らないのなんでやと思ったんだった。で実はreleaseで通るほうが間違ってたっぽいというやつ
5:52 AM
同じ話ですね
Avatar
omochimetaru 3/29/2018 2:40 AM
こんなの書いた public func neverHappen(file: StaticString = #file, line: UInt = #line) -> Never { fatalError("never happen", file: file, line: line) } public func neverHappen<T0>(_ arg0: T0, file: StaticString = #file, line: UInt = #line) -> Never { fatalError("never happen: arg0=\(arg0)") } 例えばこうやって使う Observable.just(()).asDriver(onErrorRecover: { neverHappen($0) }) (edited)
2:40 AM
本当はこう書きたい・・・ asDriver(onErrorRecover: neverHappen) (edited)
Avatar
できるぞい
2:40 AM
高階関数にしてみれ
Avatar
omochimetaru 3/29/2018 2:41 AM
asDriver(onErrorRecover: neverHappen()) こういう事?
Avatar
あーデフォルト引数ほしいのか (edited)
2:41 AM
欲張りや
Avatar
omochimetaru 3/29/2018 2:42 AM
そうそう。 もともとは asDriver(onErrorRecover: { _ in neverHappen() }) ってかいてたけど
2:42 AM
バグが見つかった時に _ in で捨てているのはもったいないから
2:42 AM
引数を食う版をオーバーロードしておくというアイデア
Avatar
でもasD(onER: nH())の方が良くないかな
2:43 AM
クロージャ毎回作るの考えると
Avatar
omochimetaru 3/29/2018 2:43 AM
() ついてるの何ってなるでしょ
Avatar
慣れるやろ
2:43 AM
高階関数は使えて当たり前な世界になる
Avatar
omochimetaru 3/29/2018 2:44 AM
default引数を埋めて引数が減った状態の関数型としてサブタイピングがあればいいと思う
2:45 AM
func a(x: Int, y: Int = 3) is (Int) -> Void
Avatar
今はそれないよねぇ
Avatar
omochimetaru 3/29/2018 2:45 AM
でも、関数呼び出し規則については、これが成り立っているでしょ?
Avatar
protococの実装も、デフォルト引数でoverloadを横着とかできないから
Avatar
omochimetaru 3/29/2018 2:46 AM
てことは、推論機構としてはもうあって、関数型の式としてそのまま使う場合にも、この変換を拡張する感じで・・・
Avatar
型システムに存在してないんじゃないかな
Avatar
デフォルト引数は呼び出しサイトで生成しなきゃならないもの(#fileとか)があるので、結局コンパイラがクロージャ的なコードを生成する必要がある。 (edited)
Avatar
omochimetaru 3/29/2018 2:49 AM
それは、生成してくれて良いと思います。 xOrNone.map(cat.speak) とかやるときも、 cat を束縛するクロージャができてますよね?
Avatar
コンテキスト(ライブラリ)分けてデフォルト引数をstatic propertyとprotocol extensionでガチャガチャやると、ライブラリ側に記述されたデフォルト引数はライブラリ側の型で引っ張られるのは前に実験した
Avatar
omochimetaru 3/29/2018 2:51 AM
デフォルト引数を生成する小さな関数が作られていて、 コールサイトではそれを呼び出す みたいな形じゃなかったっけ
2:51 AM
昔はコーリーサイトにあって、SEで整理されてたような気が
Avatar
生成してくれて良いと思います。
その通りですね。
Avatar
今って動きが変わったのかな、やったのは1年くらい前かも
Avatar
The current ABI for default arguments generate explicit functions for each default argument in a function. As a simple example, when you call something like this: // In the defining module. func foo(a: Int, b: Int = 42, c: Float = 3.14) { .....
👀 1
Avatar
omochimetaru 3/29/2018 2:54 AM
18dayのラトナスレだ
2:55 AM
// In the defining module. func foo_impl(a: Int, b: Int, c: Float) {...} func foo_b() -> Int { return 42 } func foo_c() -> Float { return 3.14 } // On the caller side. let bval = foo_b() let cval = foo_c() foo_impl(a: 192, b: bval, c: cval) ↑そうそうコレ
Avatar
それが現状を説明している pseudo code ですね。
Avatar
omochimetaru 3/29/2018 2:56 AM
// In the defining module. func foo_impl(a: Int, b bval: Int?, c val: Float?) { let b = bval ?? 42 let c = cval ?? 3.14 ... } // On the caller side. foo_impl(a: 192, b: nil, c: nil)
2:56 AM
こっちのほうがええんちゃう、と・・・
2:57 AM
あとで会話も追ってみよう。
3:02 AM
てかこういう話題ってevolのpitchだと思ったけど、ABI変更はevol通す必要がないからdevelopmentなのかな?
3:02 AM
developmentカテゴリは興味ない話題も多くて興味ある話題を見逃しがちだ
Avatar
omochimetaru 4/1/2018 2:49 AM
読んできた ラトナvs スラバ、ジョーグロフという感じ
2:54 AM
どちらの意見もたしかにと思えてめちゃ悩む
3:01 AM
現状:デフォルトパラメータが複雑な式だと呼び出し側が肥大化ないしリザイレント化 対してラトナ式:コードサイズ肥大が無くなる、シンボルが減ってリンクタイム減る 反論とか:だいたいは素朴な式で問題にならない、引数のデフォルト化がABI互換性破壊になる
Avatar
↓で "Implemented (Swift 4.2)" とあるんですが、 4.1 で実装されてますよね?? https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
一部の機能がフライングで入っているので、とか?
8:51 AM
Existentialとか一段飛ばしで実装とか出来ないから、未完成では有るように思います
Avatar
たしかに Hashable の conformance とかまだ入ってないですね。 (edited)
Avatar
ランタイムチェックが実装されたのが4.2なので、それをもってimplementedとしたと考えています
9:33 AM
When evaluating whether a given type conforms to a protocol, evaluate the conditional requirements and pass the results to the witness table accessor function. This provides the ability to query co...
Avatar
なるほど!ありがとうございます🙏
Avatar
それとHashableのやつは https://github.com/apple/swift-evolution/pull/808 で後付でSE-0143に含まれたのでもちろん4.1のタイミングではまだで(当初のスコープ外)、でも https://github.com/apple/swift/pull/15382 がマージされたので4.2に間に合ったと思います(masterからswift-4.2-branchへのリブランチはまだある)。 (edited)
Following discussions on this forum thread, amend SE-0143 to explicitly include the adoption of conditional conformances for Hashable by the following types: Optional Array ArraySlice ContiguousAr...
As a followup to SE-0143, this adds conditional conformance to Hashable to the following types in the standard library: Optional Array, ContiguousArray, ArraySlice Dictionary Range, ClosedRange T...
Avatar
これまで要素が DoubleVector3 とか Vector4 を作ってたけど、仕事で Float にも対応したものがほしくなって、 ARKit の vector_float3 互換にもしたかったので、 gyb で色々生成してみた。(ついでにライブラリ名を SwiftyVector にリネーム) https://github.com/koher/SwiftyVector/blob/0.3.0/Sources/SwiftyVector/Concrete.swift.gyb (edited)
SwiftyVector - Vector types for Swift
9:19 AM
SwiftyVector - Vector types for Swift
9:20 AM
コードジェネレーションもしてるけど、できる限りプロトコルで実装の共通化もしてて、なかなかうまくできたと思う。 https://github.com/koher/SwiftyVector/blob/0.3.0/Sources/SwiftyVector/Vector.swift
SwiftyVector - Vector types for Swift
Avatar
protocol Foo { associatedtype Bar } protocol FooA: Foo where Bar == String { } struct FooAImpl: FooA { // typealias Bar == String // Not require } protocol FooB: Foo where Bar == [Piyo] { associatedtype Piyo } struct FooBImpl<P>: FooB { typealias Piyo = P typealias Bar = [Piyo] // Require } これ結構気になってる
3:14 AM
@swift-4.1.3 @swiftbot --version=latest protocol Foo { associatedtype Bar } protocol FooA: Foo where Bar == String { } struct FooAImpl: FooA { // typealias Bar == String // Not require } protocol FooB: Foo where Bar == [Piyo] { associatedtype Piyo } struct FooBImpl<P>: FooB { typealias Piyo = P // typealias Bar = [Piyo] // Require }
Avatar
error output: <unknown>:0: error: unknown argument: '--version=latest'
Avatar
swiftbot BOT 4/17/2018 3:14 AM
Swift version 4.2-dev (LLVM d14a2b25f2, Clang c38020c511, Swift 22530b922f)
3:14 AM
/usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'Foo' struct FooBImpl<P>: FooB { ^ /usercode/main.swift:2:20: note: protocol requires nested type 'Bar'; do you want to add it? associatedtype Bar ^ /usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'FooB' struct FooBImpl<P>: FooB { ^
Avatar
ダメか
3:14 AM
そして4.1側がこけちゃったw
Avatar
Kishikawa Katsumi 4/17/2018 3:15 AM
@swiftbot --version= latest,4.1 protocol Foo { associatedtype Bar } protocol FooA: Foo where Bar == String { } struct FooAImpl: FooA { // typealias Bar == String // Not require } protocol FooB: Foo where Bar == [Piyo] { associatedtype Piyo } struct FooBImpl<P>: FooB { typealias Piyo = P // typealias Bar = [Piyo] // Require }
Avatar
swiftbot BOT 4/17/2018 3:15 AM
Swift version 4.1 (swift-4.1-RELEASE)
3:15 AM
/usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'Foo' struct FooBImpl<P>: FooB { ^ /usercode/main.swift:2:20: note: protocol requires nested type 'Bar'; do you want to add it? associatedtype Bar ^ /usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'FooB' struct FooBImpl<P>: FooB { ^
Avatar
Kishikawa Katsumi 4/17/2018 3:15 AM
@swiftbot --version=latest,4.1 protocol Foo { associatedtype Bar } protocol FooA: Foo where Bar == String { } struct FooAImpl: FooA { // typealias Bar == String // Not require } protocol FooB: Foo where Bar == [Piyo] { associatedtype Piyo } struct FooBImpl<P>: FooB { typealias Piyo = P // typealias Bar = [Piyo] // Require }
Avatar
swiftbot BOT 4/17/2018 3:15 AM
Swift version 4.2-dev (LLVM d14a2b25f2, Clang c38020c511, Swift 22530b922f)
👏 1
3:15 AM
/usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'Foo' struct FooBImpl<P>: FooB { ^ /usercode/main.swift:2:20: note: protocol requires nested type 'Bar'; do you want to add it? associatedtype Bar ^ /usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'FooB' struct FooBImpl<P>: FooB { ^
3:15 AM
Swift version 4.1 (swift-4.1-RELEASE)
3:15 AM
/usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'Foo' struct FooBImpl<P>: FooB { ^ /usercode/main.swift:2:20: note: protocol requires nested type 'Bar'; do you want to add it? associatedtype Bar ^ /usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'FooB' struct FooBImpl<P>: FooB { ^
Avatar
omochimetaru 4/17/2018 3:16 AM
structのパラメータPの制約が間接的にFooBのwhereとして書かれてるの?
Avatar
つまりFooBはBarが[Piyo]であってほしくて、Piyoはなんでもいい、みたいな
3:16 AM
兎に角Arrayであれば良いみたいなケース
Avatar
omochimetaru 4/17/2018 3:24 AM
一見FooAとFooBでルールが違うようにみえるけど、typealias経由の解決はしないってことかね
Avatar
typealiasの省略の可否が違うのが気になり
Avatar
omochimetaru 4/17/2018 3:24 AM
typealias Bar = [Piyo] が省略できないのは、 typealias Piyo = P が無いと推論できない事だから?
3:25 AM
一方、typealias Bar == String が省略できるのは、 : FooA だけで推論できることだから?
Avatar
Piyo=Pは明示する必要がある、それはわかる。Barが省略できないのは 🤔
Avatar
omochimetaru 4/17/2018 3:26 AM
論理的には解決可能だよね 単に実装上そうなっちゃってそう
Avatar
でもCollection実装するときとかはSubSequenceとか諸々省略可能だよね、どうなってんだろ
Avatar
omochimetaru 4/17/2018 3:28 AM
フーム・・・
1:00 AM
Swift for TF、普通のDoubleで書かれた関数が、gradient(of: f) で自動微分できてるし python interopがもう動いてた
Avatar
Doubleの演算子等が全部自動微分対応のものに差し替わっている?
Avatar
omochimetaru 4/24/2018 1:02 AM
if文付きの再帰関数も微分できてるし
Avatar
というかtfのVariable相当に変わってるのかな
Avatar
omochimetaru 4/24/2018 1:03 AM
コンパイラが謎拡張されてる
1:03 AM
どうやってるのかとかホワイトペーパーは来月ぐらいに出すって動画中で言ってた
Avatar
再帰関数微分とかはdefine by runだとふつうの再帰関数で書いたのでも大丈夫ですね
1:04 AM
動画見てないですけど最初の方でeager modeが云々みたいなのがあったのでそれっぽい
Avatar
omochimetaru 4/24/2018 1:04 AM
最初の方で言ってるのは
1:04 AM
コンピューティングには2つのやり方があるけど
1:05 AM
コンパイラサポートがあればひとまとめに書けるよね、でもパイソンでは無理だね、みたいなこと話してる
Avatar
じゃあdefine and runもできるんですかね
Avatar
omochimetaru 4/24/2018 1:08 AM
というか、普通の関数が微分できてる時点でそういうことにならない?
1:09 AM
関数の返り値として式ツリーのオブジェクトが返されてるならユーザー実装可能だけど
1:09 AM
シグネチャがそうではないので
1:10 AM
eagerに書いた式がコンパイル時においては式グラフ扱いだからどちらでもあるような。
Avatar
if分岐があるのはdefine by runじゃないとできないかと思います。 入力によって計算グラフが変わるので
Avatar
omochimetaru 4/24/2018 1:12 AM
ifごと微分してるんじゃないの?
1:13 AM
つまり微分された関数にも分岐が残っている
1:13 AM
そうじゃないと区間で定義された関数の微分にならないし。
Avatar
define and runだと使われない分岐経路も計算グラフになる define by runだと使われない経路は除外されるって感じですかね
Avatar
omochimetaru 4/24/2018 1:17 AM
動画の12:31
Avatar
dRecurseに3を与えた時点で計算グラフが構築されているとしか考えられない(define by run脳)
Avatar
omochimetaru 4/24/2018 1:28 AM
まあたしかにこの例だとそう解釈することもできるけど・・・
1:28 AM
そもそもTensorFlowっていうのは
1:28 AM
ユーザ定義型を使って、演算子をオーバーロードすることで、一見通常の計算式を、計算グラフとしてオブジェクト化して
1:28 AM
微分っていう高階操作を行うわけだけど
1:29 AM
あれってその前段の定義ステージと、
1:29 AM
値を流し込む計算ステージの
1:29 AM
2つがあるでしょ
1:29 AM
Pythonだからそれが両方ランタイムで行われているけど
1:29 AM
そもそもコンパイル言語でコードをコンパイルする時はASTを構築しているのだから
1:30 AM
コンパイル時とランタイムに、 ちょうどその定義ステージと計算ステージを割り当てられる
1:30 AM
ってことだと思う
😀 1
Avatar
コンパイル時に計算グラフはできてるってことですかね? define and runのフレームワークで再帰関数書いたこと無いのでどうなるのか想像がつかない……
Avatar
omochimetaru 4/24/2018 1:31 AM
そう
1:32 AM
再帰呼び出しがどう合成されてるかによるけど
1:34 AM
あーどうなんだろ?
Avatar
python interopがもう動いてた
まだ 5:08 までしか見れてないけど、これ Python 関係あるの?直接 Swift から TensorFlow 使う話じゃないの?
3:14 AM
最初字幕なしで見てたら全然聞き取れなかったけど英語字幕あって助かった。
Avatar
omochimetaru 4/24/2018 3:14 AM
8:54あたりで
3:14 AM
pickleとか使ってますよ。
3:15 AM
SwiftEvolにラトナが提案してる最終型みたいなものがもう動いてる。 (edited)
Avatar
Python 3 と連携できるのかが気になる。
3:18 AM
Python.framework 使ってたら Python 2 しか使えないよね?
Avatar
omochimetaru 4/24/2018 3:19 AM
直接 Swift から TensorFlow 使う話じゃないの?
import TensorFlow して Tensor<T> とかやってるので、その話もある。
3:20 AM
Python2/3についてはわからない。聴き逃した可能性はあるけど。
3:21 AM
Python.frameworkを使ってたらpython2しか使えないのかはそれもまたわからない。 Py2/3のC-APIの互換性がよくわからないので。 もしかしたらPythonでContext作る時に3モードで構築〜とかできるのかも。
Avatar
SE-0195 で出てくる Python は Python.framework を使ってんじゃないっけ?それだと 2 系になると思うんよね。 https://github.com/apple/swift-evolution/blob/master/proposals/0195-dynamic-member-lookup.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 4/24/2018 3:24 AM
Python.framworkを使うと2系になるっていう理由はなんですか?
3:24 AM
そこでexportされてるC-APIの詳細仕様をしらないので、そこがよくわからない。
3:24 AM
2-3どっちも使えるC-APIだったら良いなと思って。
Avatar
Python.framework って Mac に標準で入ってるやつで、それが 2 系しかサポートしてないんじゃないかな?詳しくは知らないけど。
3:26 AM
a = someValue[dynamicMember: "someMember"] someValue[dynamicMember: "someMember"] = a mutateParameter(&someValue[dynamicMember: "someMember"]) みたいなのは現状でもやろうと思えばできて、
3:27 AM
SE-0195 は↑を a = someValue.someMember someValue.someMember = a mutateParameter(&someValue.someMember) のように書けるようにするだけだと思う。
3:28 AM
Chris Lattner がお試しで作ってた Playground は Python.framework を使ってたような気がする。実際動かしたわけじゃないので確証はないけど。
Avatar
import Pythonってやってたからそうじゃないですかね
Avatar
そうすると Python 2 系になっちゃって、 Python 3 系が使えないと interop ができるようになっても辛いなぁと。 3 系の Python.framework も作れるのかもしれないですけど。
Avatar
Kishikawa Katsumi 4/24/2018 3:31 AM
macOSに標準で付属しているPythonが2.xというだけなので、3.xのPython.frameworkも公式サイトとかからインストールできますよ。
😀 1
Avatar
omochimetaru 4/24/2018 3:31 AM
インストールを行うといくつかのものが手に入ります
3:31 AM
Python 実行ファイルやライブラリを含む /Library/Frameworks/Python.framework フレームワーク
Avatar
Kishikawa Katsumi 4/24/2018 3:32 AM
ビルドすることも可能なはず。HomeBrewとかサポートしてるので。
Avatar
omochimetaru 4/24/2018 3:32 AM
アップルが出荷してるやつが2.7ビルドというだけで
3:32 AM
Python.framework自体は3のもあるみたい
Avatar
3.xのPython.frameworkも公式サイトとかからインストールできますよ。
おお、そうなんですね。それだと大丈夫ですね。
3:33 AM
Python 3 は pyenv でしか使ってませんでした。
Avatar
omochimetaru 4/24/2018 3:37 AM
クロスのブリッジではなくて、Pythonのビルド一つに一つのフレームワークみたいですね。 includeとかlibみたいなものか。
Avatar
全部 2.7 へのシンボリックリンクになってるけど、仕組み上は一つの framework で色んなバージョンが扱えるわけではない? $ ls Python.framework/Versions/ 2.3 2.5 2.6 2.7 Current (edited)
Avatar
omochimetaru 4/24/2018 3:49 AM
ここまでの情報から考えるとそう思います
3:49 AM
なので3.6のが使いたいなら、それに対応したframeworkがimportされるように、 Swift処理系のframework search pathなどをコントロールする必要がある。
Avatar
Kishikawa Katsumi 4/24/2018 4:00 AM
Frameworkの仕組み上は複数のバージョンを入れることができて、デフォルトは最新バージョンにリンクするようになっていて、必要に応じて同梱されている別のバージョン(通常は古いバージョン)リンクできる、その場合はバージョンまで含めてSearch Pathに追加する、、、という仕組みのはず。lib〜.soが無印はlatestへのリンクで必要に応じてバージョン付きの.soをリンクするのと同じ、、、はず。
4:02 AM
それはそれとして、Python2と3のような明らかに非互換の変更があるものは別のフレームワークにするべき、なんじゃないですかね。
4:02 AM
2.3-2.7が全部2.7扱いなのはよくわからない。
Avatar
omochimetaru 4/24/2018 4:02 AM
でもPython界では2と3の両方で使えるコードを書く技法などが普及してますよ
Avatar
Kishikawa Katsumi 4/24/2018 4:02 AM
たぶん/System/Frameworks以下のPythonは基本的にApple自身が使うことしか考えられてないのかな。 (edited)
Avatar
omochimetaru 4/24/2018 4:02 AM
それを支援するためのライブラリとかもあるし。
4:03 AM
C-APIレベルでみれば、構文的な差はもうちょっと減るので
4:03 AM
悩ましいラインだと思います
Avatar
でもPython界では2と3の両方で使えるコードを書く技法などが普及してますよ
これには頼らない方がよさそうな気が。
4:05 AM
/System/Library/Frameworks/Python.framework は触らずに別 Framework にした方が良さそうに思います。
Avatar
Kishikawa Katsumi 4/24/2018 4:05 AM
おもしろいですね。2と3の違いを吸収するレイヤーが作られてる?んですかね。
Avatar
Python 2 は 2020 年にはサポートが切れますし、共存のためにあれこれ労力をかけるより分けておいた方がトラブルも少なそうに思います。 (edited)
Avatar
omochimetaru 4/24/2018 4:07 AM
概ねの構文や処理系は互換性があって、 一部の 2 の文法は封印、 3の関数は 2側にライブラリとして追加 みたいな感じで・・・ https://hhsprings.bitbucket.io/docs/translations/python/six-doc-ja/
4:08 AM
(まあ個人的には嫌いなんですけど・・・)
Avatar
Kishikawa Katsumi 4/24/2018 4:08 AM
フレームワーク(ダイナミックライブラリ?)のバージョニングの思想でいうと、普通に使ってるうちはマイナーチェンジは自動的にLatestが使われるけど、それで困りそうなのは別にしろってことだと思うので、Python3が別フレームワークになるのは自然だと思います。
Avatar
omochimetaru 4/24/2018 4:08 AM
まあたしかに、そういう意味では間違いなくメジャーアップデートですね。
Avatar
map が Python 2 系では List を返していたのが 3 では iterable なオブジェクトになってるとか、吸収しきれなさそう。
Avatar
Kishikawa Katsumi 4/24/2018 4:09 AM
概ねの構文や処理系は互換性があって、
私もちょこっとPython書いたことあるけど、確かにあまり2と3の違いわかってないんですよね。
Avatar
gyb は Python 2.7 想定だと思うんですけど、普通に Python 3 でも動いてますね。
Avatar
omochimetaru 4/24/2018 4:11 AM
"" で作られるオブジェクトの型が違うのが一番大きいですね
4:11 AM
たしか2だと素直なバイトバッファで、3だとEncoding付きのUnicodeStringだった気が。
4:14 AM
↑ここに2.7から3.0の書き換えアドバイス?みたいにまとまってます
Avatar
今やるなら基本的には Python 3 になると思いますが、 Swift コンパイラのビルドが Python 2 じゃないといけなくてハマりました。 pyenv でグローバルに 3.6 を指定していたので・・・。
Avatar
https://www.python.org/downloads/release/python-365/ ここにある macOS 64-bit installer で Python 3をインストールしたら、Python.frameworkは /Library/Frameworks にインストールされました。/System/Library/Frameworks 以下はそのままのようですね。 $ ls /Library/Frameworks/Python.framework/Versions 3.6 $ ls /System/Library/Frameworks/Python.framework/Versions 2.3 2.5 2.6 2.7 Current
The official home of the Python Programming Language
🙂 1
Avatar
norio_nomura 4/24/2018 4:37 AM
pyenvの場合 $ PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install 3.6.4 python-build: use openssl from homebrew python-build: use readline from homebrew Downloading Python-3.6.4.tar.xz... -> https://www.python.org/ftp/python/3.6.4/Python-3.6.4.tar.xz Installing Python-3.6.4... python-build: use readline from homebrew Installed Python-3.6.4 to /Users/norio/.pyenv/versions/3.6.4 208.44s user 58.92s system 162% cpu 2:44.55 total $ swift `python-config --ldflags` -I `python-config --prefix` Welcome to Apple Swift version 4.1 (swiftlang-902.0.48 clang-902.0.39.1). Type :help for assistance. 1> import Python 2> func execPy(_ code: String) { 3. Py_Initialize() 4. PyRun_SimpleStringFlags(code, nil) 5. Py_Finalize() 6. } 7> execPy("import sys\nprint(sys.version)") 3.6.4 (default, Apr 24 2018, 13:35:20) [GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.1)] 8> (edited)
👏 1
Avatar
おおお・・・、そんなことができるんですね。
Avatar
ArraySlice で任意の範囲のインデックスを持つインスタンスを生成する方法ってありませんか?たとえば↓みたいな感じで。 // こんなことがしたい let slice: ArraySlice<String> = ["a", "b", "c"].offset(100) print(slice[100]) // "a" print(slice[101]) // "b" print(slice[102]) // "c" (edited)
8:03 AM
そもそも ArraySlice をそういう目的で使うのが間違いな気がしてきました。負のインデックスもできないみたいだし。
8:03 AM
startIndex の前に insert することもできない。
Avatar
norio_nomura 4/26/2018 5:40 AM
@swift-4.1.3 @swift-4.2.4 struct A { var strings: AnySequence<String> { return AnySequence { () -> AnyIterator<String> in var buffer = staticStrings ?? [] return AnyIterator { if let first = buffer.popFirst() { return first } return nil } } } } let staticStrings: [String]? = ["1", "2"] (edited)
Avatar
stderr:main.swift:6:32: error: cannot use mutating member on immutable value: 'buffer' is immutable if let first = buffer.popFirst() { ^~~~~~ (edited)
Avatar
norio_nomura 4/26/2018 5:41 AM
このbufferはimmutableなの?
Avatar
omochimetaru 4/26/2018 5:42 AM
コピーされた [String] だから 普通にmutableに見える
Avatar
exit status: 1 with stderr:main.swift:6:39: error: '[String]' requires the types '[String]' and 'ArraySlice<String>' be equivalent to use 'popFirst' if let first = buffer.popFirst() { ^
Avatar
omochimetaru 4/26/2018 5:43 AM
@swift-4.2.4 struct A { var strings: AnySequence<String> { return AnySequence { () -> AnyIterator<String> in var buf: [String] = ["1", "2"] return AnyIterator { if let first = buf.popFirst() { return first } return nil } } } }
Avatar
stderr:main.swift:6:36: error: '[String]' requires the types '[String]' and 'ArraySlice<String>' be equivalent to use 'popFirst' if let first = buf.popFirst() { ^
Avatar
norio_nomura 4/26/2018 5:43 AM
なんかよくわからん。
Avatar
popLastだと動く?
Avatar
omochimetaru 4/26/2018 5:44 AM
popFirstがそもそも出ない
5:44 AM
IDEで
Avatar
それ
5:44 AM
popFirstって導入されたんでしたっけ?前から無かったと思いますけど
5:45 AM
@swift-4.2.4 var buf: [String] = ["1", "2"] buf.popFirst()
Avatar
exit status: 1 with stderr:main.swift:2:5: error: '[String]' requires the types '[String]' and 'ArraySlice<String>' be equivalent to use 'popFirst' buf.popFirst() ^
Avatar
omochimetaru 4/26/2018 5:45 AM
Playground execution failed: error: iOSGround.playground:13:1: error: cannot use mutating member on immutable value: 'buf' is immutable buf.popFirst() ^~~
5:46 AM
botとxcodeでエラーも違う
Avatar
popFirstだけおかしいみたいですかね
5:46 AM
SDK Xcode 7.1+
けっこう古くからあった?補完出ないから気づかなかったということかな
Avatar
omochimetaru 4/26/2018 5:47 AM
extension Collection where SubSequence == Self { /// Removes and returns the first element of the collection. /// /// - Returns: The first element of the collection if the collection is /// not empty; otherwise, `nil`. /// /// - Complexity: O(1) @_inlineable public mutating func popFirst() -> Element? { // TODO: swift-3-indexing-model - review the following guard !isEmpty else { return nil } let element = first! self = self[index(after: startIndex)..<endIndex] return element } }
5:47 AM
'[String]' requires the types '[String]' and 'ArraySlice<String>' be equivalent
5:47 AM
このメッセージはこのwhereから来てるものか。
Avatar
norio_nomura 4/26/2018 5:49 AM
なるほど、これで動く。 @swift-4.2.4 struct A { var strings: AnySequence<String> { return AnySequence { () -> AnyIterator<String> in var buffer = ArraySlice(staticStrings ?? []) return AnyIterator { if let first = buffer.popFirst() { return first } return nil } } } } let staticStrings: [String]? = ["1", "2"] (edited)
Avatar
no output (edited)
Avatar
SubSeqeuece制約が必要なのはO(1)にするためで、普通のArrayだと適合しないから補完でないのが正しいのか
Avatar
norio_nomura 4/26/2018 5:50 AM
エラーメッセージがおかしかったのは4.2で直ってるのね。
Avatar
omochimetaru 4/26/2018 5:50 AM
@swift-4.2.4 var buf = ArraySlice([1,2,3]) print(buf) buf.popFirst() print(buf)
Avatar
[1, 2, 3] [2, 3]stderr:main.swift:3:5: warning: result of call to 'popFirst()' is unused buf.popFirst() ^ ~~
Avatar
omochimetaru 4/26/2018 5:50 AM
ああ、それでpopLastと違うのか。
5:50 AM
ArraySliceはオフセットを持ってるからO(1)と
Avatar
これO(1)じゃないののオーバーロードじゃだめなんですかね
Avatar
omochimetaru 4/26/2018 5:52 AM
Let’s Retire Sequence TL;DR Evaluated against its documented purpose, Sequence is not pulling its weight. It creates pitfalls for library users and complexity for everyone. That said, defining a Sequence is super easy. We should make it th...
5:52 AM
まだ読んでないんだけど↑こんな提案出てた
5:52 AM
@koher が前にSequenceに結構突っ込んでたから関係あるかも
Avatar
4.1 でエラーメッセージがバグってるだけそう。
6:01 AM
@swift-4.1.3 var a = [2, 3, 5] print(a.popFirst()!) (edited)
Avatar
exit status: 1 with stderr:main.swift:2:7: error: cannot use mutating member on immutable value: 'a' is immutable print(a.popFirst()!) ^ (edited)
Avatar
ArraySlice ならちゃんと popFirst があるから使える。 @swift-4.1.3 var a: ArraySlice<Int> = [2, 3, 5] print(a.popFirst()!) (edited)
Avatar
2 (edited)
Avatar
何が起こったんだ??
Avatar
omochimetaru 4/26/2018 6:04 AM
メンションが。
Avatar
できた。
6:05 AM
一体どうなったらメソッドがないときに error: cannot use mutating member on immutable value: 'a' is immutable なるメッセージが出ることになるのかは興味深いけど・・・。
Avatar
omochimetaru 4/26/2018 6:05 AM
メソッドは見つかっていて、whereでこけてるけど
6:06 AM
エラーメッセージを出す時に、whereでこけるまでに、mutatabilityのチェックを先にやって
6:06 AM
そっちを吐いちゃってるとか。
6:06 AM
あ、でもmutabilityは通ってるのか。
Avatar
これに関連して、昨日↑に書いたのにも関連してるけど、 Swift では Queue/Deque 的なものは ArraySlice でやるべきと思ってたんだけど、 (edited)
6:07 AM
Swift の ArraySlice はインデックスを保存するから
Avatar
@swiftbot extension Collection { func indexed() -> [(Index, Element)] { return indices.map { ($0, self[$0]) } } } let a = [ 2, 3, 5, 7, 11, 13] var b = a[2...4] print(Array(b.indexed())) _ = b.popLast() b.append(11) print(Array(b.indexed())) _ = b.popFirst() b.insert(5, at: 3) print(Array(b.indexed()))
🛠 1
Avatar
swiftbot BOT 4/26/2018 6:14 AM
Swift version 4.1 (swift-4.1-RELEASE)
Avatar
Kishikawa Katsumi 4/26/2018 6:14 AM
ちょっと空間効率が悪いのを許容してQueueのデータ構造でもインデックスアクセスができるようにしたらいいと思うんですよね。
Avatar
swiftbot BOT 4/26/2018 6:14 AM
[(2, 5), (3, 7), (4, 11)] [(2, 5), (3, 7), (4, 11)] [(3, 5), (4, 7), (5, 11)]
Avatar
↑の最後で [(2, 5), (3, 7), (4, 11)] を取り戻す方法がない気がしてます。
6:16 AM
インデックスも要素も整数でわかりづらいな・・・。
Avatar
omochimetaru 4/26/2018 6:16 AM
@koher 生のインデックスじゃなくて
6:16 AM
startIndex + offset
Avatar
@swiftbot extension Collection { func indexed() -> [(Index, Element)] { return indices.map { ($0, self[$0]) } } } let a = ["a", "b", "c", "d", "e", "f", "g"] var b = a[2...4] print(Array(b.indexed())) _ = b.popLast() b.append("e") print(Array(b.indexed())) _ = b.popFirst() b.insert("c", at: 3) print(Array(b.indexed())) (edited)
🛠 1
Avatar
swiftbot BOT 4/26/2018 6:16 AM
Swift version 4.1 (swift-4.1-RELEASE) (edited)
Avatar
omochimetaru 4/26/2018 6:17 AM
の形で考えるんじゃないです?
Avatar
swiftbot BOT 4/26/2018 6:17 AM
[(2, "c"), (3, "d"), (4, "e")] [(2, "c"), (3, "d"), (4, "e")] [(3, "c"), (4, "d"), (5, "e")]
Avatar
@omochimetaru その startIndex を変える方法がない気がしてる。
6:18 AM
endIndex は伸びるんだけど。
6:20 AM
というか、 startIndex の前に挿入できないと全部ずらすことになっていて O(N) になってるかも。
6:21 AM
appendFirst とか pushFirst とか insertFirst がない。
Avatar
omochimetaru 4/26/2018 6:21 AM
@swiftbot func indexed<T>(_ slice: ArraySlice<T>) -> [(Int, T)] { return (0..<slice.count).map { (offset: Int) in (offset, slice[slice.startIndex + offset]) } } let a = ["a", "b", "c", "d", "e", "f", "g"] var b = a[2...4] print(indexed(b)) _ = b.popLast() b.append("h") print(indexed(b)) _ = b.popFirst() b.insert("i", at: 3) print(indexed(b))
🛠 1
Avatar
swiftbot BOT 4/26/2018 6:21 AM
Swift version 4.1 (swift-4.1-RELEASE)
6:21 AM
[(0, "c"), (1, "d"), (2, "e")] [(0, "c"), (1, "d"), (2, "h")] [(0, "i"), (1, "d"), (2, "h")]
Avatar
@omochimetaru それは表示を変えただけでは?
Avatar
omochimetaru 4/26/2018 6:22 AM
例えばStringをイテレートする時は
6:22 AM
startIndexから初めて、index(after: index)で
6:22 AM
進めていくように
6:23 AM
元々の整数インデックスは気にしないのが正しいArraySliceの触り方なのかな?と
6:23 AM
startIndex の前に挿入できないと全部ずらすことになっていて O(N) になってるかも
それはそんな気がする。
Avatar
ArraySlicesubscript の仕様を使うとおもしろいことができて、
Avatar
omochimetaru 4/26/2018 6:23 AM
ArraySliceはQueueとは違いそう
Avatar
昨日やってたのは動画のフレームをコマ送りにするときに
6:24 AM
N フレーム分戻れるように画像をキャッシュしてたんだけど
6:25 AM
var cachedFrames = ArraySlice<Image<RGBA<UInt8>>> としてキャッシュしておけば、 (edited)
6:25 AM
cachedFrames[frameIndex] で簡単にアクセスできる。
6:26 AM
if cachedFrames.count > maxNumberOfCachedFrames { cachedFrames.removeFirst() } みたいにして簡単に古いキャッシュを消せるし
6:28 AM
if cachedFrames.indices.contains(frameIndex) { ... } みたいにキャッシュが存在するときの処理も簡単に書ける。
6:29 AM
(↑が O(1) になってるか自信ないけど、 (cachedFrames.startIndex ..< cachedFrames.endIndex).contains(frameIndex) にすれば O(1) ) (edited)
Avatar
omochimetaru 4/26/2018 6:30 AM
あれ、それって、本当に消えてるんですか?
6:31 AM
ArraySliceのremoveFirstは元々のArrayを保持+オフセットをずらすだけで
6:31 AM
消えないとかないっけ
Avatar
いや、変更を加えた時点で Array とは別物になるし
6:31 AM
そもそも最初から ArraySlice として作ってる。
6:33 AM
@swiftbot class A { deinit { print("deinit") } } var x: ArraySlice<A> = [A(), A(), A()] print("A") x.removeFirst() print("B") x.removeFirst() print("C") x.removeFirst() print("D") (edited)
🛠 1
Avatar
swiftbot BOT 4/26/2018 6:33 AM
Swift version 4.1 (swift-4.1-RELEASE) (edited)
6:33 AM
A B C D
Avatar
おや
6:35 AM
@swiftbot class A { deinit { print("deinit") } } var x: ArraySlice<A> = [A(), A(), A()] print("A") x.removeFirst() x[2] = A() print("B") x.removeFirst() x[2] = A() print("C") x.removeFirst() print("D")
🛠 1
Avatar
swiftbot BOT 4/26/2018 6:35 AM
Swift version 4.1 (swift-4.1-RELEASE)
6:35 AM
A deinit B deinit C D
Avatar
ああ、 CoW でコピー発生してなかった
6:38 AM
コピーが発生したら removeFirst されたやつらも解放されると思うんだけど、どうやって試すのがいいかな・・・。
6:42 AM
@swiftbot class A { deinit { print("deinit") } } var x = [A(), A(), A()] print("A") x.removeLast() print("B") x.removeLast() print("C") x.removeLast() print("D")
🛠 1
Avatar
swiftbot BOT 4/26/2018 6:42 AM
Swift version 4.1 (swift-4.1-RELEASE)
6:42 AM
A deinit B deinit C deinit D
Avatar
むー、少なくとも単純に removeFirst じゃ ArraySlice はバッファの中身をクリアしないっぽいな。
Avatar
norio_nomura 4/26/2018 6:47 AM
CoWの時にもremoveFirstされた要素もコピーされてそう。
Avatar
えー、さすがにそのときは startIndex から endIndex の分だけコピーされてんじゃないかと思ってるんですが。
6:50 AM
ダメっぽい? @swiftbot class A { deinit { print("deinit") } } var x: ArraySlice<A> = [A(), A(), A()] do { let y = x print("A") x.removeFirst() x[2] = A() print("B") x.removeFirst() x[2] = A() print("C") x.removeFirst() print("D") } print("E")
🛠 1
Avatar
swiftbot BOT 4/26/2018 6:50 AM
Swift version 4.1 (swift-4.1-RELEASE)
6:50 AM
A B deinit C D deinit deinit E
6:50 AM
/usercode/main.swift:7:9: warning: initialization of immutable value 'y' was never used; consider replacing with assignment to '_' or removing it let y = x ~~~~^ _
Avatar
@swiftbot class A : CustomStringConvertible{ let val: Int init(_ val: Int) { self.val = val } deinit { print("deinit: \(self)") } var description: String { return "A(\(val))" } } var x: ArraySlice<A> = [A(1), A(2), A(3)] do { let y = x print("A") x.removeFirst() x[2] = A(4) print("B") x.removeFirst() x[2] = A(5) print("C") x.removeFirst() print("D") } print("E")
🛠 1
Avatar
swiftbot BOT 4/26/2018 7:02 AM
Swift version 4.1 (swift-4.1-RELEASE)
7:02 AM
A B deinit: A(4) C D deinit: A(1) deinit: A(3) E
7:02 AM
/usercode/main.swift:12:7: warning: initialization of immutable value 'y' was never used; consider replacing with assignment to '_' or removing it let y = x ~~~~^ _
Avatar
なぜ A(1) が deinit されるのか?
Avatar
確かに(元のコードでも)そこで 2 回 deinit されてるの変だ。なんで 1 も解放されてるんだろう・・・。 (edited)
Avatar
norio_nomura 4/26/2018 7:07 AM
その出力を見る限り、removeFirstされた要素はCoWでコピーされてない様ですね。
7:08 AM
x[2] = A(4) でCoW発生か。
Avatar
でも A(2) も解放されないといけない気が。ちょっと紙に書いてみないと頭の中で CoW 含む参照関係が追えなくなってきたので間違ってるかもですが・・・。
Avatar
ですね。もし開放されるなら A(2) もされるべきっぽいし、妙に中途半端。
Avatar
norio_nomura 4/26/2018 7:11 AM
CoW時の境界チェックがバグってるぽい。バグってないと思う。 (edited)
Avatar
@swiftbot class A : CustomStringConvertible { let value: Int init(_ value: Int) { self.value = value } var description: String { return "A(\(value))" } deinit { print("deinit \(self)") } } do { var x: ArraySlice<A> = [] for i in 0..<20 { x.append(A(i)) } while let a = x.popFirst() { print("pop \(a)") } print("-----") }
🛠 1
Avatar
swiftbot BOT 4/26/2018 8:23 AM
Swift version 4.1 (swift-4.1-RELEASE)
8:23 AM
pop A(0) pop A(1) pop A(2) pop A(3) pop A(4) pop A(5) pop A(6) pop A(7) pop A(8) pop A(9) pop A(10) pop A(11) pop A(12) pop A(13) pop A(14) pop A(15) pop A(16) pop A(17) pop A(18) pop A(19) ----- deinit A(0) deinit A(1) deinit A(2) deinit A(3) deinit A(4) deinit A(5) deinit A(6) deinit A(7) deinit A(8) deinit A(9) deinit A(10) deinit A(11) deinit A(12) deinit A(13) deinit A(14) deinit A(15) deinit A(16) deinit A(17) deinit A(18) deinit A(19)
Avatar
@swiftbot class A : CustomStringConvertible { let value: Int init(_ value: Int) { self.value = value } var description: String { return "A(\(value))" } deinit { print("deinit \(self)") } } var i = 0 do { var x: ArraySlice<A> = [] do { for _ in 0..<20 { x.append(A(i)) i += 1 } while let a = x.popFirst() { print("pop \(a)") if !x.isEmpty { x[x.endIndex - 1] = A(i) i += 1 } } } print("-----") }
🛠 1
Avatar
swiftbot BOT 4/26/2018 8:23 AM
Swift version 4.1 (swift-4.1-RELEASE)
8:23 AM
pop A(0) deinit A(19) pop A(1) deinit A(20) pop A(2) deinit A(21) pop A(3) deinit A(22) pop A(4) deinit A(23) pop A(5) deinit A(24) pop A(6) deinit A(25) pop A(7) deinit A(26) pop A(8) deinit A(27) pop A(9) deinit A(28) pop A(10) deinit A(29) pop A(11) deinit A(30) pop A(12) deinit A(31) pop A(13) deinit A(32) pop A(14) deinit A(33) pop A(15) deinit A(34) pop A(16) deinit A(35) pop A(17) deinit A(36) pop A(18) deinit A(37) pop A(38) ----- deinit A(0) deinit A(1) deinit A(2) deinit A(3) deinit A(4) deinit A(5) deinit A(6) deinit A(7) deinit A(8) deinit A(9) deinit A(10) deinit A(11) deinit A(12) deinit A(13) deinit A(14) deinit A(15) deinit A(16) deinit A(17) deinit A(18) deinit A(38)
Avatar
これはちゃんと動いてそう。
8:25 AM
while let ちゃんと使ったの初めてかも。
Avatar
norio_nomura 4/26/2018 8:28 AM
でも A(2) も解放されないといけない気が。
これってCoW時点ではA(2)もコピーされてるから、解放されなくて正解な気が。 @swift-4.1.3 class A : CustomStringConvertible{ let val: Int init(_ val: Int) { self.val = val } deinit { print("deinit: \(self)") } var description: String { return "A(\(val))" } } var x: ArraySlice<A> = [A(1), A(2), A(3)] do { let y = x // yは[A(1), A(2), A(3)]を保持 print("A") x.removeFirst() // xは[A(1), A(2), A(3)]を保持して[A(2), A(3)]を露出 x[2] = A(4) // CoW発生、xは[A(2), A(4)]を保持 print("B") x.removeFirst() // xは[A(2), A(4)]を保持して[A(4)]を露出 x[2] = A(5) // xは[A(2), A(5)]を保持して[A(5)]を露出、A(4)解放 print("C") x.removeFirst() // xは[A(2), A(5)]を保持して[]を露出 print("D") } // y解放、xに保持されていないA(1),A(3)解放 print("E")
(edited)
Avatar
A B deinit: A(4) C D deinit: A(1) deinit: A(3) Estderr:main.swift:12:7: warning: initialization of immutable value 'y' was never used; consider replacing with assignment to '_' or removing it let y = x ~~~~^ _
Avatar
A B deinit: A(4) C D deinit: A(1) deinit: A(3) Estderr:main.swift:12:9: warning: initialization of immutable value 'y' was never used; consider replacing with assignment to '_' or removing it let y = x // yは[A(1), A(2), A(3)]を保持
Avatar
なるほどー
Avatar
今更ですが確認しました。 x[2] = A(5) でコピーが発生してなかったんですね😅
Avatar
Dictionary にある Key のエントリーが含まれるかどうかを調べる一番いい方法って dictionary.keys.contains(key) でいいんでしたっけ? O(1) になることのドキュメントが見つけられず・・・。
8:08 AM
dictionary[key] != nil は不細工なので。
Avatar
keys作っちゃうとそこのオーバーヘッドが大変そう
Avatar
Kishikawa Katsumi 5/2/2018 8:12 AM
かっこいいかどうかはともかく、 index(forKey:) が目当てのメソッドじゃないしょうか?
Avatar
https://github.com/apple/swift-evolution/blob/master/proposals/0154-dictionary-key-and-value-collections.md#proposed-solution Keys 実装目的の最初に挙げられているくらいなので、O(1) だと思うんですが、実装追えてないです。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
Kishikawa Katsumi 5/2/2018 8:22 AM
https://github.com/apple/swift/blob/82226642c2459c0f5d2054fe1f6545b57efafffb/stdlib/public/core/Dictionary.swift#L655-L660 なんかNSDictionaryをラップしてる場合はO(n)と書いてあります。
swift - The Swift Programming Language
8:22 AM
^ はindex(forKey:) についての話です。
8:25 AM
かっこよくないと思いますけど dictionary[key] != nil は一番わかりやすいと思いますね。
Avatar
追いました。 https://github.com/apple/swift/blob/82226642c2459c0f5d2054fe1f6545b57efafffb/stdlib/public/core/Dictionary.swift#L1255-L1258 Dictionary.Keys.contains(_:) は最終これが呼ばれるので、O(1) ですね。(Nativeの場合) (edited)
swift - The Swift Programming Language
🙏 1
Avatar
あれでも、結局、 index(forKey:) と同じってこと?
Avatar
Kishikawa Katsumi 5/2/2018 8:27 AM
_variantBuffer.index(forKey:) は結局 Dictionary.index(forKey:) と同じですね。
Avatar
おおお、そんなところ( Proposal )に書いてあったんですね・・・。
Avatar
keys は struct 1つ作るだけだからそんなにオーバーヘッドなさそう https://github.com/apple/swift/blob/82226642c2459c0f5d2054fe1f6545b57efafffb/stdlib/public/core/Dictionary.swift#L1169-L1173
swift - The Swift Programming Language
Avatar
index(for:) にしても nil と比較することになると思うんで、ダイレクトにキーが存在するかを調べているということをコード上で表し、かつオーバーヘッドの少ない(最低でも O(1) の)方法はなんだろうということでした。
8:32 AM
安心して dictionary.keys.contains(key) 使うことにします。
🙂 1
Avatar
Keysもcow効くのすごい
Avatar
_customContainsEquatableElement mayBeGet(key) != nil を直接使わず index(forKey: key) != nil なのは何故なんだろう。 (edited)
Avatar
キーがないということを明確に表したかったとか?でもそのせいで NSDictionary をラップしてたら O(1) じゃなくなってる?? (edited)
Avatar
NSDictionary をラップしてないときは、 _variantBufferNativeDictionaryBuffer で、それだと、 index(forKey:)maybeGet_find を呼ぶことになるので同じですよね。(値を取得しない分、 index(forKey:) の方が得)
8:50 AM
NSDictionary をラップしているときは、 _CocoaDictionaryBuffer なので、 index(forKey:) が中で mayBeGet を呼ぶようになっているので、結局同じっぽいような。
Avatar
ああ、Native の方だと index(forKey:) のほうが特なのですね。納得。 Cocoa のほうだと、maybeGet で見つかったときに、比較的重い処理 https://github.com/apple/swift/blob/82226642c2459c0f5d2054fe1f6545b57efafffb/stdlib/public/core/Dictionary.swift#L3026-L3036 が入るので、何故なんだろうと思ったのです。
swift - The Swift Programming Language
Avatar
あ、ほんとだ。この重い処理は何なんでしょう
8:55 AM
ああ、Indexを探しているのか。
Avatar
https://github.com/apple/swift/blob/82226642c2459c0f5d2054fe1f6545b57efafffb/stdlib/public/core/Dictionary.swift#L1255-L1258index(for:) を呼ばずに https://github.com/apple/swift/blob/82226642c2459c0f5d2054fe1f6545b57efafffb/stdlib/public/core/Dictionary.swift#L3397-L3420 みたいな分岐をして .cocoa のときに maybeGet なり何なりを使って検査するようにすれば NSDictionary をラップしてても dictionary.keys.contains(key) を O(1) にできるような気がするんですが、そんなことはないですか?
swift - The Swift Programming Language
swift - The Swift Programming Language
Avatar
_VariantDictionaryBuffer にそれ用のメソッドを作って、_customContainsEquatableElement から呼ぶべきだと思いますが、はいキーの有無だけであれば O(1) にできると思います。 (edited)
Avatar
_VariantDictionaryBuffer 側に containsKey みたいなメソッドを作ってそれを呼ぶのがいいんでしょうか。 (edited)
Avatar
だと思います。
🙂 1
Avatar
NSDictionary をラップしてても O(1) になってる? @swiftbot import Foundation let native1M = [String: String](uniqueKeysWithValues: (1...1_000_000).map { ("\($0)", "\($0)") }) let cocoa1M = (native1M as NSDictionary) as! [String: String] let native2M = [String: String](uniqueKeysWithValues: (1...2_000_000).map { ("\($0)", "\($0)") }) let cocoa2M = (native2M as NSDictionary) as! [String: String] let n = 10 func measure(_ operation: () -> ()) { var sum: TimeInterval = 0 for i in 1...n { let start = Date.timeIntervalSinceReferenceDate operation() let end = Date.timeIntervalSinceReferenceDate let interval = end - start print("\(i): \(interval)") sum += interval } print("avg: \(sum / TimeInterval(n))") } let dictionaries: [(String, [String: String])] = [ ("Native 1M", native1M), ("Cocoa 1M", cocoa1M), ("Native 2M", native2M), ("Cocoa 2M", cocoa2M), ] for (name, dictionary) in dictionaries { print(name) measure { for i in 1...100 { _ = dictionary.keys.contains("\(i)") } } }
🛠 1
Avatar
swiftbot BOT 5/2/2018 9:42 AM
Swift version 4.1 (swift-4.1-RELEASE)
9:42 AM
/usercode/main.swift:4:16: error: cannot convert value of type '[String : String]' to type 'NSDictionary' in coercion let cocoa1M = (native1M as NSDictionary) as! [String: String] ^~~~~~~~ /usercode/main.swift:6:16: error: cannot convert value of type '[String : String]' to type 'NSDictionary' in coercion let cocoa2M = (native2M as NSDictionary) as! [String: String] ^~~~~~~~
Avatar
あれ?手元では通ってるのに。
9:43 AM
あ、 Linux だからか。
9:43 AM
そりゃダメだ。
Avatar
as! [String: String] の時点でどうもNativeに変換されているっぽいですね。
Avatar
なるほど。
9:55 AM
何かの Obj-C の API を介さないといけないということでしょうか
Avatar
import Foundation let native1M = [NSString: NSString](uniqueKeysWithValues: (1...1_000_000).map { ("\($0)" as NSString, "\($0)" as NSString) }) let cocoa1M = NSDictionary(dictionary: native1M) as! [NSString: NSString] let native2M = [NSString: NSString](uniqueKeysWithValues: (1...2_000_000).map { ("\($0)" as NSString, "\($0)" as NSString) }) let cocoa2M = NSDictionary(dictionary: native2M) as! [NSString: NSString] let n = 10 func measure(_ operation: () -> ()) { var sum: TimeInterval = 0 for i in 1...n { let start = Date.timeIntervalSinceReferenceDate operation() let end = Date.timeIntervalSinceReferenceDate let interval = end - start print("\(i): \(interval)") sum += interval } print("avg: \(sum / TimeInterval(n))") } let dictionaries: [(String, [NSString: NSString])] = [ ("Native 1M", native1M), ("Cocoa 1M", cocoa1M), ("Native 2M", native2M), ("Cocoa 2M", cocoa2M), ] for (name, dictionary) in dictionaries { print(name) measure { for i in 1...100 { _ = dictionary.keys.contains("\(i)" as NSString) } } } これで確認できました。 (edited)
Avatar
ありがとうございます!
Avatar
とりあえず Swift コンパイラをビルドして↑が再現することが確認できました。修正してみます。
Avatar
Before Native 1M 1: 0.00014901161193847656 2: 9.000301361083984e-05 3: 8.797645568847656e-05 4: 8.702278137207031e-05 5: 8.809566497802734e-05 6: 8.702278137207031e-05 7: 8.797645568847656e-05 8: 8.702278137207031e-05 9: 8.702278137207031e-05 10: 8.809566497802734e-05 avg: 9.392499923706054e-05 Cocoa 1M 1: 1.5260519981384277 2: 1.4988809823989868 3: 1.4609719514846802 4: 1.4877859354019165 5: 1.4853370189666748 6: 1.4784049987792969 7: 1.4788520336151123 8: 1.4836270809173584 9: 1.5162140130996704 10: 1.471932053565979 avg: 1.4888058066368104 Native 2M 1: 9.799003601074219e-05 2: 7.700920104980469e-05 3: 7.605552673339844e-05 4: 7.605552673339844e-05 5: 7.700920104980469e-05 6: 7.700920104980469e-05 7: 7.593631744384766e-05 8: 7.700920104980469e-05 9: 7.700920104980469e-05 10: 9.09566879272461e-05 avg: 8.020401000976562e-05 Cocoa 2M 1: 2.558851957321167 2: 2.5838489532470703 3: 2.5781790018081665 4: 2.586503028869629 5: 2.5640339851379395 6: 2.611467957496643 7: 2.587472081184387 8: 2.5809329748153687 9: 2.5621449947357178 10: 2.583261013031006 avg: 2.5796695947647095
2:04 PM
After Native 1M 1: 0.0001779794692993164 2: 9.298324584960938e-05 3: 9.000301361083984e-05 4: 8.90493392944336e-05 5: 8.893013000488281e-05 6: 8.90493392944336e-05 7: 0.00011992454528808594 8: 0.0001380443572998047 9: 9.799003601074219e-05 10: 9.59634780883789e-05 avg: 0.00010799169540405273 Cocoa 1M 1: 0.00013005733489990234 2: 9.799003601074219e-05 3: 9.799003601074219e-05 4: 9.799003601074219e-05 5: 9.799003601074219e-05 6: 9.799003601074219e-05 7: 9.799003601074219e-05 8: 9.906291961669922e-05 9: 9.799003601074219e-05 10: 9.799003601074219e-05 avg: 0.0001013040542602539 Native 2M 1: 0.00010597705841064453 2: 9.000301361083984e-05 3: 9.000301361083984e-05 4: 8.893013000488281e-05 5: 8.90493392944336e-05 6: 8.90493392944336e-05 7: 8.893013000488281e-05 8: 9.000301361083984e-05 9: 9.000301361083984e-05 10: 8.90493392944336e-05 avg: 9.109973907470704e-05 Cocoa 2M 1: 0.00010001659393310547 2: 9.799003601074219e-05 3: 9.799003601074219e-05 4: 9.906291961669922e-05 5: 9.799003601074219e-05 6: 9.799003601074219e-05 7: 9.799003601074219e-05 8: 9.799003601074219e-05 9: 9.894371032714844e-05 10: 9.799003601074219e-05 avg: 9.839534759521484e-05
Avatar
@rintaro PR 送ろうと思うんですが、こういう場合のパフォーマンスのテストの参考になりそうなものありますか?
Avatar
Dictionary.Keys.contains(_:) takes O(1) for native dictionaries. However it takes O(n) when dictionaries wrap a NSDictionary. This PR makes it to take just O(1) even when wrapping a NSDictionary. B...
💯 2
Avatar
ああー、反応できなくてごめんなさい。大丈夫だとおもいます!
🙂 1
Avatar
@Kishikawa Katsumi @hironytic @rintaro この前話してた dictionary.keys.contains(key) ですが、↑の PR がマージされたので NSDictionary をラップしてる場合でも O(1) になりました😀
👏 6
Avatar
Kishikawa Katsumi 5/9/2018 5:18 AM
そうすると、ヘッダのドキュメントの記述も直したほうが良さそう?
Avatar
O(n) って書いてあったのってここ↓じゃありませんっけ? https://github.com/apple/swift/blob/8afa9b1dcd2b535fb2b84ec87cafd36457d8eca6/stdlib/public/core/Dictionary.swift#L658 (edited)
swift - The Swift Programming Language
Avatar
Kishikawa Katsumi 5/9/2018 5:28 AM
そうです。そこの // Complexity: amortized O(1) for native buffer, O(n) when wrapping an // NSDictionary. っていうのはもう消していいのかなと。
Avatar
僕の PR は( NSDictionary をラップしているときに)それを使わないようにして O(n) を回避しているので、 index(for:) はそのままのはずですね。 (edited)
Avatar
Kishikawa Katsumi 5/9/2018 5:30 AM
あ、そうなんですね。index(for:) からそれが呼ばれてるのだと思ってました。
Avatar
_variantBuffer index(for:) を呼ぶ代わりに↓を呼ぶようになっています。 internal func containsKey(_ key: Key) -> Bool { if _fastPath(guaranteedNative) { return asNative.index(forKey: key) != nil } switch self { case .native: return asNative.index(forKey: key) != nil #if _runtime(_ObjC) case .cocoa(let cocoaBuffer): return SelfType.maybeGetFromCocoaBuffer(cocoaBuffer, forKey: key) != nil #endif } }
5:33 AM
Native のときは index(for:) が呼ばれますが、 NSDictionary をラップしているときは maybeGetFromCocoaBuffer になります。 (edited)
5:35 AM
index もいらないんで、その生成をショートカットできるならわずかにオーバーヘッドを減らせるかもしれないです。が、 O(1) が保証されることが一番大事だと思うので。
Avatar
@compilerEvaluable いいね。今はllvmが特定のc関数についてやってるだけなのかな? https://forums.swift.org/t/pitch-compile-time-constant-expressions-for-swift/12879
Chris Lattner and I have been working on a proposal to add compile-time constant expressions to Swift. Our goal is to create a very general feature that enables many other useful features that need compile-time execution, like: static assertions, value parameters in generics,...
Avatar
omochimetaru 5/22/2018 1:29 AM
貼ろうとしたらもう貼られてた。アツい提案が来ましたね、コンパイル時計算のプロポーザルが Authors: Marc Rasi, Chris Lattner から。
1:35 AM
SILパスとしてinterpreterが追加されてそこでコードを評価するみたい。 取り扱える言語仕様はSwiftのサブセットで、提案の中で詳細に定義されてる(長い)
Avatar
型チェックはあるのかな
Avatar
omochimetaru 5/22/2018 1:36 AM
型があるね
Avatar
素晴らしい、Genericsをconditionedにするとexistentialとれないから、「ExistentialをとるGenerics」はAnyだったんだけど、これがあれば保証できるようになる
1:37 AM
実行時fatalじゃなくなるぞ
Avatar
omochimetaru 5/22/2018 1:37 AM
This interpreter keeps track of intermediate values using an algebraic data type (ADT) whose variants correspond to the types that the interpreter can operate on. We call these "compiler-representable types".
1:37 AM
compiler representable type に限定されるらしい。どういうのがそれなのかはよくわかんない。
Avatar
むむ
Avatar
omochimetaru 5/22/2018 1:38 AM
とりあえず、Standard library Bool and Int types, Struct, Tupleが書いてある。
1:39 AM
Types This model supports: builtin integer type tuples of compiler-representable types user-defined structs whose fields are compiler-representable types, which are defined in the current module or which otherwise have a known/fixed layout. metatypes addresses of stack objects
Avatar
これは雰囲気Protocol使えなさそうやなぁ
Avatar
omochimetaru 5/22/2018 1:40 AM
いまのところ無いね。
Avatar
#swiftbot-sandbox でやった↓だけど、 Randomstruct っぽくない挙動をする・・・。 var a = Random.default var b = a print(a.next()) print(b.next()) 2190522142258413190 6214093798825593358
8:03 AM
仕方ない気もするけど。
Avatar
実装みた感じだと自身で種をもってないっぽい?
Avatar
単に自身で seed を持つようにしただけだと、 Random.default.next() と呼び出さない限り毎回初期化されちゃうから、
Avatar
内部はarc4randomとかそもそも種持てないやつか
Avatar
Random.default の度に色々やんないといけなくなっちゃう。
Avatar
nextがmutatingなのもミスリーディングですね
Avatar
まあ、ハードウェアノイズ使おうとすると原理的に無理か。
8:09 AM
struct なのがミスリーディングな気も。 class の方がよい?🤔
Avatar
omochimetaru 5/24/2018 8:09 AM
それ議論されてました
8:11 AM
Sure. Small disclaimer that this was originally written back in the Swift 1~2 days, so it is overdue for a simplifying rewrite. Also, I should point out that the term “Source” has a special meaning in my code. It basically means that something will provide an ~infinite ...
8:11 AM
どこだったかな・・・
8:11 AM
structの方が早いって計測結果とか貼られてた
8:12 AM
Generators as reference vs value types I think we should require Generators to be classes. It simplifies calling the functions and I don’t see any clear advantage of using struct Generators.
8:12 AM
ここらへんから。
Avatar
https://forums.swift.org/t/se-0202-random-unification/11313/186 Random自体じゃないですけど変わらないって言ってるような
8:18 AM
Random自体をどっちにするかの話もでてきてます?
Avatar
omochimetaru 5/24/2018 8:19 AM
Random自体とは?
Avatar
この比較は自作のXoroshiroとかでstruct/classの比較をしてますけど組み込みのRandomの速度については書いて無さそう
Avatar
omochimetaru 5/24/2018 8:19 AM
Look! The results for the struct and class versions of your Xorshift128Plus and LinearCongruential are now the same!
早さは一緒って言ってたか。
8:20 AM
組み込みのRandomが結局なんなのかよくわかっていない。
8:20 AM
この先の会話を読むとわかりそう?
8:26 AM
英語が難しい
Avatar
↓これってどうやればいいんですっけ? func foo<S : Sequence>(_ sequence: S) { ... } let a: Any = ... // a が Sequence か調べて Sequence のときは foo に渡すにはどうすればいい?
Avatar
AnySequence使っては?
Avatar
omochimetaru 5/29/2018 7:26 AM
できない気がする。
Avatar
確かにコンストラクタに渡せないか
Avatar
omochimetaru 5/29/2018 7:27 AM
既知の様々なSequenceを総当たりしないと。
Avatar
これできないの辛くないかな? Any に限らず Foo の中から BarProtocol を満たすものだけを渡したいってのができない。
7:40 AM
処理系的にはできそうな気がするけど構文が存在しない?
Avatar
omochimetaru 5/29/2018 7:40 AM
処理系的に無理じゃないですか?
7:41 AM
あー一応ジェネリクスのコンパイル先のSequenceのExistential表現は存在するか
7:41 AM
今は無いけど原理的にはできるって感じがする。
Avatar
うん、スペシャライズされないときに処理してるはずだから
Avatar
omochimetaru 5/29/2018 7:41 AM
まあ結局Existentialがほしいってことですよね
Avatar
うーん、 existential そのものじゃなくていいんよね。
7:42 AM
as して渡すだけだから、型として表に見えなくていい。
Avatar
omochimetaru 5/29/2018 7:42 AM
ジェネリックな関数に渡せるだけで
7:42 AM
変数の型としては使えなくてもいいってことですか?
Avatar
はい
Avatar
omochimetaru 5/29/2018 7:43 AM
if let seq = a as Sequence { // でもこれができちゃうよ print(type(of: seq)) foo(seq) } (edited)
Avatar
first class の existential じゃなくて、 <S : Sequence> に渡せるようにするだけの限定的なやつ
7:44 AM
そのコードだといかにも existential っぽいから
7:44 AM
新しい構文が必要そう。
Avatar
うーん、いい構文が思いつかない。 generalized existential が一番シンプルなのかな・・・
Avatar
omochimetaru 5/29/2018 8:10 AM
generalized existentialなんですけど Any<Sequence where .Iterator.Element == String> この表記、 型パラメータを一つ取るジェネリック型Anyがあるように見えてしまう気がしてきた
Avatar
@omochimetaru 元々は普通のプロトコルの existential も Any<FooProtocol> にしようという話があって、その時代に書かれたものだから。
8:22 AM
ちがった。 protocol<A, B>Any<A, B> にしようってだけだったか。 https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#renaming-protocol-to-any-
swift - The Swift Programming Language
8:23 AM
いずれにせよ Any<A, B>A & B になった以上、 generilized existential の構文も変更しないといけない気がする。それ以前に、あまり導入する気もなさそうな・・・。
Avatar
omochimetaru 5/29/2018 8:23 AM
Any<A, B> になりかけて A & B になったから僕の言ったような問題は今は無いのか
8:24 AM
その延長でいくと普通に let a: Sequence where Element == Int & Foo みたいになりそうだ。
Avatar
プロパティに対して↓のようなことができる方法ってないですか? struct Foo { // method func a() -> Int { return 2 } // computed property var b: Int { return 3 } // stored property let c: Int = 5 } let foo = Foo() print(Foo.a(foo)()) // OK print(Foo.b(foo)) // NG print(Foo.c(foo)) // NG
Avatar
自分で書くしかないような
Avatar
omochimetaru 6/1/2018 10:19 AM
KeyPath print(foo[keyPath: \Foo.b])
Avatar
KeyPath、structでも動くの知らなかった
Avatar
omochimetaru 6/1/2018 10:23 AM
処理系としてはMetaClassの中にレイアウト情報があってそれで動いてるはず
Avatar
@swift-4.2.4 func get<T, U>(_ keyPath: KeyPath<T, U>) -> (T) -> (U) { return { value in return value[keyPath: keyPath] } } struct A { let a: Int } let x = get(\A.a) print(x(A(a: 3))) (edited)
Avatar
3 (edited)
Avatar
@koher こうですかね。やりたいことはできそう。
Avatar
お、そもそも KeyPath でいい気がしてきました。ありがとうございます🙏🏻
Avatar
staticな参照を取る道具を取り回して何かやりたいのかと思った。
Avatar
KeyPath 、ちょっと合ってるか自信ないですが、↓になってほしくないですか? class Animal { var a: Int = 42 } class Cat : Animal {} let k1: WritableKeyPath<Animal, Int> = \.a let k2: KeyPath<Animal, Int> = k1 // OK let k3: PartialKeyPath<Animal> = k2 // OK let k4: AnyKeyPath = k3 // OK let k1b: WritableKeyPath<Animal, Any> = k1 // NG: これはできなくてよい let k2b: KeyPath<Animal, Any> = k2 // NG: これはできてほしい let k1c: WritableKeyPath<Cat, Int> = k1 // NG: これはできてほしい let k2c: KeyPath<Cat, Int> = k2 // NG: これはできてほしい let k3c: PartialKeyPath<Cat> = k3 // NG: これはできてほしい
3:48 PM
つまり、↓であってほしい気が。 class WritableKeyPath<in Root, Value> : ... { ... } class KeyPath<in Root, out Value> : ... { ... } class PartialKeyPath<in Root> : ... { ... } class AnyKeyPath { ... } (edited)
Avatar
なんか↓このメソッドおかしくないですか? KeyPathWritableKeyPath を結合しても KeyPath であってほしい気が。 https://developer.apple.com/documentation/swift/keypath/2945102-appending
4:36 PM
リファレンスには記載があるけど実際には使えない? @swiftbot struct Foo { var a: Int } struct Bar { var foo: Foo } let k1: KeyPath<Bar, Foo> = \.foo let k2: WritableKeyPath<Foo, Int> = \.a let k: WritableKeyPath<Bar, Int> = k1.appending(path: k2)
🛠 1
Avatar
swiftbot BOT 6/2/2018 4:36 PM
Author icon
koher
struct Foo { var a: Int } struct Bar { var foo: Foo } let k1: KeyPath<Bar, Foo> = \.foo let k2: WritableKeyPath<Foo, Int> = \.a let k: WritableKeyPath<Bar, Int> = k1.appending(path: k2)
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:11:39: error: cannot convert value of type 'KeyPath<Bar, Int>' to specified type 'WritableKeyPath<Bar, Int>' let k: WritableKeyPath<Bar, Int> = k1.appending(path: k2) ~~~^~~~~~~~~~~~~~~~~~~ as! WritableKeyPath<Bar, Int>
Avatar
↓ができない(このメソッドがない)のはなぜ? @swiftbot struct Foo { var a: Int = 42 } struct Bar { var foo: Foo = Foo() } let k1: KeyPath<Bar, Foo> = \.foo let k2: PartialKeyPath<Foo> = \.a let k: PartialKeyPath<Bar> = k1.appending(path: k2)
🛠 1
Avatar
swiftbot BOT 6/2/2018 4:47 PM
Author icon
koher
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo = Foo() } let k1: KeyPath<Bar, Foo> = \.foo let k2: PartialKeyPath<Foo> = \.a let k: PartialKeyPath<Bar> = k1.appending(path: k2)
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:11:49: error: cannot convert value of type 'PartialKeyPath<Foo>' to expected argument type 'ReferenceWritableKeyPath<_, _>' let k: PartialKeyPath<Bar> = k1.appending(path: k2) ^~
Avatar
↓はできるので結合できて問題ない気が。 @swiftbot struct Foo { var a: Int = 42 } struct Bar { var foo: Foo = Foo() } let k1: KeyPath<Bar, Foo> = \.foo let k2: PartialKeyPath<Foo> = \.a // let k: PartialKeyPath<Bar> = k1.appending(path: k2) let bar = Bar() // let a: Int = bar[keyPath: k1][keyPath: k2] let a: Any = bar[keyPath: k1][keyPath: k2] print(a) // OK: 42
🛠 1
Avatar
swiftbot BOT 6/2/2018 4:49 PM
Author icon
koher
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo = Foo() } let k1: KeyPath<Bar, Foo> = \.foo let k2: PartialKeyPath<Foo> = \.a // let k: PartialKeyPath<Bar> = k1.appending(path: k2) let bar = Bar() // let a: Int = bar[keyPath: k1][keyPath: k2] let a: Any = bar[keyPath: k1][keyPath: k2] print(a) // OK: 42
Version:
swift-4.1.1-RELEASE
Output:
42
Error:
Avatar
KeyPathWritableKeyPath を append して WritableKeyPath 生成するメソッドが(ドキュメント上?)できてしまってるの↓のせいか。 where 以下がコメントアウト。 extension _AppendKeyPath /* where Self == WritableKeyPath<T,U> */ { https://github.com/apple/swift/blob/master/stdlib/public/core/KeyPath.swift#L1812
swift - The Swift Programming Language
5:13 PM
swift - The Swift Programming Language
Avatar
(Writable)KeyPathPartialKeyPath を append して PartialKeyPath を得るの、とりあえず無理やりで extension 書けた。 @swiftbot struct Foo { var a: Int = 42 } struct Bar { var foo: Foo = Foo() } extension KeyPath { func appending(path: PartialKeyPath<Value>) -> PartialKeyPath<Root> { return (self as AnyKeyPath).appending(path: path as AnyKeyPath)! as! PartialKeyPath<Root> } } let k1: WritableKeyPath<Bar, Foo> = \.foo let k2: PartialKeyPath<Foo> = \.a let k: PartialKeyPath<Bar> = k1.appending(path: k2) let bar = Bar() let a: Any = bar[keyPath: k] print(a)
🛠 1
Avatar
swiftbot BOT 6/2/2018 5:31 PM
Author icon
koher
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo = Foo() } extension KeyPath { func appending(path: PartialKeyPath<Value>) -> PartialKeyPath<Root> { return (self as AnyKeyPath).appending(path: path as AnyKeyPath)! as! PartialKeyPath<Root> } } let k1: WritableKeyPath<Bar, Foo> = \.foo let k2: PartialKeyPath<Foo> = \.a let k: PartialKeyPath<Bar> = k1.appending(path: k2) let bar = Bar() let a: Any = bar[keyPath: k] print(a)
Version:
swift-4.1.1-RELEASE
Output:
42
Error:
Avatar
omochimetaru 6/2/2018 6:02 PM
厳密に読めてないけどパッと見そのとおりに思える。
Avatar
@swiftbot ↓だと didSet の中で didSet は呼ばれないけど・・・ struct Foo { var count: Int = 0 var a: Int = 42 { didSet { print("Foo.a didSet: \(count)") count += 1 } } } struct Bar { var count: Int = 0 var foo: Foo = Foo() { didSet { print("Bar.foo didSet: \(count), \(foo.count)") count += 1 foo.count += 100 } } } var bar = Bar() bar.foo.a = -1 (edited)
🛠 1
Avatar
swiftbot BOT 6/3/2018 3:41 PM
(edited)
Author icon
koher
struct Foo { var count: Int = 0 var a: Int = 42 { didSet { print("Foo.a didSet: \(count)") count += 1 } } } struct Bar { var count: Int = 0 var foo: Foo = Foo() { didSet { print("Bar.foo didSet: \(count), \(foo.count)") count += 1 foo.count += 100 } } } var bar = Bar() bar.foo.a = -1
Version:
swift-4.1.1-RELEASE
Output:
Foo.a didSet: 0 Bar.foo didSet: 0, 1
Error:
Avatar
@swiftbot Key Path 経由だと無限再帰・・・。 struct Foo { var count: Int = 0 var a: Int = 42 { didSet { print("Foo.a didSet: \(count)") count += 1 } } } struct Bar { var count: Int = 0 var foo: Foo = Foo() { didSet { print("Bar.foo didSet: \(count), \(foo.count)") count += 1 // foo.count += 100 self[keyPath: \Bar.foo].count += 100 } } } var bar = Bar() bar.foo.a = -1 (edited)
🛠 1
Avatar
swiftbot BOT 6/3/2018 3:43 PM
(edited)
Author icon
koher
struct Foo { var count: Int = 0 var a: Int = 42 { didSet { print("Foo.a didSet: \(count)") count += 1 } } } struct Bar { var count: Int = 0 var foo: Foo = Foo() { didSet { print("Bar.foo didSet: \(count), \(foo.count)") count += 1 // foo.count += 100 self[keyPath: \Bar.foo].count += 100 } } } var bar = Bar() bar.foo.a = -1
Version:
swift-4.1.1-RELEASE
Output:
Foo.a didSet: 0 Bar.foo didSet: 0, 1 Bar.foo didSet: 1, 101 Bar.foo didSet: 2, 201 Bar.foo didSet: 3, 301 Bar.foo didSet: 4, 401 Bar.foo didSet: 5, 501 Bar.foo didSet: 6, 601 Bar.foo didSet: 7, 701 Bar.foo didSet: 8, 801 Bar.foo didSet: 9, 901 Bar.foo didSet: 10, 1001 Bar.foo didSet: 11, 1101 Bar.foo didSet: 12, 1201 Bar.foo didSet: 13, 1301 Bar.foo didSet: 14, 1401 Bar.foo didSet: 15, 1501 Bar.foo didSet: 16, 1601 Bar.foo didSet: 17, 1701 Bar.foo didSet: 18, 1801 Bar.foo didSet: 19, 1901 Bar.foo didSet: 20, 2001 Bar.foo didSet: 21, 2101 Bar.foo didSet: 22, 2201 Bar.foo didSet: 23, 2301 Bar.foo didSet: 24, 2401 Bar.foo didSet: 25, 2501 Bar.foo didSet: 26, 2601 Bar.foo didSet: 27, 2701 Bar.foo didSet: 28, 2801 Bar.foo didSet: 29, 2901 Bar.foo didSet: 30, 3001 Bar.foo didSet: 31, 3101 Bar.foo didSet: 32, 3201 Bar.foo didSet: 33, 3301 Bar.foo didSet: 34, 3401 Bar.foo didSet: 35, 3501 Bar.foo didSet: 36, 3601 Bar.foo didSet: 37, 3701 Bar.foo didSet: 38, 3801 Bar.foo didSet: 39, 3901 ...
Error:
/usr/bin/swift[0x3f24d64] /usr/bin/swift[0x3f250a6] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7fb6ec227390] /usr/lib/swift/linux/libswiftCore.so(swift_conformsToProtocol+0x3e)[0x7fb6e840373e] /usr/lib/swift/linux/libswiftCore.so(+0x39c05f)[0x7fb6e83f505f] /usr/lib/swift/linux/libswiftCore.so(+0x39b82d)[0x7fb6e83f482d] /usr/lib/swift/linux/libswiftCore.so(+0x2e518a)[0x7fb6e833e18a] Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret /usercode/main.swift -disable-objc-interop -I /Libraries/All/.build/release -module-name main -lAll Segmentation fault (core dumped)
3:43 PM
Avatar
omochimetaru 6/4/2018 1:16 AM
countに代入するメソッドを作って、それをsetterの中で呼び出した場合も同じ事になるし、自然だと思います
Avatar
昨日試したときはmutatinf funcで書き換えた場合(多分inoutも)はならなかった。
Avatar
omochimetaru 6/4/2018 1:20 AM
あれ、マジすか 後で試してみます
Avatar
omochimetaru 6/4/2018 1:49 AM
@swiftbot struct Stone { var name: String = "" { didSet { let newValue = name if recCount == 5 { return } recCount += 1 print("name.didSet begin: \(oldValue) -> \(newValue)") update() print("name.didSet end: \(oldValue) -> \(newValue)") } } var recCount = 0 mutating func update() { name = "jiro" } } var b = Stone() b.name = "taro"
🛠 1
Avatar
swiftbot BOT 6/4/2018 1:49 AM
Author icon
omochimetaru
struct Stone { var name: String = "" { didSet { let newValue = name if recCount == 5 { return } recCount += 1 print("name.didSet begin: \(oldValue) -> \(newValue)") update() print("name.didSet end: \(oldValue) -> \(newValue)") } } var recCount = 0 mutating func update() { name = "jiro" } } var b = Stone() b.name = "taro"
Version:
swift-4.1.1-RELEASE
Output:
name.didSet begin: -> taro name.didSet begin: taro -> jiro name.didSet begin: jiro -> jiro name.didSet begin: jiro -> jiro name.didSet begin: jiro -> jiro name.didSet end: jiro -> jiro name.didSet end: jiro -> jiro name.didSet end: jiro -> jiro name.didSet end: taro -> jiro name.didSet end: -> taro
Error:
Avatar
omochimetaru 6/4/2018 1:49 AM
@koher やっぱり再入しました。
Avatar
↑で言えば namemutating funcStonedidSet から呼び出した場合の話だった。それだと直接編集するのと同じだから再帰しなくて当然か。
2:12 AM
この再帰を防ぐ良い方法ってないかな?
Avatar
omochimetaru 6/4/2018 2:12 AM
name.capitalize() みたいな事か。
Avatar
↓こういう場合。 @swiftbot struct Stone { var name: String = "" { didSet { let newValue = name if recCount == 5 { return } recCount += 1 print("name.didSet begin: \(oldValue) -> \(newValue)") name.append("x") print("name.didSet end: \(oldValue) -> \(newValue)") } } var recCount = 0 } var b = Stone() b.name = "taro"
🛠 1
Avatar
swiftbot BOT 6/4/2018 2:13 AM
Author icon
koher
struct Stone { var name: String = "" { didSet { let newValue = name if recCount == 5 { return } recCount += 1 print("name.didSet begin: \(oldValue) -> \(newValue)") name.append("x") print("name.didSet end: \(oldValue) -> \(newValue)") } } var recCount = 0 } var b = Stone() b.name = "taro"
Version:
swift-4.1.1-RELEASE
Output:
name.didSet begin: -> taro name.didSet end: -> taro
Error:
Avatar
omochimetaru 6/4/2018 2:14 AM
この再帰を防ぐ良い方法
自分ならフラグを立ててdidSetの中で分岐します、なるべくそのようなコールフロー自体を排除するようにリファクタリングするけど。
2:14 AM
didSetじゃなくてsetterじゃないと無理かも
Avatar
↓これできてほしい気が。 @swiftbot struct Foo { var a: Int = 42 } struct Bar { var foo: Foo? = Foo() } var bar = Bar() bar[keyPath: \Bar.foo?.a] = -1 // ⛔ print(bar.foo!.a)
🛠 1
Avatar
swiftbot BOT 6/5/2018 4:56 AM
Author icon
koher
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo? = Foo() } var bar = Bar() bar[keyPath: \Bar.foo?.a] = -1 // ⛔ print(bar.foo!.a)
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:10:27: error: cannot assign to immutable expression of type 'Int?' bar[keyPath: \Bar.foo?.a] = -1 // ⛔
Avatar
もちろん↓はできる。 @swiftbot struct Foo { var a: Int = 42 } struct Bar { var foo: Foo? = Foo() } var bar = Bar() bar.foo?.a = -1 // ✅ print(bar.foo!.a)
🛠 1
Avatar
swiftbot BOT 6/5/2018 4:57 AM
Author icon
koher
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo? = Foo() } var bar = Bar() bar.foo?.a = -1 // ✅ print(bar.foo!.a)
Version:
swift-4.1.1-RELEASE
Output:
-1
Error:
Avatar
それ確かbugsでも話題になってましたよ
4:58 AM
ObjectiveCだとOptional-chainingなkvcできるのにswiftはできねーじゃんってのが
4:58 AM
あった記憶がある
4:58 AM
RxSwiftとかReactiveCocoaも、それで困ってましたね
Avatar
おお、そうなんですね。できるようになったらいいんですが・・・。
5:12 AM
Joe Groff added a comment - 7 Sep 2017 2:49 AM This is by design. You can't write back through optional chains, since there's nowhere to write to if the element is nil.
5:12 AM
😭
5:14 AM
あー、確かに non-nil しか書き戻せないというのを記述不能なのか。
5:15 AM
Jaden Geller and Matthew Johnson suggested some extensions to Optional that could make working with writable key paths more expressive within the current model:
extension Optional { // Produce the `default` value if `self` is nil. subscript(default value: Wrapped) -> Wrapped { get { return self ?? value } set { self = newValue } } // Act like optional chaining on read, while allowing "writes" that drop // the value on the floor if `self` is nil. subscript<T>(droppingWritesOnNil path: WritableKeyPath<Wrapped, T>) -> T? { get { return self?[keyPath: path] } set { if let newValue = newValue { self?[keyPath: path] = newValue } } } }
5:19 AM
↑使ったらネストした KeyPath で記述できました。 @swiftbot extension Optional { // Produce the `default` value if `self` is nil. subscript(default value: Wrapped) -> Wrapped { get { return self ?? value } set { self = newValue } } // Act like optional chaining on read, while allowing "writes" that drop // the value on the floor if `self` is nil. subscript<T>(droppingWritesOnNil path: WritableKeyPath<Wrapped, T>) -> T? { get { return self?[keyPath: path] } set { if let newValue = newValue { self?[keyPath: path] = newValue } } } } struct Foo { var a: Int = 42 } struct Bar { var foo: Foo? = Foo() } var bar = Bar() bar[keyPath: \Bar.foo[droppingWritesOnNil: \.a]] = -1 print(bar.foo!.a) bar.foo = nil bar[keyPath: \Bar.foo[droppingWritesOnNil: \.a]] = 999 print(String(describing: bar.foo)) (edited)
🛠 1
Avatar
swiftbot BOT 6/5/2018 5:19 AM
(edited)
Author icon
koher
extension Optional { // Produce the `default` value if `self` is nil. subscript(default value: Wrapped) -> Wrapped { get { return self ?? value } set { self = newValue } } // Act like optional chaining on read, while allowing "writes" that drop // the value on the floor if `self` is nil. subscript<T>(droppingWritesOnNil path: WritableKeyPath<Wrapped, T>) -> T? { get { return self?[keyPath: path] } set { if let newValue = newValue { self?[keyPath: path] = newValue } } } } struct Foo { var a: Int = 42 } struct Bar { var foo: Foo? = Foo() } var bar = Bar() bar[keyPath: \Bar.foo[droppingWritesOnNil: \.a]] = -1 print(bar.foo!.a) bar.foo = nil bar[keyPath: \Bar.foo[droppingWritesOnNil: \.a]] = 999 print(String(describing: bar.foo))
Version:
swift-4.1.1-RELEASE
Output:
-1 nil
Error:
Avatar
値型とイミュータブルクラスしか使ってないのに weak でイミュータビリティが壊れた。 @swiftbot struct Weak<Value : AnyObject> { weak var value: Value? { didSet { print("Weak.value didSet") } } init(_ value: Value) { self.value = value } } extension Weak : Equatable where Value : Equatable { static func ==(lhs: Weak<Value>, rhs: Weak<Value>) -> Bool { return lhs.value == rhs.value } } extension Weak : Hashable where Value : Hashable { var hashValue: Int { return value?.hashValue ?? 0 } } class Foo : Hashable { static func ==(lhs: Foo, rhs: Foo) -> Bool { return lhs === rhs } var hashValue: Int { return ObjectIdentifier(self).hashValue } } var dict: [Weak<Foo>: Int] = [:] var weak1: Weak<Foo>! var weak2: Weak<Foo>! do { let foo1 = Foo() weak1 = Weak(foo1) dict[weak1] = 111 print("weak1: \(weak1)") let foo2 = Foo() weak2 = Weak(foo2) dict[weak2] = 222 print("weak2: \(weak2)") for (key, value) in dict { print("\(key) -> \(value)") } print("dict[weak1]: \(String(describing: dict[weak1]))") print("dict[weak2]: \(String(describing: dict[weak2]))") } print("---") print("weak1: \(weak1)") print("weak2: \(weak2)") for (key, value) in dict { print("\(key) -> \(value)") } print("dict[weak1]: \(String(describing: dict[weak1]))") print("dict[weak2]: \(String(describing: dict[weak2]))") (edited)
🛠 1
Avatar
swiftbot BOT 6/5/2018 7:43 AM
(edited)
Author icon
koher
struct Weak<Value : AnyObject> { weak var value: Value? { didSet { print("Weak.value didSet") } } init(_ value: Value) { self.value = value } } extension Weak : Equatable where Value : Equatable { static func ==(lhs: Weak<Value>, rhs: Weak<Value>) -> Bool { return lhs.value == rhs.value } } extension Weak : Hashable where Value : Hashable { var hashValue: Int { return value?.hashValue ?? 0 } } class Foo : Hashable { static func ==(lhs: Foo, rhs: Foo) -> Bool { return lhs === rhs } var hashValue: Int { return ObjectIdentifier(self).hashValue } } var dict: [Weak<Foo>: Int] = [:] var weak1: Weak<Foo>! var weak2: Weak<Foo>! do { let foo1 = Foo() weak1 = Weak(foo1) dict[weak1] = 111 print("weak1: \(weak1)") let foo2 = Foo() weak2 = Weak(foo2) dict[weak2] = 222 print("weak2: \(weak2)") for (key, value) in dict { print("\(key) -> \(value)") } print("dict[weak1]: \(String(describing: dict[weak1]))") print("dict[weak2]: \(String(describing: dict[weak2]))") } print("---") print("weak1: \(weak1)") print("weak2: \(weak2)") for (key, value) in dict { print("\(key) -> \(value)") } print("dict[weak1]: \(String(describing: dict[weak1]))") print("dict[weak2]: \(String(describing: dict[weak2]))")
Version:
swift-4.1.1-RELEASE
Output:
weak1: Optional(main.Weak<main.Foo>(value: Optional(main.Foo))) weak2: Optional(main.Weak<main.Foo>(value: Optional(main.Foo))) Weak<Foo>(value: Optional(main.Foo)) -> 222 Weak<Foo>(value: Optional(main.Foo)) -> 111 dict[weak1]: Optional(111) dict[weak2]: Optional(222) --- weak1: Optional(main.Weak<main.Foo>(value: nil)) weak2: Optional(main.Weak<main.Foo>(value: nil)) Weak<Foo>(value: nil) -> 222 Weak<Foo>(value: nil) -> 111 dict[weak1]: nil dict[weak2]: nil
Error:
7:43 AM
Avatar
破壊しようとしてるようにしか見えないw
😅 1
Avatar
Kishikawa Katsumi 6/5/2018 8:53 AM
なるほど。これは動作としては私は納得できるけど、どうあるべきなんですかねえ?
8:54 AM
これかな。
8:59 AM
I've argued that we just shouldn't have weak fields in structs at all.
私はまあStructはweakプロパティを持てないとするのは、むしろ良いと思います。
(edited)
Avatar
僕も言語的には structweak プロパティを持てないのがいいんじゃないかと思います。
Avatar
Kishikawa Katsumi 6/5/2018 9:02 AM
weakはまあ現在のリファレンスカウントの仕組みによるものだから、クラスについてもweak自体を無くしてしまうことができたらそれが一番なんですけどね。
Avatar
うーん、 weak は GC であっても必要になるんじゃないでしょうか?
Avatar
Kishikawa Katsumi 6/5/2018 9:03 AM
相互参照していると解放できないっていうのを解決しよう。
Avatar
GCすなぁ
Avatar
相互参照しないように使うケースは多いですが、それ以外でほしいこともあると思います。
Avatar
個人的には今のrefcountは何だかんだ言いつつも好きです。
Avatar
Kishikawa Katsumi 6/5/2018 9:06 AM
Javaのように型でやればいいんじゃないかな。
Avatar
Kishikawa Katsumi 6/5/2018 9:07 AM
そうですね。まあ、これは現状の仕組みを解決できたらという前提の話だから、夢ですけど。
Avatar
ref count 自体は CoW を考えても必要そうですね。
Avatar
JavaのGC周りはおもちが面白い話し合ったはず
9:09 AM
Weak指定したのに壊れるとかその辺 (edited)
9:10 AM
Rustの型はかなり強力に生存期間を指定できるので魅力的ですね
Avatar
ref count ベースのままサイクルコレクターを入れるという手もありますが、パフォーマンスとのトレードオフになりローレベルでは許容できず、 2 系統作ることは分断を招くのでやらないというようなことを、たしか IBM での Chris Lattner のトークで言ってました。
Avatar
evolutionでも明記されてますね
Avatar
Kishikawa Katsumi 6/5/2018 9:17 AM
ライブラリレベルで導入できる何かとかないかな。
パフォーマンスとのトレードオフになりローレベルでは許容できず
^ はまあ理解するけど、その一方で、モバイルアプリ開発においては圧倒的に問題は解放されないか意図しない解放なので、そこのパフォーマンスは重要ではないし。。。
Avatar
実際書かれてるコードの 90% で不便を強いられてるのが辛いのはありますよね〜。
Avatar
omochimetaru 6/5/2018 1:25 PM
なるほど~weakがnilになるから壊れるのか
Avatar
↓みたいな KeyPath のパターンマッチしたくないですか?今だと KeyPath から構成要素を取り出す方法がないので。 struct Foo { var values: [Int] = [2, 3, 5] } let foo = Foo() let path = \Foo.values[0] print(foo[keyPath: path]) switch path { case \Foo.values[let i]: print(i) default: print("default") }
Avatar
norio_nomura 6/7/2018 3:51 AM
メソッドの別名を定義したいのだけれど、デフォルトパラメータを用意したい場合にはラッパーメソッドを作るしかないのだろうか? import Foundation func darwinStyleFoo(_ size: Int = 32) { print("darwin style foo") } func unknownStyleFoo(_ size: Int = 32) { print("unknown style foo") } #if _runtime(_ObjC) let foo = darwinStyleFoo #else let foo = unknownStyleFoo #endif foo(32) //OK // foo() // NG
Avatar
omochimetaru 6/7/2018 3:52 AM
クロージャに代入するとデフォルトパラメータなかったことになりますよね
Avatar
norio_nomura 6/7/2018 3:54 AM
@_silgen(…)みたいな裏技は無いかなあ。
Avatar
omochimetaru 6/7/2018 3:54 AM
import Foundation func darwinStyleFoo(_ size: Int) { print("darwin style foo") } func unknownStyleFoo(_ size: Int) { print("unknown style foo") } #if _runtime(_ObjC) let _foo = darwinStyleFoo #else let _foo = unknownStyleFoo #endif func foo(_ size: Int = 32) { _foo(size) } こういうスタイルはどうですか?
3:54 AM
(裏技は知らないです
Avatar
norio_nomura 6/7/2018 3:56 AM
スタックトレースを出力するメソッドでdarwinとLinuxで挙動を変えようとしているのですが、ラッパーを挟むとその分スタックトレースが増えるのですよね。
Avatar
omochimetaru 6/7/2018 3:58 AM
なるほど、う〜ん。。
Avatar
インライン化するとどうなりますか?
Avatar
norio_nomura 6/7/2018 4:24 AM
インライン化だけを制御する属性って4.2からですよね。
Avatar
こういうのはカリー化したらやりたいことできる様になるイメージ
Avatar
norio_nomura 6/7/2018 4:25 AM
APIデザインをガラッと変えるかな。
4:26 AM
一つのメソッドで挙動を変えるパラメータを持たせて、それらのデフォルトをプラットフォームによって変える、みたいな。
Avatar
  • darwinStyleFoounknownStyleFoo は明示的にどちらも呼べるようにしたい
  • どちらもデフォルト引数を設定したい
  • foo を呼ぶとプラットフォームによって適切な方が呼ばれるようにしたい(その場合でもデフォルト引数を設定したい)
  • foo を呼んだ場合でもスタックトレースは darwinStyleFoo 等と同じにしたい
(edited)
4:33 AM
とすると、 gyb 等で darwinStyleFoo 等のコードを foo の中にも展開するとかでしょうか・・・。
Avatar
norio_nomura 6/7/2018 4:34 AM
そうなりますね。
4:36 AM
現状のデザインが良くないみたいなので、変えてみます。 (edited)
4:36 AM
ありがとうございました。
Avatar
omochimetaru 6/7/2018 4:37 AM
一段多くてもよくて、そのライブラリの分は勝手に消しちゃうとか?
Avatar
@omochimetaru そう単純にはいかない気が。
4:40 AM
仮に [StackTraceElement] がとれて間の一つを取り除けたとしても、 foo を呼び出しているのにその次が darwinStyleFoo になって整合性が崩れそう。
Avatar
あーそうだ
5:00 AM
デフォルト引数なんですが、Staticなパラメータ参照出来るので
5:00 AM
class X { static let defaultArgument = 1 func foo(_ bar: Int = defaultArgument) { ... } } こういうのいけるはず
Avatar
norio_nomura 6/8/2018 3:06 AM
Staticなパラメータ参照出来るので
とても役に立ちました。ありがとうございます。
3:07 AM
このdefault2Generic parameter 'T' could not be inferredとなる理由が分からない。 @swift-4.2.4 import Foundation infix operator ∘ : CompositionPrecedence precedencegroup CompositionPrecedence { associativity: left higherThan: TernaryPrecedence } public struct Converter<T, U> { public typealias Handler = (T) -> U let handler: Handler public init(_ handler: @escaping Handler) { self.handler = handler } public func compose<A>(_ other: Converter<A, T>) -> Converter<A, U> { return .init { self.handler(other.handler($0)) } } public static func ∘ <A, B, C>(_ lhs: Converter<B, C>, _ rhs: Converter<A, B>) -> Converter<A, C> { return .init { lhs.handler(rhs.handler($0)) } } } public typealias Symbol = (String, String) public typealias Demangler = Converter<Symbol, Symbol> public typealias SymbolFormatter = Converter<Symbol, String> // Demangler extension Converter where T == Symbol, U == Symbol { #if os(macOS) public static let `default` = Converter { ($0.0.uppercased(), $0.1) } #elseif os(Linux) public static let `default` = Converter { ($0.0.lowercased(), $0.1) } #endif } // SymbolFormatter extension Converter where T == Symbol, U == String { #if os(macOS) public static let defaultStyle = Converter { "macOS: \($0)" } #elseif os(Linux) public static let defaultStyle = Converter { "linux: \($0)" } #endif public static let default1 = SymbolFormatter.defaultStyle.compose(Demangler.default) public static let default2 = SymbolFormatter.defaultStyle ∘ Demangler.default } (edited)
Avatar
swift42 BOT 6/8/2018 3:08 AM
exit status: 1 with stderr:<stdin>:49:63: error: generic parameter 'T' could not be inferred public static let default2 = SymbolFormatter.defaultStyle ∘ Demangler.default <stdin>:22:24: note: in call to operator '∘' public static func ∘ <A, B, C>(_ lhs: Converter<B, C>, _ rhs: Converter<A, B>) -> Converter<A, C> { (edited)
Avatar
norio_nomura 6/8/2018 4:15 AM
わかった。これで通った。 public static func ∘ <A>(_ lhs: Converter<T, U>, _ rhs: Converter<A, T>) -> Converter<A, U> { return .init { lhs.handler(rhs.handler($0)) } }
Avatar
omochimetaru 6/8/2018 4:16 AM
ああ。
4:16 AM
型自体のT, Uを使うべきところで、A, B, C を定義しちゃったから、 TとUが解決しなかったんですね。
Avatar
norio_nomura 6/8/2018 4:16 AM
でした。
Avatar
omochimetaru 6/8/2018 4:17 AM
static func が 型パラメータの支配下にあるの、忘れがち。僕もそれたまにやります。
4:17 AM
見てたけど推論のバグとかかと思って気づけなかった。。
Avatar
@swiftbot let a: Range<Int> = 1..<10 print(a.map { $0 * 2 })
🛠 1
Avatar
swiftbot BOT 6/8/2018 4:34 AM
Author icon
koher
let a: Range<Int> = 1..<10 print(a.map { $0 * 2 })
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:2:7: error: value of type 'Range<Int>' has no member 'map' print(a.map { $0 * 2 }) ^ ~~~
Avatar
↑何か間違えてますっけ?なんかアホなミスしてそう・・・。
Avatar
omochimetaru 6/8/2018 4:35 AM
Rangeにmapはないのでは
Avatar
omochimetaru 6/8/2018 4:36 AM
あー CountableRangeならCollectionとしてmapできるか。
Avatar
SequenceCollection を conform してる。
4:36 AM
ん? RangeSequence じゃないのか。
4:37 AM
Swift 4.1 だと。
Avatar
omochimetaru 6/8/2018 4:37 AM
4.1はまだCountableRangeとRangeがある?
4:37 AM
CountableRangeがc.c.でtypealiasになるのは4.2?
Avatar
そのはず。
Avatar
omochimetaru 6/8/2018 4:37 AM
じゃあ、それですね。
Avatar
ドキュメントが先行してるから騙された。
Avatar
omochimetaru 6/8/2018 4:38 AM
[2, 4, 6, 8, 10, 12, 14, 16, 18]
4:38 AM
Avatar
↓は問題なかった。 @swiftbot let a: CountableRange<Int> = 1..<10 print(a.map { $0 * 2 })
🛠 1
Avatar
swiftbot BOT 6/8/2018 4:38 AM
Author icon
koher
let a: CountableRange<Int> = 1..<10 print(a.map { $0 * 2 })
Version:
swift-4.1.1-RELEASE
Output:
[2, 4, 6, 8, 10, 12, 14, 16, 18]
Error:
Avatar
omochimetaru 6/8/2018 4:38 AM
@swiftbot versions
Avatar
swiftbot BOT 6/8/2018 4:38 AM
2018-05-29-a 2018-05-08-a 2018-05-02-a 2018-04-25-a 2018-04-23-a 4.1.1 4.1 4.0.3 4.0.2 4.0 3.1.1 3.1 3.0.2 3.0.1
Avatar
omochimetaru 6/8/2018 4:38 AM
@swiftbot --version=2018-05-29-a let a: Range<Int> = 1..<10 print(a.map { $0 * 2 })
🛠 1
Avatar
swiftbot BOT 6/8/2018 4:38 AM
Author icon
omochimetaru
let a: Range<Int> = 1..<10 print(a.map { $0 * 2 })
Version:
swift-4.2-DEVELOPMENT-SNAPSHOT-2018-05-29-a
Output:
[2, 4, 6, 8, 10, 12, 14, 16, 18]
Error:
Avatar
omochimetaru 6/8/2018 4:38 AM
うむ
🙏 1
Avatar
↓おもしろ。 @swiftbot extension Never: Equatable { public static func == (lhs: Never, rhs: Never) -> Bool { switch (lhs, rhs) { } } } let a: [Never] = [] print(a == a) // OK https://github.com/apple/swift-evolution/blob/master/proposals/0215-conform-never-to-hashable-and-equatable.md (edited)
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
🛠 1
Avatar
swiftbot BOT 6/12/2018 7:26 AM
(edited)
Author icon
koher
extension Never: Equatable { public static func == (lhs: Never, rhs: Never) -> Bool { switch (lhs, rhs) { } } } let a: [Never] = [] print(a == a) // OK
Version:
swift-4.1.1-RELEASE
Output:
true
Error:
Avatar
Never なので switch の中が空で OK 。 -> Bool だけど return がなくて OK 。
😮 2
Avatar
omochimetaru 6/12/2018 7:35 AM
@swiftbot func a(a: Int, b: String, c: Never) -> Float { }
🛠 1
Avatar
swiftbot BOT 6/12/2018 7:35 AM
Author icon
omochimetaru
func a(a: Int, b: String, c: Never) -> Float { }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:2:1: error: missing return in a function expected to return 'Float' } ^
Avatar
omochimetaru 6/12/2018 7:35 AM
あれ?
7:36 AM
引数に Neverを含む関数は絶対に呼び出せないからreturnいらないのかと思った。
Avatar
norio_nomura 6/12/2018 9:22 AM
おー、これってinamyさんあたりが何かで発表してたのを見た気がする。
Avatar
どうせだったら Error も付けてほしいですよね。 EquatableHashable だけでなくて。
9:34 AM
そうすれば bottom type にならなくても大分使いやすくなる。
9:34 AM
ってか、付けれるのか。今でも。 (edited)
9:36 AM
@swiftbot extension Never : Error {} enum Result<T, E: Error> { case success(T) case failue(E) } let a: Result<Int, Never> = .success(42) print(a)
🛠 1
Avatar
swiftbot BOT 6/12/2018 9:36 AM
Author icon
koher
extension Never : Error {} enum Result<T, E: Error> { case success(T) case failue(E) } let a: Result<Int, Never> = .success(42) print(a)
Version:
swift-4.1.1-RELEASE
Output:
success(42)
Error:
Avatar
NoError じゃなくても Never : Error 自分で後付でもいいのか。
Avatar
これできるならResultで対応してNoErrorをNeverのaliasにしてほしいなぁ
Avatar
うーんstdlib側でNever: Errorになるならいいですけど、stdlibで準拠させてないprotocolにライブラリがextensionで準拠させるのは僕は気乗りしないですねー。各自が自分のアプリコードでやる分にはいいと思うけど。
3:12 PM
ということでそのevolutionのレビュー期間中にコメントするとよさそうですね (edited)
Avatar
レビュー期間中なのか
Avatar
Active review (June 12...19)
🙏 1
3:17 PM
AuthorがReactiveSwiftやCarthageのmdiepです
Avatar
これざっと読むとError==Neverとか書いてあるのでそれやるなら…みたいなところはある
3:23 PM
議論元も読んでみよう
Avatar
Never could also conform to the Error protocol.
If we're cherry-picking protocols to conform Never to, Error seems like another good one to whitelist, since it's useful to use Never to close off the error path in Result-like abstractions.
5:59 AM
Moderate -1. Never is special because it has no instances - it is uninhabited by design. This means that it can conform to all protocols. I'd rather see a global solution rather than cherry picking these two specific protocols. Also, in the discussion of Never, it was poi...
Avatar
全然関係ないけどEquatableが気軽に定義できるようになったのめちゃくちゃ嬉しいですね
🙂 1
Avatar
omochimetaru 6/13/2018 6:44 AM
自動生成?
Avatar
そう。最近妙に捗るなと思ったら下手したらCondConfよりこっちのほうがコードベースに効いてる
Avatar
omochimetaru 6/13/2018 6:46 AM
適用箇所多いなら大きいよね
Avatar
omochimetaru 6/14/2018 3:06 AM
@swiftbot struct Cat { var name: String? func nya() { if let name = name { print(name) } } }
🛠 1
Avatar
swiftbot BOT 6/14/2018 3:06 AM
Author icon
omochimetaru
struct Cat { var name: String? func nya() { if let name = name { print(name) } } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
Avatar
omochimetaru 6/14/2018 3:07 AM
@swiftbot versions
Avatar
swiftbot BOT 6/14/2018 3:07 AM
2018-05-29-a 2018-05-08-a 2018-05-02-a 2018-04-25-a 2018-04-23-a 4.1.1 4.1 4.0.3 4.0.2 4.0 3.1.1 3.1 3.0.2 3.0.1
Avatar
omochimetaru 6/14/2018 3:07 AM
@swiftbot --version=3.0.2,3.1.1,4.0.3 struct Cat { var name: String? func nya() { if let name = name { print(name) } } }
🛠 1
Avatar
swiftbot BOT 6/14/2018 3:07 AM
Author icon
omochimetaru
struct Cat { var name: String? func nya() { if let name = name { print(name) } } }
Version:
swift-3.0.2-RELEASE
Output:
Error:
Version:
swift-3.1.1-RELEASE
Output:
Error:
Version:
swift-4.0.3-RELEASE
Output:
Error:
Avatar
omochimetaru 6/14/2018 3:08 AM
if let name = self.name { } じゃないといけなかった気がするんだけど勘違い・・・?
Avatar
norio_nomura 6/14/2018 3:56 AM
その場合、ずっとselfは不要だったと思う。
Avatar
omochimetaru 6/14/2018 3:59 AM
うーむ、なるほど。
Avatar
Kishikawa Katsumi 6/14/2018 4:37 AM
if letのパターンは大丈夫だっと思いますね。
Avatar
omochimetaru 6/14/2018 4:38 AM
struct Cat { func name() -> String { return "tama" } func nya() { let name = self.name() } }
4:38 AM
これだ、これと混ざってた。 (edited)
Avatar
Kishikawa Katsumi 6/14/2018 4:38 AM
関数と同じ名前の変数は怒られる。
Avatar
omochimetaru 6/14/2018 4:38 AM
struct Cat { func name() -> String? { return "tama" } func nya() { if let name = name() {} } }
4:39 AM
↑こうだといける。
4:39 AM
let var = expif let var = exp では 右辺と左辺の名前衝突ルールが違うんですね。
Avatar
EasyImagy 楽だ🙂 var image: Image<RGBA<UInt8>> = Image(nsImage: imageView.image!) image = Image(image[1000..<1640, 1000..<1640]) imageView.image! = image.nsImage
Avatar
@swiftbot import Foundation class UDPSocket { let queue = DispatchQueue(label: "socket") let socket = Socket() func noreturn() { queue.async { [weak self] in let socket = self!.socket socket.noreturn() } } deinit { socket.canceled = true print("UDPSocket deinit.") } } class Socket { var canceled = false func noreturn() { while !canceled { } } deinit { print("Socket deinit.") } } var udp: UDPSocket? = UDPSocket() udp!.noreturn() sleep(1) udp = nil sleep(1) (edited)
🛠 1
Avatar
swiftbot BOT 6/21/2018 1:36 AM
(edited)
Author icon
t.ae
import Foundation class UDPSocket { let queue = DispatchQueue(label: "socket") let socket = Socket() func noreturn() { queue.async { [weak self] in let socket = self!.socket socket.noreturn() } } deinit { socket.canceled = true print("UDPSocket deinit.") } } class Socket { var canceled = false func noreturn() { while !canceled { } } deinit { print("Socket deinit.") } } var udp: UDPSocket? = UDPSocket() udp!.noreturn() sleep(1) udp = nil sleep(1)
Version:
swift-4.1.1-RELEASE
Output:
UDPSocket deinit. Socket deinit.
Error:
1:36 AM
Avatar
@swiftbot import Foundation class UDPSocket { let queue = DispatchQueue(label: "socket") let socket = Socket() func noreturn() { queue.async { [weak self] in // let socket = self!.socket self?.socket.noreturn() } } deinit { socket.canceled = true print("UDPSocket deinit.") } } class Socket { var canceled = false func noreturn() { while !canceled { } } deinit { print("Socket deinit.") } } var udp: UDPSocket? = UDPSocket() udp!.noreturn() sleep(1) udp = nil sleep(1)
🛠 1
Avatar
swiftbot BOT 6/21/2018 1:38 AM
Author icon
t.ae
import Foundation class UDPSocket { let queue = DispatchQueue(label: "socket") let socket = Socket() func noreturn() { queue.async { [weak self] in // let socket = self!.socket self?.socket.noreturn() } } deinit { socket.canceled = true print("UDPSocket deinit.") } } class Socket { var canceled = false func noreturn() { while !canceled { } } deinit { print("Socket deinit.") } } var udp: UDPSocket? = UDPSocket() udp!.noreturn() sleep(1) udp = nil sleep(1)
Version:
swift-4.1.1-RELEASE
Output:
Error:
Avatar
上の2つで片方リークしてるんですがどう違うんですかね・・・
Avatar
omochimetaru 6/21/2018 1:39 AM
無限ループが静的に確定して最適化で壊れてるんじゃない?
Avatar
というと?
Avatar
omochimetaru 6/21/2018 1:42 AM
あれ?出力結果が変わった。
1:42 AM
クラッシュしてたように見えた。
Avatar
fatalerrorしてたのはキューに投げたタスク以前にudp = nilが走ってるみたいだったのでsleepいれました (edited)
Avatar
omochimetaru 6/21/2018 1:46 AM
ああ、わかった
1:46 AM
おそらく self?.hoge.fuga() この式は
1:47 AM
if let sself = self { sself.hoge.fuga() } こう展開されてる。
Avatar
そこで捕まるくらいしか考えられないなとは思ってたんですけど
1:49 AM
実行はfugaに移ってるわけで、そこではselfとしてhogeをもってますがsselfへの参照が残ってるのはどういうことなんでしょうか?
1:49 AM
if let sself = self { let hoge = sself.hoge hoge.fuga() }
Avatar
omochimetaru 6/21/2018 1:49 AM
そうはなってないんだろうね
1:49 AM
式を構成するオブジェクトはその式が終了するまで生きてると思う。
Avatar
なるほど・・・
1:50 AM
[weak self]してれば安心と思ってたんですがそうでもないですね
Avatar
omochimetaru 6/21/2018 1:50 AM
いや
1:50 AM
シングルスレッドならこれで問題は起こらない
1:51 AM
構成してる状況がかなり特殊な条件だと思う (edited)
1:52 AM
クロージャの中で self?. を使うと
1:52 AM
1行目は実行されたけど2行目では解放されてた、みたいな
1:52 AM
実行のバリエーションが増えちゃうから
1:53 AM
冒頭でguard letして意識して制御するほうが無難なことが多いと思う
1:53 AM
今回もそうしてれば不思議な事は起こらないし
1:53 AM
「[weak self] + guard let 」で概ね安心できそう。
Avatar
いや今回は冒頭sselfはまずくって
Avatar
if let sself = self { sself.hoge.fuga() } という展開だとしたら、 sself が強参照もってしまうので、だめじゃないですか?
Avatar
noreturnなので捕まり続けてしまう
Avatar
omochimetaru 6/21/2018 1:54 AM
hogeが stored property で fuga が mutating func だった場合
1:54 AM
sselfのsetterを介した書き戻しの必要もあるので
1:55 AM
一般的なコード生成を考えると自然に思う
1:56 AM
あ、まあこの制御の場合はそうね > noreturnなので捕まり続けてしまう
Avatar
多分今回の正解は、 queue.async { [weak socket] in socket?.noreturn() }
Avatar
冒頭でguard letしても今回はどうしようもなさそうな。。。
Avatar
omochimetaru 6/21/2018 1:58 AM
あーなので、言いたかったのは 多くのパターンでは weak self + guard let で良くて 今回のキューに無限ループを入れるような特殊なシチュエーションは、 その多くのパターンには当てはまらない って整理するのがよいのでは、と。 @t.ae
Avatar
はい。
Avatar
omochimetaru 6/21/2018 1:58 AM
例えばこれ、while ループさせずに、Queueにasyncの投げ直しを繰り返して
1:58 AM
ループ自体はQueueで担保して、ブロックするクロージャは入れない形に書き換えられて
1:58 AM
そうしていたなら 冒頭guard letでもこの問題を踏まなかったと思う
Avatar
ですね。ただここのnoreturnはrecvfromを想定しているのでこの形で書いています。
Avatar
omochimetaru 6/21/2018 1:59 AM
ああブロックする関数をキューにいれた場合の挙動を前提にやってるのか。
2:00 AM
多分今回の正解は、
元の意図の流れで書くならりんたろさんの↑がシンプルでいいですね
Avatar
[weak socket]は良さそうですが他にselfのプロパティを使う場合には[weak self]も足すか個別にキャプチャするか迷いそうですね
Avatar
omochimetaru 6/21/2018 2:01 AM
queue.async { [weak self] in let socket = self?.socket socket.noreturn() }
👌 2
Avatar
socketをキャプチャする場合は[socket]でもいいのかな
Avatar
omochimetaru 6/21/2018 2:01 AM
もろもろ踏まえて書くなら↑こうかな?
Avatar
同じものを書こうとしてた。
Avatar
omochimetaru 6/21/2018 2:02 AM
socketをキャプチャする場合は[socket]でもいいのかな
それだとキューの発火後にselfがdeinitされてる場合の挙動が変わるけどね。
Avatar
確かに
Avatar
omochimetaru 6/21/2018 2:02 AM
ただここで一回 self?.socket で切ってる事に
2:02 AM
そこまで重要な意味があることがコードから読み取れ無さそうだから
2:03 AM
コメント書いておきたいね・・
🙂 2
Avatar
コメント書いておきます。ありがとうございました。
Avatar
面白いなー。これはハマったとき悩みそう。
Avatar
最適化かけると早期に開放されたりして動作変わっちゃうかもしれないですね。
😳 1
Avatar
omochimetaru 6/21/2018 2:08 AM
あ〜〜 たしかに・・・
Avatar
SILの質問です。closureのSILを見て遊んでたら気づいたんですが、strong_retainstrong_releaseはペアになってないときもあるんですか?strong_retainは1回しか呼ばれてないのにstrong_releaseは2回呼ばれている func foo() -> Int { var i = 1 let closure: ((Int) -> Void) = { _ in } closure(10) return i } // foo() sil hidden @$S7sample23fooSiyF : $@convention(thin) () -> Int { bb0: %0 = alloc_stack $Int, var, name "i" // users: %3, %13 %1 = integer_literal $Builtin.Int64, 1 // user: %2 %2 = struct $Int (%1 : $Builtin.Int64) // users: %14, %3 store %2 to %0 : $*Int // id: %3 // function_ref closure #1 in foo() %4 = function_ref @$S7sample23fooSiyFySicfU_ : $@convention(thin) (Int) -> () // user: %5 %5 = thin_to_thick_function %4 : $@convention(thin) (Int) -> () to $@callee_guaranteed (Int) -> () // users: %12, %11, %10, %7, %6 debug_value %5 : $@callee_guaranteed (Int) -> (), let, name "closure" // id: %6 strong_retain %5 : $@callee_guaranteed (Int) -> () // id: %7 %8 = integer_literal $Builtin.Int64, 10 // user: %9 %9 = struct $Int (%8 : $Builtin.Int64) // user: %10 %10 = apply %5(%9) : $@callee_guaranteed (Int) -> () strong_release %5 : $@callee_guaranteed (Int) -> () // id: %11 strong_release %5 : $@callee_guaranteed (Int) -> () // id: %12 dealloc_stack %0 : $*Int // id: %13 return %2 : $Int // id: %14 } // end sil function '$S7sample23fooSiyF'
Avatar
norio_nomura 6/23/2018 9:47 AM
thin_to_thick_functionretainされたモノを返すのでは。
9:52 AM
@swift-4.2.4 -Xfrontend -emit-sil _ = { (_: Int) -> Void in }
Avatar
sil_stage canonical import Builtin import Swift import SwiftShims // main sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): // function_ref closure #1 in %2 = function_ref @$S4mainySicfU_ : $@convention(thin) (Int) -> () // user: %3 %3 = thin_to_thick_function %2 : $@convention(thin) (Int) -> () to $@callee_guaranteed (Int) -> () // user: %4 strong_release %3 : $@callee_guaranteed (Int) -> () // id: %4 %5 = integer_literal $Builtin.Int32, 0 // user: %6 %6 = struct $Int32 (%5 : $Builtin.Int32) // user: %7 return %6 : $Int32 // id: %7 } // end sil function 'main' // closure #1 in sil private @$S4mainySicfU_ : $@convention(thin) (Int) -> () { // %0 // user: %1 bb0(%0 : $Int): debug_value %0 : $Int // id: %1 %2 = tuple () // user: %3 return %2 : $() // id: %3 } // end sil function '$S4mainySicfU_'
Avatar
thin_to_thick_functionか。ドキュメントを探すとそれっぽい記述が見つかりました。@ callee_guaranteedが@convention(thick)を示しているの知らなかったので気づきませんでした。ありがとうございます! @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. This attribute is implied by @callee_owned or @callee_guaranteed. (edited)
Avatar
@swiftbot ↓警告が出る。 extension Optional { @_specialize(exported: true, where Wrapped == Int, S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
🛠 1
Avatar
swiftbot BOT 6/25/2018 5:23 AM
Author icon
koher
extension Optional { @_specialize(exported: true, where Wrapped == Int, S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:2:48: warning: redundant same-type constraint 'Wrapped' == 'Int' @_specialize(exported: true, where Wrapped == Int, S == [Int]) ^ /usercode/main.swift:2:58: note: same-type constraint 'S.Element' == 'Int' implied here @_specialize(exported: true, where Wrapped == Int, S == [Int]) ^
Avatar
@swiftbot 冗長な部分を消すとエラーになる。 extension Optional { @_specialize(exported: true, where Wrapped == Int) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
🛠 1
Avatar
swiftbot BOT 6/25/2018 5:24 AM
Author icon
koher
extension Optional { @_specialize(exported: true, where Wrapped == Int) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:2:6: error: too few type parameters are specified in '_specialize' attribute (got 1, but expected 2) @_specialize(exported: true, where Wrapped == Int) ^ /usercode/main.swift:2:6: error: Missing constraint for 'S' in '_specialize' attribute @_specialize(exported: true, where Wrapped == Int) ^
Avatar
@swiftbot もう一つの方を消しても同じくエラー。 extension Optional { @_specialize(exported: true, where S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
🛠 1
Avatar
swiftbot BOT 6/25/2018 5:24 AM
Author icon
koher
extension Optional { @_specialize(exported: true, where S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:2:6: error: too few type parameters are specified in '_specialize' attribute (got 1, but expected 2) @_specialize(exported: true, where S == [Int]) ^ /usercode/main.swift:2:6: error: Missing constraint for 'Wrapped' in '_specialize' attribute @_specialize(exported: true, where S == [Int]) ^
Avatar
これは警告が出る条件判定のコンパイラのバグ?
Avatar
omochimetaru 6/25/2018 5:25 AM
func の方を消すのはどうなりますか?
Avatar
func の方を消すってどういうこと?
Avatar
omochimetaru 6/25/2018 5:25 AM
specializeの中身と func文のwhere句が冗長なのかなって思って。
Avatar
それはできなくない?
5:27 AM
条件が変わってしまう。
5:28 AM
@swiftbot funcwhere を消すと↓ WrapedS.Element が同じ型である保証がなくなって + ができない。 extension Optional { @_specialize(exported: true, where Wrapped == Int, S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] { return Array(sequence) + (self.map { [$0] } ?? []) } }
🛠 1
Avatar
swiftbot BOT 6/25/2018 5:29 AM
Author icon
koher
extension Optional { @_specialize(exported: true, where Wrapped == Int, S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] { return Array(sequence) + (self.map { [$0] } ?? []) } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:4:16: error: generic parameter 'S' could not be inferred return Array(sequence) + (self.map { [$0] } ?? []) ^
Avatar
omochimetaru 6/25/2018 5:29 AM
やってみたけどだめだった
5:29 AM
specializedの中だけで起きてる事ですね
Avatar
@_specialize(exported: true, where Wrapped == Int, S == [_]) みたいな記述を認めてほしいね。
5:32 AM
この _ が他の構文の where でも書けるなら Parameterized Extension がなくても↓みたいなのもできるし。 extension Optional where Wrapped == _? { func flatten() -> Wrapped.Wrapped? { return flatMap { $0 } } }
5:33 AM
@_specialize(exported: true, where Wrapped == Int, S == [Int]) で警告が出なくなるというのもいいけど、記述が冗長であることは否めない。 Int じゃなくて Foo<Bar<Baz>> とかだと 2 回書くのは大変。
Avatar
omochimetaru 6/25/2018 5:34 AM
_ が書けると Higher Kind Type が書けるようになる気がする
Avatar
たしかに
5:41 AM
protocol がジェネリックじゃないからギリギリ書けない?↓みたいなことが書きたいけど。 protocol Functor { associatedtype Value func map<F>(_ f: (Value) -> F.Value) -> F where F<_> == Self<_> }
Avatar
var foo: Foo? というプロパティを持つ型があって、そのメソッドで↓のようなことをやりたいときにうまい書き方ってありますか? if self.foo == nil { // self.foo の初期化 self.foo = ... } let foo: Foo = self.foo! // 以下、foo を使うコード
Avatar
lazy var foo: Foo = ... にしない理由は何でしょう?
Avatar
↓みたいにメソッドの引数を使って初期化したいときとかですね。 class ViewController { var foo: Foo? = nil func bar(_ x: Int) { if self.foo == nil { // self.foo の初期化 self.foo = Foo(x) } let foo: Foo = self.foo! // 以下、foo を使うコード ... } }
Avatar
これぐらいしか思いつきませんでした😅 func bar(_ x: Int) { let foo = self.foo ?? (self.foo = Foo(x), self.foo!).1 (edited)
Avatar
よくこんなの思いつきますね😅
7:15 AM
あ、でも ! が残ってる
Avatar
omochimetaru 6/25/2018 7:16 AM
let foo: Foo = { guard let foo = self.foo else { let foo = ... self.foo = foo return foo } return foo }() よくこれ書いてます
Avatar
なるほど・・・
Avatar
omochimetaru 6/25/2018 7:18 AM
!はないけど self.foo が 2回出てくるので それが嫌だったら高階関数用意したほうが良いと思います
Avatar
extension Optional { mutating func ensure(default val: @autoclosure () -> Wrapped) -> Wrapped { if let v = self { return v } let v = val() self = v return v } } class C { var foo: Foo? func test(x: Int) { let foo = self.foo.ensure(default: Foo(x)) } (edited)
Avatar
@omochimetaru こう? func initUnwrap<T>(_ optional: inout T?, initialize: () -> T) -> T { if let value = optional { return value } let value = initialize() optional = value return value } let foo: Foo = initUnwrap(&self.foo) { Foo(x) }
Avatar
omochimetaru 6/25/2018 7:21 AM
@koher そう
Avatar
あー、 inout より @rintaro さんの mutating func の方がキレイかな。
Avatar
omochimetaru 6/25/2018 7:21 AM
りんたろさんの Optional の mutating func にするのはオシャレだな。
Avatar
mutating funcselfinout 引数を体現してる。
Avatar
omochimetaru 6/25/2018 7:22 AM
第一引数の inout は mutatingメソッドと等価なわけだな
Avatar
この ensure 普通に標準ライブラリにほしい。
7:25 AM
Booltoggle が通ったことを考えるとこれもいけるのでは?
Avatar
代入が返値を持つのを意識的に避けている気があるので、無理筋っぽい。
7:26 AM
Bool.toggle は値返さないです。 (edited)
Avatar
Dictionarysubscript(_:default:) は同じじゃないですか?
Avatar
omochimetaru 6/25/2018 7:27 AM
mutating func かつ return self な例が無いのか
7:27 AM
Dictのsubscriptはなかった場合にdefaultが返るけどセットはしないんじゃないですっけ (edited)
Avatar
Bool.toggle は、メソッド単発の小さな改良のための Proposal の意でした。
7:29 AM
Dictのsubscriptはなかった場合にdefaultが返るけどセットはしない
あれ?そっか。
Avatar
@swiftbot extension Optional { @_specialize(exported: true, kind: partial, where S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } } kind: partial だと警告消えますね。出力されるコードが同等なのかは調べてないです。
🛠 1
Avatar
swiftbot BOT 6/25/2018 7:50 AM
Author icon
rintaro
extension Optional { @_specialize(exported: true, kind: partial, where S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
Avatar
なるほど〜。でも本当に partial になっちゃってたら微妙ですね・・・。
Avatar
$cat full.swift extension Optional { @_specialize(exported: true, kind: full, where Wrapped == Int, S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } } let a: Int? = 7 let b: [Int] = [2, 3, 5] print(a.foo(b)) $cat partial.swift extension Optional { @_specialize(exported: true, kind: partial, where S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } } let a: Int? = 7 let b: [Int] = [2, 3, 5] print(a.foo(b)) $swift -O full.swift full.swift:2:60: warning: redundant same-type constraint 'Wrapped' == 'Int' @_specialize(exported: true, kind: full, where Wrapped == Int, S == [Int]) ^ full.swift:2:70: note: same-type constraint 'S.Element' == 'Int' implied here @_specialize(exported: true, kind: full, where Wrapped == Int, S == [Int]) ^ [2, 3, 5, 7] $swift -O partial.swift [2, 3, 5, 7] $md5 full MD5 (full) = 728efb9ffc6814bb17e0eedb72c5cda2 $md5 partial MD5 (partial) = c07fb4573afb1d8ae2ee53f30f341383 (edited)
8:39 AM
とりあえず生成されたバイナリは違うみたいです。
8:41 AM
(念のため同じファイルを 2 回コンパイルしたら同じ生成物ができました。)
Avatar
-module-name 揃えないと同じバイナリにならないので
8:48 AM
$ swiftc -O partial.swift -module-name Test -o partial $ swiftc -O full.swift -module-name Test -o full で試したら一致しました。
🙏 1
8:49 AM
きちんと特殊化されているかはまた別問題ですが。
Avatar
なるほどー。
8:51 AM
きちんと特殊化されているかはまた別問題ですが。
full の方で特殊化できてなかったらどの道これ以上やりようがないですし、仕方なさそうですね。
Avatar
なんだか https://github.com/apple/swift/pull/13012 ちょうどこれっぽい話がされている
This PR adds a few items to the generics manifesto. The first two were discussed briefly on Twitter where @DougGregor requested a PR to add them. I plan to followup with a pitch to Swift evolutio...
11:07 AM
generic associatestype
11:08 AM
あくまでmanifestoへの追記のprですが
Avatar
↓こういうことでしょうか?🤔 protocol Functor { associatedtype Value associatedtype Transformed<T> func map<T>(_ transform: (Value) -> T) -> Transformed<T> } extension Optional { typealias Value = Wrapped typealias Transformed<T> = Optional<T> func map<T>(_ transform: (Wrapped) -> T) -> Optional<T> { ... } } (edited)
Avatar
それ可能ならHigherKindedTypeそのものっぽい
Avatar
omochimetaru 6/26/2018 1:46 AM
protocolのassociatedtypeに型パラメータを取るのか
Avatar
これって Functor の制約としては緩いですよね。
Avatar
assocの外側が自身じゃないとだめですかね
Avatar
ですねー。 (edited)
Avatar
でもやりたいことの8割はカバーできそう
Avatar
omochimetaru 6/26/2018 1:47 AM
ああ、なるほど、Selfから剥がさないと意味ちがうか。
1:47 AM
Optionalの場合に明示的に = Optional<T> と書いたから Functorになっただけで。
Avatar
Selfassociatedtype 含めて同一になっちゃうから強すぎて、
1:48 AM
Functor とか Monad を作ろうとしたら Self から associatedtype を剥がしたものを記述できる構文が必要なはず。
1:51 AM
↓の SelfProtocol みたいなものが必要。 protocol Functor { associatedtype Value func map<R: SelfProtocol>(_ transform: (Value) -> R.Value) -> R }
1:52 AM
Protocol は変か。
1:52 AM
OptionalProtocol じゃないもんな。
Avatar
Arrayもそうですね
1:53 AM
ただsequenceになるだけならそれはfunctorではない
Avatar
type でもないし、なんと呼べばいいんだ?型クラス?
1:56 AM
カインド = 「型の型」 - 例: Optional<Int> : * (型) - 例: Optional: * -> * (型→型)
1:56 AM
Kind でよい?
1:57 AM
↓とか? protocol Functor { associatedtype Value func map<R: MyKind>(_ transform: (Value) -> R.Value) -> R }
Avatar
omochimetaru 6/30/2018 7:22 AM
The review of SE-0217 — Introducing the !! "Unwrap or Die" operator to the Swift Standard Library begins now and runs through July 7, 2018. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you wo...
7:22 AM
メッセージ付きの!!がレビュー入り
7:24 AM
ここでも好評だったアイデアだけどラトナーは反対しとるね。
Avatar
While it addresses the issue of x!, it doesn't generalize or address the other failing forms in Swift, such as like try!, as!, array subscripting, integer overflows, etc.
なるほど。
1:31 AM
まあ array subscripting とかはともかく(それが API の選択だから、それを利用している時点で意図が感じられる)、 try!as!optional! と同様の問題は抱えてるはずで、 !! じゃ不十分というのはその通りだ。 (edited)
Avatar
omochimetaru 7/2/2018 2:18 AM
思ったより賛否両論の流れになってますねえ
Avatar
implicitly のある行に処理を差し込めるものを求めてるのかもしれない
2:20 AM
try! foo.bar()! !! "失敗した理由"
2:20 AM
こう書ける方が良いのかも?結構これは抜本的に変えないといけないからしんどいが (edited)
Avatar
Never as bottom type の流れに持っていけないかなー。
2:23 AM
?? fatalError() でいければ問題ないわけだし。
Avatar
それはアリアリですね
2:23 AM
try!やas!もtry?as? ?? fatalにすればok
Avatar
それ良さそうですね。
2:25 AM
Never as bottom type ってなんで進まないんだろう?誰も Proposal 出さないから?実装の問題?
2:27 AM
副作用があるメソッドの場合とかは微妙な気も。 try? foo.writeToFile(path) ?? fatalError("Reason")
Avatar
omochimetaru 7/2/2018 2:38 AM
(Erica_Sadun) > Even if the team prefers to use a () -> Never rhs, I'd still recommend using !! over ?? to indicate the imbalance in roles between the safely unwrapped lhs and the unsafely unwrapped rhs. Expanding Never to be a bottom type does not fix this symbology mismatch. Whether Never is or is not a bottom type is orthogonal to this proposal. (edited)
2:40 AM
Neverの話してるレスもあるけどEricaはそれでも !! が良いらしい。 Symbology mismatchが強調になってるんだけど、たしかに ?? でデフォルト値を与えると見せかけて fatalError で死ぬ っていうのも他の ! 用法と比べて危険性が見えにくい気もする。
Avatar
NeverがBottomになると嬉しいことが沢山あるのでそれはやった上で、T? ?? Neverだったらwarning出して!!使ってねと出るのがいいんじゃないかなぁとか (edited)
👀 1
Avatar
@swift-4.2.4 // https://github.com/apple/swift/blob/9286b3627d90523752cb1a2ffc02f7500ead0ea8/stdlib/public/core/FloatingPoint.swift.gyb#L2405-L2466 func test<T: BinaryFloatingPoint>(range: Range<T>) { print("\(T.self): \(range)") let delta = range.upperBound - range.lowerBound let maxSignificand = T.RawSignificand(1) << (T.significandBitCount + 1) // rand = generator.next(upperBound: maxSignificand) \in 0...maxSignificand-1 let zero: T.RawSignificand = 0 let maxx = maxSignificand - 1 let minimum = T(zero) * .ulpOfOne / 2 print("minimum == 0: \(minimum == 0)") let lb = delta * minimum + range.lowerBound print("lb == range.lowerBound: \(lb == range.lowerBound)") let maximum = T(maxx) * .ulpOfOne / 2 print("maximum < 1: \(maximum < 1)") let ub = delta * maximum + range.lowerBound print("ub < range.upperBound: \(ub < range.upperBound)") print("") } let floatRanges: [Range<Float>] = [1..<2, 2..<4] for range in floatRanges { test(range: range) } let doubleRanges: [Range<Double>] = [1..<2, 2..<4] for range in doubleRanges { test(range: range) }
Avatar
swift42 BOT 7/5/2018 1:14 AM
Float: 1.0..<2.0 minimum == 0: true lb == range.lowerBound: true maximum < 1: true ub < range.upperBound: false Float: 2.0..<4.0 minimum == 0: true lb == range.lowerBound: true maximum < 1: true ub < range.upperBound: false Double: 1.0..<2.0 minimum == 0: true lb == range.lowerBound: true maximum < 1: true ub < range.upperBound: false Double: 2.0..<4.0 minimum == 0: true lb == range.lowerBound: true maximum < 1: true ub < range.upperBound: false
Avatar
↑これFloat.random(1..<2)で2が生成されうることの確認なんですがbugs.swift.orgに投げればいいんですかね
Avatar
https://bugs.swift.org/browse/SR-8152 そもそもテストカバレッジが十分でないみたい。 とりあえず投げときます。
Avatar
浮動小数点の問題で発生し得るのかしら
Avatar
みたいですね。
1:53 AM
こんな面倒なコード書かなくても常にMaxを返すRNG作ってそれ渡せばいいですね。 RNG渡すことなんてそんな無いじゃんと思ってたけどテスタビリティは向上するのか。
Avatar
Float.random(in: Float(2.0) - .ulpOfOne ..< Float(2.0)) == Float(2.0) で true 出てしまう。
Avatar
https://bugs.swift.org/browse/SR-8178 とりあえず投げました。
Avatar
@rintaro 修正ありがとうございます🙇
👍 1
Avatar
omochimetaru 7/5/2018 5:20 AM
t.aeから直接話しを聞いたんだけど難しすぎワロタ
Avatar
@swift-4.2.4 let range = 0..<0 print(Int.random(in: range))
Avatar
swift42 BOT 7/5/2018 5:27 AM
exit status: 4 with stderr:Fatal error: Can't get random value with an empty range Current stack trace: 0 libswiftCore.so 0x00007f60e2191750 _swift_stdlib_reportFatalError + 168 1 libswiftCore.so 0x00007f60e1eec56a <unavailable> + 1488234 2 libswiftCore.so 0x00007f60e212859e <unavailable> + 3831198 3 libswiftCore.so 0x00007f60e1eec56a <unavailable> + 1488234 4 libswiftCore.so 0x00007f60e20838e9 <unavailable> + 3156201 5 libswiftCore.so 0x00007f60e1fb13d0 <unavailable> + 2294736 6 libswiftCore.so 0x00007f60e1fb1690 static FixedWidthInteger<>.random(in:) + 27 8 swift 0x0000000001041ffe <unavailable> + 12853246 9 swift 0x0000000001046122 <unavailable> + 12869922 10 swift 0x00000000004f82e2 <unavailable> + 1016546 11 swift 0x00000000004de86b <unavailable> + 911467 12 swift 0x00000000004d9ba0 <unavailable> + 891808 13 swift 0x000000000048a308 <unavailable> + 566024 14 libc.so.6 0x00007f60e52d3740 __libc_start_main + 240 15 swift 0x0000000000487fc9 <unavailable> + 557001 #0 0x0000000004106e24 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x4106e24) #1 0x0000000004104cb2 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4104cb2) #2 0x0000000004106fd2 SignalHandler(int) (/usr/bin/swift+0x4106fd2) #3 0x00007f60e6ba9390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f60e20838f1 $Ss18_fatalErrorMessage__4file4line5flagss5NeverOs12StaticStringV_A2HSus6UInt32VtFTf4nnddn_n (/usr/lib/swift/linux/libswiftCore.so+0x3028f1) #5 0x00007f60e1fb13d0 $Ss17FixedWidthIntegerPss08UnsignedC09MagnitudeRpzs06SignedC06StrideRpzrlE6random2in5usingxSnyxG_qd__zts21Random
Avatar
emptyかどうかはprecondition入ってます。
Avatar
なるほど。
Avatar
omochimetaru 7/5/2018 5:27 AM
それは1行目で落ちてるのでは?
Avatar
0..<0 自体は OK (edited)
Avatar
omochimetaru 7/5/2018 5:28 AM
そうか
5:28 AM
Precondition・・・
Avatar
ClosedRange Closed でない Range の場合は Optional 返すでもいい気が。 (edited)
Avatar
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
5:30 AM
いや内容的には違う話かな
Avatar
@swift-4.2.4 let range1 = 0..<1 print(String(describing: range1.first)) print(String(describing: Int.random(in: range1))) let range2 = 0..<0 print(String(describing: range2.first)) // print(String(describing: Int.random(in: range2))) // nil になってほしい
Avatar
swift42 BOT 7/5/2018 5:32 AM
Optional(0) 0 nil
Avatar
まさにどうして range.random() じゃないのかが書いてあるね。でもいまいち英文の意味がわからない・・・。
5:44 AM
"primary spelling" って何?一番よく使われる方法的な意味?
🤔 1
5:46 AM
Also, since we decided pretty early on that we're going to trap if for whatever reason we can't get a random number この trap って何を意味してる? signal を trap する話?それとも単にエラーハンドリング的な意味?
Avatar
エラーハンドリングでしょうねそこは (edited)
Avatar
RNG がランダムナンバーを生成出来ないなどの理由でエラーになるときは nil ではなく トラップして fatal なエラー (logic error) にすることを早い段階で決定した。 (edited)
🙏 1
5:49 AM
というのと、 Collection.random() が空のときに nil を返すことも決定したので、 range.random() を正規の表現にすると、前述の non-nil のポリシーに例外を持たせる事になってしまう (edited)
Avatar
フォーラムの議論ちゃんと読んでないんですけどRNG自体にいろいろ生やす方針はなかったんですかね。
5:52 AM
レス多すぎるし検索性も微妙なのでさっと探せない……
Avatar
omochimetaru 7/5/2018 5:52 AM
当然話し合ってるんじゃないかな Randomスレむちゃくちゃ長いことめっちゃ伸びてたし
Avatar
なるほどー。
6:16 AM
↓は O(n) なのかな? @swift-4.2.4 print(String(describing: "abcdefg".randomElement()))
Avatar
swift42 BOT 7/5/2018 6:16 AM
Optional("b")
Avatar
collectionに生えてるならO(1)では?
Avatar
StringIndexInt じゃないので。
Avatar
omochimetaru 7/5/2018 6:19 AM
CollectionはO(1)じゃないよ
Avatar
subscript は O(1) だけど
6:20 AM
インデックスをランダムに選ぶためのインデックス列が O(1) で用意できないので
Avatar
count から最初にインデックスのインデックスを決めて、
6:21 AM
順次アクセスかなと想像した。
Avatar
numericCastしてる
6:21 AM
Complexity: O(1) if the collection conforms to RandomAccessCollection; otherwise, O(n), where n is the absolute value of n.
Avatar
なるほど
Avatar
.count も O(n) なので、なかなか重い処理だ。
Avatar
String って生成時に count も生成してるんじゃないのか・・・。
Avatar
ASCII 時の最適化などもあるので、一概には言えないですね。
Avatar
てっきりバイト列のチェックは走ってて、そのときにカウントだけは保持してるかなと思ってました。
6:27 AM
RandomAccessCollection って subscript によるランダムアクセスが O(1) なんじゃなくて(当然これも満たされるけど)、インデックス間の任意個数分の移動が O(1) ってややこしいな・・・。
6:28 AM
Collectionsubscript が O(1) は保証されてるんだっけ・・・。 String は O(1) として。
Avatar
omochimetaru 7/5/2018 6:28 AM
Expected Performance Types that conform to Collection are expected to provide the startIndex and endIndex properties and subscript access to elements as O(1) operations.
Avatar
まさに同じとこ見てたw
6:30 AM
O(n) は論外としても、 O(log n) は認めてほしい気も。
Avatar
omochimetaru 7/5/2018 6:33 AM
StringGutsのGutsって結局なんなんだ(しばらく調べたけどわからず
Avatar
'guts' という言葉の意味自体は「内蔵」です。
Avatar
omochimetaru 7/5/2018 6:34 AM
なるほど・・・
Avatar
内臓じゃなくて内蔵もあるんですか?
Avatar
omochimetaru 7/5/2018 6:35 AM
Avatar
誤変換w 内臓です! (edited)
Avatar
ああ、誤変換でしたかw
Avatar
omochimetaru 7/5/2018 6:35 AM
誤変換を無意識に再変換してたw
6:45 AM
で、たしかにO(n)で文字をstartからendまでイテレートしてた。
😂 1
Avatar
ASCII でも CR+LF は 1 character なのが痛いところで 、O(n) ですね。
Avatar
omochimetaru 7/5/2018 6:47 AM
マジすか
6:47 AM
それは2文字でいいじゃんと思った。。
6:47 AM
普通にSwiftで文字列を作ったらこのパスには行かなそうだな
6:50 AM
あ、これはUTF8での要素数かな?
6:52 AM
うーんそうか、どうせGraphemeCrusterの事考えると
6:52 AM
Characterでのcountだけ持ってても特に意味がない気がする
6:53 AM
count使うってことはおそらくそれとセットでCharacterでのindexも使うはずで、そこはどうせシーケンシャルに操作しないといかんし
6:54 AM
文字数数えたいこととかはあるか。
6:54 AM
Stringのソース、無限にバリエーションがあって広大
Avatar
文字数数えたいこととかはあるか。
むしろそれが count の一番の用途じゃないの?
Avatar
omochimetaru 7/14/2018 1:49 PM
@t.ae 報告してたやつ直ってるけど、 upperboundにぶつかってたらもっかい呼び出すっていうワイルドなアプローチだった https://github.com/apple/swift/pull/17794/files
The problem seemed to come from the final addition + range.lowerBound.
Avatar
棄却して取り直せばOKってやつですね
Avatar
omochimetaru 7/14/2018 1:50 PM
確率的に処理時間が伸びちゃうけどレアケースだから問題ないわな、っていって
1:50 PM
mergeされてるけど
1:50 PM
これって @t.ae が作ってたような
1:50 PM
狂ったRNGのときに
1:50 PM
無限ループしね?
Avatar
そこのテストケースについてもプルリクで話してましたね
Avatar
omochimetaru 7/14/2018 1:51 PM
ん、どれだ
Avatar
コードレビューのどこかにあったはず
Avatar
omochimetaru 7/14/2018 1:52 PM
ああインラインレビューか
Avatar
あれ?見つからないな……
1:52 PM
ああふつうに最後にかいてあった
Avatar
omochimetaru 7/14/2018 1:53 PM
Yeah, that is a concern, though it won't happen with non-pathological RNGs =) Maybe for the test use an RNG that instead generates [.min, .max, basic LCG sequence ...].
1:53 PM
RNGとしてはナンセンスだから気にしなくていいって?
Avatar
そうですね。実際テストケースが詰まるので固定のシーケンスを生成するRNGもどきにしたということみたいです
Avatar
omochimetaru 7/14/2018 1:53 PM
う〜〜〜〜〜〜〜〜ん・・・・・・・・・・
1:54 PM
プラクティカルだ・・・
1:54 PM
乱数モジュールの事考えてるときは数理的な発想になるから違和感あるけどまあそうか・・・
Avatar
内部的に複数回乱数引くことがあるので100回max生成してその後はランダム〜みたいなのが良いようにも思えますね
Avatar
norio_nomura 7/14/2018 8:04 PM
Never as bottom になったの? https://twitter.com/mdiep/status/1018159704818831360
SE-0215, Conform Never to Equatable and Hashable, has been accepted! 🎉 https://t.co/zBneV1oWiZ The core team also concluded: 1. Never should also conform to Error and Comparable 2. Never should become a blessed bottom type Exactly the resolution I hope...
Avatar
お、bottomになったならうれしいですね!
Avatar
↑絡みかunwrap or dieがrejectされましたね https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/222
Proposal rejected The core team has decided to reject this proposal as written. However, the core team concurs that the motivating problems posed by the proposal are important to solve, as did an overwhelming majority of commenters who participated in the public review. The f...
Avatar
言及されてますね。
Meanwhile, elsewhere in swift-evolution, the core team has also accepted SE-0215 — Conform Never to Equatable and Hashable 9, and came out of that discussion strongly in favor of investigating making Never be a subtype of every other type. This requires its own design cycle, but it fills in a general gap in the type system, and would enable the idiom x ?? fatalError("message") without any additions to the standard library.
Avatar
↓の方法、 Base が値型だとオーバーヘッド大きそう。 struct Extension<Base> { let base: Base init (_ base: Base) { self.base = base } } protocol ExtensionCompatible { associatedtype Compatible static var ex: Extension<Compatible>.Type { get } var ex: Extension<Compatible> { get } } extension ExtensionCompatible { static var ex: Extension<Self>.Type { return Extension<Self>.self } var ex: Extension<Self> { return Extension(self) } } https://qiita.com/motokiee/items/e8f07c11b88d692b2cc5

Extensionをモダンでオシャレにしたい

この記事の結論を先に書いておくと、 UIColor.yamabuki のように書いているExtensionを以下のようにオシャレに書くことができる、と...
6:04 AM
↓ここで毎回コピーが走る。 var ex: Extension<Self> { return Extension(self) }
Avatar
Kishikawa Katsumi 7/25/2018 6:07 AM
気にするようなオーバーヘッドあるかな。まあ使い方によるわけですけれど。
Avatar
omochimetaru 7/25/2018 6:07 AM
これってまさにこの前の read property を使えば
6:07 AM
コピーを回避できるパターンじゃないかしら
6:11 AM
いや、無理か・・・
Avatar
これ値型でやろうとすると結構大変になる
6:11 AM
そもそもfoo.exを生やすだけで大変
Avatar
@Kishikawa Katsumi もしプロパティが 10 個あってそれぞれ 8 バイトだとしたら、 foo.ex.bar ってやるだけで 80 バイトのコピーが走るってことですよね?
6:13 AM
@tarunon 拡張の仕方自体に値型で大変な点ありますっけ? set しようとしたら大変ですが。
Avatar
Kishikawa Katsumi 7/25/2018 6:13 AM
特に気にするようなオーバーヘッドじゃないと思いますね。私が普段書いてるプログラムでは。
Avatar
classでこれやるのって現実的にはBaseClass一括になるんですが
6:14 AM
値型だとそうはいかないので一個ずつ定義する必要が出てきてあんまり嬉しくないになりがちな感じです
6:15 AM
extension Foo: ExCompatibleを必要な全てのstructに一つずつ書いていくことに
Avatar
@Kishikawa Katsumi ボタン一回押したらそれが数回呼ばれるとかだと問題にならないですね。リアルタイム性が重要なアプリで、ループの中で呼ぶとかだと辛そうです。
Avatar
Kishikawa Katsumi 7/25/2018 6:15 AM
そういうことはあると思います。
Avatar
omochimetaru 7/25/2018 6:16 AM
extension Foo: ExCompatibleを必要な全てのstructに一つずつ書いていくことに
それが大変とは思わなかったw
6:16 AM
ようするに対応する事を型ごとに表明するだけだよね、必然的なコストでは・・・?
Avatar
@tarunon Conditional Conformance でどうにかできたりしないですか?(コード書いてないので自信ないですが・・・) (edited)
Avatar
omochimetaru 7/25/2018 6:16 AM
@koher Conditionalに書けるってことは、そのConditionの起点になるProtocolへのconformanceは結局必要になるはずなので、手数が同じに思います
Avatar
@omochimetaru@tarunon さんが話してるのは BaseClass があるパターンなので、値型に対してもバラバラに記述しないといけないケースをプロトコルでどうにかならないかなと。
Avatar
ならないっす
Avatar
Kishikawa Katsumi 7/25/2018 6:18 AM
ただ、基本的にこういう類のパフォーマンスがどれだけ影響するかは自明ではないし、優先度としては一般的に高くないはずです。
Avatar
IntX UIntX String StaticString ... と書いてるとウーンって感じになるし流石に用途ごとに全部やるのは
Avatar
omochimetaru 7/25/2018 6:19 AM
@koher @tarunon BaseClassを指定するのと、Foo: ExComaptible するのと、 共通のProtocolを置くのって、どれも同じことじゃないですか?
Avatar
extension メソッドの実装じゃなくて、 conform の話をしてるのか。
Avatar
omochimetaru 7/25/2018 6:20 AM
実際のexntensionする内容に関しては、 全く異なる型ならそもそも拡張で提供できる機能も全く異なるはずだし
6:20 AM
そこに共通性があるならその共通性はProtocolで、拡張する前に宣言できるはずなので
6:21 AM
特に値型ゆえに面倒になっている理由になっていないように聞こえます。
Avatar
protocolのベースを後付けで増やせないから、classの時のやり方とは違う方法を考えた方が良い、が正しそう
Avatar
omochimetaru 7/25/2018 6:23 AM
protocol P0 で使える .ex.<hogehoge for P0> と protocol P1 で使える .ex.<fugafuga for P1> が
6:24 AM
struct STone: P0, P1 {} の場合に両方使えるようにするのがむずい、みたいな事? (edited)
6:25 AM
それは大丈夫そうだな。 extension Reactive where Base : P0 { ... } extension Reactive where Base : P1 { ... }
Avatar
パフォーマンスについてはこちらの記事に書いてありますね: https://tech.starttoday-tech.com/entry/swift_modern_extensions まあそれほど気にするようなオーバーヘッドはないかと思います;NotAutoLayoutもこれ大量に使ってますがそれでもAuto Layout使わないライブラリーの中でも最速ですし() https://github.com/layoutBox/LayoutFrameworkBenchmark
VASILYのiOSエンジニアにこらすです。最近、Swift Evolutionに私の2つ目の提案がマージされました。 今回は、Swiftで型にExtensionを作る特殊な方法について説明します。 今回紹介する方法を使ってExtensionを作ると...
LayoutFrameworkBenchmark - Benchmark the performances of various Swift layout frameworks (autolayout, UIStackView, PinLayout, LayoutKit, FlexLayout, Yoga, ...)
👍 1
Avatar
omochimetaru 7/25/2018 9:31 AM
レイアウトライブラリの内部だと、オブジェクトの数やループする数が、たかだか画面コンポーネントの数なので、影響は感じ無さそうです
Avatar
僕が作っている Image 型とかで、ピクセル単位でループしてたりするとちょっと許容できなさそうですね。 (edited)
9:38 AM
あと、↑のリンク先の Example<Base>class になってますが、これは struct でないとパフォーマンス的によりまずい気がします(ヒープに確保されるので)。 (edited)
9:44 AM
こっちでもベンチマークとってみたら、参照型でも ex. だとずいぶん遅くなって謎・・・。何か間違ってんのかなぁ。
9:45 AM
あと、 : ExtensionConvertible するだけだと -c release でも ex が特殊化されてないみたいで、 ex_ に比べて数十倍遅くなってしまった・・・。
9:46 AM
あえて個々の extensionex の実装を書き下すと(おそらく) Extension が特殊化されて数倍の遅さ程度になった。
9:50 AM
色々謎だけどとりあえずリポジトリ公開しました。 https://github.com/koher/ExPerformance
Contribute to ExPerformance development by creating an account on GitHub.
9:51 AM
FoostructBarclass
9:51 AM
テストで measure してるので swift test -c release で実行。
Avatar
Generics、関数はSpecializeされるけど型はSpecializeされない、、ですよね?
9:58 AM
もうされるようになった?
9:58 AM
だからEx<T>はどうやってもオーバーヘッド出ると思います
9:59 AM
無視できるかはさておき
Avatar
型っていうかストレージはされないっぽいね
Avatar
Swift 4.2で@inlinableとか使うとtestFooDirecttestFooExampleは同等になった。 public struct Example<Base> { @usableFromInline let base: Base @inlinable public init(_ base: Base) { self.base = base } } public protocol ExampleCompatible { associatedtype CompatibleType var ex: CompatibleType { get } } extension ExampleCompatible { @inlinable public var ex: Example<Self> { return Example(self) } } extension Foo { @inlinable public var ex_ab: Int { return a + b } } extension Example where Base == Foo { @inlinable public var ab: Int { return base.a + base.b } } (edited)
10:30 AM
testBarExample@inlinableを色々つけてもtestBarDirectより10倍くらい遅い。
Avatar
https://github.com/apple/swift/blob/e9cb62d4/stdlib/public/SwiftOnoneSupport/SwiftOnoneSupport.swift#L159-L173 型が specialize されないっていうのと、これの関係が気になる。
swift - The Swift Programming Language
Avatar
ああ、public final class BarにしたらtestBarExampletestBarDirectも同等になった。 (edited)
Avatar
@_specializeでspecialize実装を生成しておくよりも@inlinableを活用すべき、という理解で合ってるのかな?
Avatar
私の理解が正しければinline化とspecializeはゴールが違っていてこの場合は特別な例で近いゴールになってるだけ、な気がする
1:34 PM
あー、、、仮にEx<T>に生えたメソッド群がインライン化可能なら、オーバーヘッドを無くせる可能性が出てきますね
Avatar
少し試した限りでは@inlinableはかなり有効ですね。
Avatar
final でないクラスで遅くなるのは、 ex の呼び出しと ex の持つ self 経由での呼び出しとで 2 回動的ディスパッチが走るからでしょうか?で、 final にすると両方静的ディスパッチになるので速くなる。 (edited)
Avatar
Ex<T>のTに制約かけて何かやってるとそこが動的になるはず
2:19 AM
exそのものの呼び出しは動的にならない気がする、直感的には
Avatar
Barfinal でなかったら、 bar.ex が動的ですよね。
2:19 AM
exself を呼び出すところは特殊化できないなら動的になって、
2:20 AM
さらに self.ab するところが動的か静的か。
Avatar
どういう記述になってるかによりそうですが
2:21 AM
そもそもextensionに記述したものはoverrideできない(3まではできた)なので
2:21 AM
少し違う気がしています
Avatar
let bar = Bar() var sum = 0 for _ in 0..<N { sum += bar.ex.ab }
Avatar
静的に型検査されたEx<Base>になるはず
2:21 AM
コンパイル時の型のExになる
2:21 AM
少なくともRxSwiftはそうです
Avatar
あー、 abExtension だからオーバーライドできないことが保証されて静的になるってことですね。
Avatar
そう
Avatar
そうすると、↑の final 付けるかどうかの差は、 ex 関係なくて単に bar.ex が動的/静的ディスパッチになっているかの差?
2:23 AM
それなら、 bar.ex_ab のときも速くなりそう。 (edited)
Avatar
norio_nomura 7/26/2018 2:24 AM
静的になる != inline化される、では無いと思う。実際、 extension Example where Base == Bar { @inlinable public var ab: Int { return base.a + base.b } }@inlinable有無で速度が違うし。
Avatar
こっちはinline化された結果、exの存在が無かったことになると思っていて
Avatar
そのインライン化ってコンパイラが勝手に最適化してくれるイメージだったんですが、 @inlineable がないとインライン化されないんでしょうか?
Avatar
その最適化が可能ならオーバーヘッドがほぼ無くなりそうだなと
2:25 AM
インライン化は明示しないと基本やってくれないと思います
Avatar
norio_nomura 7/26/2018 2:25 AM
モジュール内で使う限りは勝手にインライン化されるんじゃ無いかな?
Avatar
あー、今モジュールを超えてるからか。
Avatar
モジュールの内外で違う
2:26 AM
のか
Avatar
omochimetaru 7/26/2018 2:26 AM
@inlineable はモジュールをまたいでインライン化可能できるようにする指定子
2:26 AM
これを指定するとコンパイル後のバイナリにASTが埋め込まれる
2:26 AM
そうしないとインライン化できないから。
Avatar
確かに呼び出しはテスト側だからモジュールまたいでた。
Avatar
omochimetaru 7/26/2018 2:26 AM
デメリットとしてバイナリサイズが肥大する。
Avatar
norio_nomura 7/26/2018 2:26 AM
ExPerformanceでは別モジュールのExPerformanceTestsで使ってるから。
Avatar
でもまあ現実的に計測するならモジュールまたぎの方が
Avatar
コンパイル後のバイナリにASTが埋め込まれる
僕の理解では swiftmodule に SIL 実装が埋め込まれる です。
👍 1
Avatar
実態に近いですよね
Avatar
@tarunon
その最適化が可能ならオーバーヘッドがほぼ無くなりそうだなと
インライン化できたとしても、 Example<T>self への代入によるコピーコストまでなかったことにはならない気がするんですよねぇ。
Avatar
omochimetaru 7/26/2018 2:27 AM
SILか。(ちゃんと確認してないです) (edited)
Avatar
Exの参照なければ生成しない、までアグレッシブにできない、できないか
2:29 AM
副作用無しを保証する指定子みたいなのが出てくると、できることが増えそう
Avatar
↓の二段を解釈してコピーを省略するのはハードルが高そう・・・。 extension Foo: ExampleCompatible { public var ex: Example<Foo> { return Example(self) } } extension Example where Base == Foo { public var ab: Int { return base.a + base.b } }
2:33 AM
同じ領域参照するにしても、 Example<T> が値を保持してるのを参照にしなきゃいけないし。 @nonescaping 的な、即時解放されることが保証されてればコピー省略できるのかなぁ。
Avatar
omochimetaru 7/26/2018 2:33 AM
LLVM-IRを見てみるのが良いのでは モジュール跨ぎの状況を生コマンドで構築するのはちょっと大変だけど
Avatar
norio_nomura 7/26/2018 2:35 AM
とりあえず、@inlinablefinalを活用してのExPerformanceTestsのmeasuredはこんな感じ。 …testBarDirect]' measured [Time, seconds] average: 0.009, … …testBarExample]' measured [Time, seconds] average: 0.010, … …testFooDirect]' measured [Time, seconds] average: 0.004, … …testFooExample]' measured [Time, seconds] average: 0.004, … (edited)
2:37 AM
活用前: …testBarDirect]' measured [Time, seconds] average: 0.018, … …testBarExample]' measured [Time, seconds] average: 0.614, … …testFooDirect]' measured [Time, seconds] average: 0.024, … …testFooExample]' measured [Time, seconds] average: 0.767, …
Avatar
なんでコピーコストがないんだろう。無視できるほど小さいのかなぁ。 80 バイトあるんだけどなぁ。
2:38 AM
ジェネリック型変数が特殊化されないとすると、 existential みたいにある程度以上大きな値は COW バッファーになってる?
2:43 AM
bot で -emit-ir できるんだっけ? @swiftbot -O -emit-ir (edited)
🛠 1
Avatar
swiftbot BOT 7/26/2018 2:43 AM
(edited)
Author icon
koher
let N = 10_000_000 public struct Example<Base> { let base: Base public init(_ base: Base) { self.base = base } } public protocol ExampleCompatible { associatedtype CompatibleType var ex: CompatibleType { get } } extension ExampleCompatible { public var ex: Example<Self> { return Example(self) } } public struct Foo { public var a: Int = 1 public var b: Int = 2 public var c: Int = 3 public var d: Int = 4 public var e: Int = 5 public var f: Int = 6 public var g: Int = 7 public var h: Int = 8 public var i: Int = 9 public var j: Int = 10 public init() {} } extension Foo { public var ex_ab: Int { return a + b } } extension Foo: ExampleCompatible { public var ex: Example<Foo> { return Example(self) } } extension Example where Base == Foo { public var ab: Int { return base.a + base.b } } let foo = Foo() var sum = 0 for _ in 0..<N { sum += foo.ex.ab } print(foo)
Version:
swift-4.1.1-RELEASE
Output:
Foo(a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10)
Error:
Avatar
omochimetaru 7/26/2018 2:45 AM
#swift に例があります
Avatar
@swift-4.1.3 -O -emit-ir let N = 10_000_000 public struct Example<Base> { let base: Base public init(_ base: Base) { self.base = base } } public protocol ExampleCompatible { associatedtype CompatibleType var ex: CompatibleType { get } } extension ExampleCompatible { public var ex: Example<Self> { return Example(self) } } public struct Foo { public var a: Int = 1 public var b: Int = 2 public var c: Int = 3 public var d: Int = 4 public var e: Int = 5 public var f: Int = 6 public var g: Int = 7 public var h: Int = 8 public var i: Int = 9 public var j: Int = 10 public init() {} } extension Foo { public var ex_ab: Int { return a + b } } extension Foo: ExampleCompatible { public var ex: Example<Foo> { return Example(self) } } extension Example where Base == Foo { public var ab: Int { return base.a + base.b } } let foo = Foo() var sum = 0 for _ in 0..<N { sum += foo.ex.ab } print(foo)
Avatar
exit status: 1 with stderr:<unknown>:0: error: option '-emit-ir' is not supported by 'swift'; did you mean to use 'swiftc'?
Avatar
norio_nomura 7/26/2018 2:48 AM
swiftcではなくswiftなので、-Xfrontend -emit-irを使ってください。 (edited)
🙏 1
Avatar
@omochimetaru
レイアウトライブラリの内部だと、オブジェクトの数やループする数が、たかだか画面コンポーネントの数なので、影響は感じ無さそうです
NotAutoLayout内部の話になると、nal の度にインスタンス作ってるだけでなく、何かを設定するときも大量にインスタンス作ってます、例えばサンプルコード出してみると self.nal.layout(self.viewA) { $0 .setTopCenter(by: { $0.topCenter }) .setWidth(by: { $0.width }) .fitHeight() } 上記画面コンポーネントは viewA だけだけど、作ったインスタンスは nal $0 .setTopCenter $0.topCenter setWidth $0.width .fitHeight の7つあります
Avatar
omochimetaru 7/26/2018 3:16 AM
@lovee viewAに対してたかだか10倍程度ですよね、 僕がイメージしてる「たくさん」は、 ゲームコンテンツなどでワールドに3Dオブジェクトが500個程度描画されていて、 それぞれの姿勢行列 Matrix4x4 に対して、 回転制御を行うためのクォータニオン変換などの計算ユーティリティが、 このextensionで書かれていたら、みたいなオーダーです。 これを毎フレームの16ms以内に完了しないといけない。 (edited)
Avatar
そこまでいくと「たくさん」の定義は違って来ますね 😇
Avatar
omochimetaru 7/26/2018 3:17 AM
このときに、 Reactive(base: self) で Base == Matrix4x4 なら 32bit floatが16個になるので
3:17 AM
コピーコストも大きそうです。
Avatar
classでMatrix4x4を包むしかなさそう 🤔
Avatar
omochimetaru 7/26/2018 3:20 AM
.ex形式にしないで 直接extensionを書けば良いと思います。 まあ、今の会話の流れだと、それでもinline化によってコピーが回避されてる説が出てきましたが。
Avatar
試してみたいですねinline化
Avatar
omochimetaru 7/26/2018 3:22 AM
今ちょっと忙しいので後でIR見てみようと思ってます
Avatar
:sasuga:
Avatar
@swift-4.1.3 -O -Xfrontend -emit-ir let N = 10_000_000 public struct Example<Base> { let base: Base public init(_ base: Base) { self.base = base } } public protocol ExampleCompatible { associatedtype CompatibleType var ex: CompatibleType { get } } extension ExampleCompatible { public var ex: Example<Self> { return Example(self) } } public struct Foo { public var a: Int = 1 public var b: Int = 2 public var c: Int = 3 public var d: Int = 4 public var e: Int = 5 public var f: Int = 6 public var g: Int = 7 public var h: Int = 8 public var i: Int = 9 public var j: Int = 10 public init() {} } extension Foo { public var ex_ab: Int { return a + b } } extension Foo: ExampleCompatible { public var ex: Example<Foo> { return Example(self) } } extension Example where Base == Foo { public var ab: Int { return base.a + base.b } } let foo = Foo() var sum = 0 for _ in 0..<N { sum += foo.ex.ab } print(foo)
Avatar
; ModuleID = '-' source_filename = "-" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" %TSi = type <{ i64 }> %T4main3FooV = type <{ %TSi, %TSi, %TSi, %TSi, %TSi, %TSi, %TSi, %TSi, %TSi, %TSi }> %swift.type = type { i64 } %swift.protocol = type { i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i32, i32, i16, i16, i32 } %swift.refcounted = type { %swift.type*, i64 } %swift.full_boxmetadata = type { void (%swift.refcounted*)*, i8**, %swift.type, i32, i8* } %swift.opaque = type opaque %swift.type_pattern = type opaque %swift.protocol_requirement = type { i32, i32 } %swift.protocol_conformance = type { i32, i32, i32, i32 } %swift.type_metadata_record = type { i32, i32 } %Ts27_ContiguousArrayStorageBaseC = type <{ %swift.refcounted, %Ts10_ArrayBodyV }> %Ts10_ArrayBodyV = type <{ %TSC22_SwiftArrayBodyStorageV }> %TSC22_SwiftArrayBodyStorageV = type <{ %TSi, %TSu }> %TSu = type <{ i64 }> %T4main7ExampleV = type <{}> %T4main7ExampleV.2 = type <{}> %T4main7ExampleVyAA3FooVG = type <{ %T4main3FooV }> @_T04main1NSivp = hidden local_unnamed_addr global %TSi zeroinitializer, align 8 @_T04main3fooAA3FooVvp = hidden local_unnamed_addr global %T4main3FooV zeroinitializer, align 16 @_T04main3sumSivp = hidden local_unnamed_addr global %TSi zeroinitializer, align 8 @_T0s23_ContiguousArrayStorageCyypGML = linkonce_odr hidden local_unnamed_addr global %swift.type* null, align 8 @_T0ypML = linkonce_odr hidden local_unnamed_addr global %swift.type* null, align 8 @_swift_getExistentialTypeMetadata = external local_unnamed_addr global %swift.type* (i1, %swift.type*, i64, %swift.protocol**)* @_swift_allocObject = external local_unnamed_addr global %swift.refcounted* (%swift.type*, i64, i64)* @_T0s27_ContiguousArrayStorageBaseC16countAndCapacitys01_B4BodyVvpWvd = external local_unnamed_addr global i64, align 8 @0 = private constant [11 x i8] c"4main3FooV\00", section "swift3_typeref" @"\01l__swift3_reflection_descriptor" = private constan
Avatar
なんか手元でやったのと結果が違うと思ったら Linux だからか。
Avatar
$ swift demangle S4main7ExampleVA2A3FooVRszlE2abSivg $S4main7ExampleVA2A3FooVRszlE2abSivg ---> (extension in main):main.Example<A where A == main.Foo>.ab.getter : Swift.Int
4:05 AM
swiftc -O -emit-ir main.swift | grep S4main7ExampleVA2A3FooVRszlE2abSivg するととんでもなく長い行が出てくる😭
Avatar
omochimetaru 7/27/2018 5:02 AM
Enables local refactoring on a class declaration to generate member wise initializer Resolves SR-7292.
5:02 AM
これXcode10で使えると良いな
Avatar
4.2 に今から入れるのは無理だと思います。残念。
😣 1
Avatar
@rintaro もしかして↓も 4.2 に入らないんでしょうか? https://github.com/apple/swift-evolution/blob/master/proposals/0216-dynamic-callable.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
5:06 AM
SE-0195 だけ入って SE-0216 は入らないとか辛い気が・・・。
Avatar
https://swift.org/blog/4-2-release-process/ によると、April 20 の final branching 以降は
After the final branch date there will be a “bake” period in which only select, critical fixes will go into the release (via pull requests).
This post describes the goals, release process, and estimated schedule for Swift 4.2.
🙏 1
Avatar
なるほど。 SE-0216 は Chris Lattner 肝いりだし、 Swift for TensorFlow との兼ね合いでも早く入れたいだろうし、入ると期待したいですね・・・。
5:10 AM
まだマージもされてないですが・・・。
Avatar
struct Foo { init?(...) } これの時に、左辺の型がFoo?の場合に右辺を.initで型省略できないの、仕方ないとは理解しつつも感情が受け付けない
Avatar
omochimetaru 8/2/2018 6:37 AM
それ不便だよね
Avatar
vicktorManuel 8/5/2018 3:42 PM
you can only public struct Foo { public var j: Int ! ............... --------- }
Avatar
https://github.com/apple/swift/pull/18579 これは嬉しい!インターフェイスでデフォルト値が default じゃなくてきちんと表示されるようになります。
This allows us to dump it in the generated interface, though it's still not syntax-highlighted. This is necessary for textual module interfaces, but it's also just a longstanding request fo...
❤ 1
Avatar
omochimetaru 8/9/2018 7:16 AM
おお
7:22 AM
diff眺めたのですけど、 struct StoredDefaultArgument { Expr *DefaultArg = nullptr; Initializer *InitContext = nullptr; StringRef StringRepresentation; };
Avatar
nilとか参照先のフィールドも出るようになる感じでしょうか
Avatar
omochimetaru 8/9/2018 7:23 AM
基本これだけですか?
7:23 AM
Parse/ParsePattern.cppでもソースレンジを渡してるだけだから、本当にそのまま・・・
Avatar
Kishikawa Katsumi 8/9/2018 7:24 AM
これはとても嬉しいですね。
Avatar
Swift4あたりから、デフォルト引数の中でプライベートな値が使えなくなったので、単純なソーステキストのコピーで問題ないという判断でしょうね。
Avatar
omochimetaru 8/9/2018 7:27 AM
なるほど?なんか変なことになるケースが無いか考えてるんですけど思いつかないし大丈夫なのか。 たしかにプライベートコンテキストだった時代だと変な事にもなるけど・・・
Avatar
#swift-zatsu で話してた件ですが、capture で別名つける方法がいけるか?と思ってやったら予想外の結果に。 class Example { func test() { let f = { [weak weakSelf = self] in guard let `self` = weakSelf else { return } // Set a breakpoint at here print(self) } f() } } Example().test() 今度は謎の結果に… (lldb) po self error: <EXPR>:3:1: error: use of unresolved identifier 'self' self ^~~~ (lldb) fr var (@lvalue example.Example?) weakSelf = 0x00000001009002b0 (example.Example) self = 0x00000001009002b0 {}
8:32 AM
とりあえず、self という名前での変数宣言をやめましょうということですね…
8:32 AM
昔採用していた guard let this = self else { return } は案外賢かったのかもしれない… (edited)
Avatar
( Swift の話が 4 本並行してしまった・・・。)
8:39 AM
僕は zelf 派ですが、あまり zelf の人いないですね・・・。
Avatar
omochimetaru 8/9/2018 8:39 AM
僕は wselfsselfuself (edited)
Avatar
Kishikawa Katsumi 8/9/2018 8:39 AM
私はthis/me/self/stringSelfその他どれも微妙だと思っていて、
👀 1
8:39 AM
pageControl.rx.controlEvent(.valueChanged) .subscribe(onNext: { [weak self] in guard let currentPage = self?.pageControl.currentPage else { return } guard let contentOffset = self?.scrollView.contentOffset else { return } guard let currentIndex = self?.currentIndex else { return } ...
😃 1
Avatar
みんなばらばら😭
Avatar
Kishikawa Katsumi 8/9/2018 8:40 AM
^ みたいにselfの先の必要なプロパティを個別にguardでとることが多いですね。
Avatar
これ、本質的な問題は LLDB でやりづらいってだけなので、LLDB 直す方向でいきたいですね…
Avatar
Kishikawa Katsumi 8/9/2018 8:40 AM
ちなみにこれはだいぶ極端な例。
Avatar
そうすれば、 self 派も weakSelf capture 派も救われる…
Avatar
omochimetaru 8/9/2018 8:41 AM
@Kuniwak 僕が self の再定義をしないのは、デバッグは関係なくて、
8:41 AM
self に再定義したそのスコープでさらにクロージャーを作るときに
Avatar
@Kishikawa Katsumi self?. 方式だと、 self によらない処理が書かれていると self が解放されていてもそれが走ってしまいませんか?
Avatar
omochimetaru 8/9/2018 8:41 AM
[weak self] を書き忘れた場合などで、 self が強なのか弱なのかゴチャゴチャしてくるからです
8:42 AM
正しくは、弱でキャプチャして、冒頭で強にリバインドですが、 「弱でキャプチャして冒頭で強にリバインド」を、まるまる忘れちゃって、そのまま強でキャプチャするミスが
8:42 AM
見た目にわかりづらいと思っています
Avatar
@omochimetaru うーん、なるほど…?個人的には capture で別名を基本として Lint で検査が健全な感じします
Avatar
omochimetaru 8/9/2018 8:43 AM
ミスによるデフォルトでの強のキャプチャを機械で防ぐんですね、なるほど、それなら僕の指摘は回避できそう。
Avatar
Kishikawa Katsumi 8/9/2018 8:43 AM
self が解放されていてもそれが走ってしまいませんか?
これは私が今書いてるコードだと別にOKですね。
8:44 AM
困る場合はさっきのやり方で早期リターン。
Avatar
うーん、Swift でましな Lint を実装したいという気持ちがずっとあるんですが、なかなか手をつけられない
Avatar
OK なケースがほとんどだと思いますが、解放されているときはクロージャが実行されないことを明確化するために冒頭で return したいような・・・。
Avatar
Kishikawa Katsumi 8/9/2018 8:47 AM
{ [weak self] in self?.titleLabel.alpha = 0 self?.titleLabel.transform = CGAffineTransform(translationX: 0, y: labelHeight) } こういう場合はいちいちguard書くよりはself?.の方が私はいいんじゃないかと思います。
😃 1
Avatar
その例はやばいですね。これだったら guard を上で羅列した方が見通しがいいです
Avatar
omochimetaru 8/9/2018 8:47 AM
2文までは↑僕もそう書いてます、3文になるとguard let sself したくなります
😃 1
Avatar
ちなみに、別スレッドで reference count が 0 になって、あるスレッドの途中で解放されるケースとかってあるんでしょうか?
8:48 AM
参照型を複数のスレッドで共有しているケースを想定しています
😲 1
Avatar
omochimetaru 8/9/2018 8:49 AM
どういうことですか?どこかのスレッドで = nil されて 0 になれば、そのスレッドで deinit されますよ。
Avatar
↑の例で self?.titleLabel.alpha = 0 のときは生きてるけど self?.titleLabel.transform = ... では死んでることがあり得るかということですよね?
👌 1
Avatar
omochimetaru 8/9/2018 8:50 AM
ありえますね。
😲 1
Avatar
Kishikawa Katsumi 8/9/2018 8:50 AM
ありえますね。
😲 1
Avatar
そうですよね、だとすると guard let 羅列は途中に処理を挟むと稀に変な状況が発生するという辛いバグがありそう…
👍 1
Avatar
逆に、盲目的に冒頭で guard let していると、途中で解放されたときにそのクロージャからのみキャプチャされている状態になって、それで変なことになることがないかなというのが前から少し気になってました。
👍 1
Avatar
omochimetaru 8/9/2018 8:53 AM
まあそうですけど、ViewControllerであれば、少なくともUIKit側からのretainの切断がメインスレッドでしかおこりえないので、さっきみたいなクロージャーがメインスレッドで実行される限り、実際のところそのパターンは生じない、って考えてます
🦀 1
👍 1
Avatar
私はよく Model 層のやつでも weak self してたので、この場合はなるべく guard let xxx = self は一箇所でまとめてやりたいですね
8:57 AM
とりあえず、LLDB で再宣言 self が死ぬ問題の修正に向けてアップを始めたい…(あと Swift の Lint つくりたい…)
Avatar
(なるほどー👏
Avatar
そも論ですが成る可くselfキャプチャを作らないようにはしている
Avatar
うーん、なるほど。self キャプチャを作らない方法、思いつくのは Monad 的な purely functional なアプローチなのですが、それであっていますか? (edited)
Avatar
ベースはRACなのであってそうです。 (edited)
Avatar
昨日の話の続きで思ったんですが、 self に限らず weak キャプチャしたオブジェクトが異なるスレッドで解放される可能性がある場合、リファレンスカウントの減少から deinit の実行までは排他的でもアトミックでもないと思うんですが、そうすると weak キャプチャしてる側で常にぶっ壊れる可能性がないですか?異なるスレッドからの解放はそもそもやっちゃいけない?
3:37 AM
たとえば、 self?.foo() を呼び出したときに、 self のリファレンスカウントをチェックしたときは 1 だったけど、 foo が呼ばれる前に別スレッドから self が解放されてしまったとか。
3:38 AM
冒頭で guard let self = self else { return } してると一見安全そうだけど、この場合でもリファレンスカウントのチェックから代入してリファレンスカウント増やすまでの間に別スレッドから解放されてしまうおそれがありそう。 (edited)
Avatar
omochimetaru 8/10/2018 3:38 AM
self?.foo() は fooを呼び出す前に self を retain するはずです
3:39 AM
チェックして増やすところがアトミックなはず。
3:40 AM
弱参照から強参照を取り出す操作ですね
Avatar
チェックして増やすところがアトミックなはず。
これはコンパイラを見ればわかる?ドキュメントに記載されてるっけ?
Avatar
omochimetaru 8/10/2018 3:40 AM
確実にわかるのはそのへんはランタイム関数になってるからソース読めばわかりますね
Avatar
それが行われるのは weak の場合のみ?それとも ?. 全般?
Avatar
omochimetaru 8/10/2018 3:43 AM
strongの ?. は その strong が生きてるので + 1 はいらんですね
Avatar
strong は要らなさそうだけど、 var foo: Foo? = Foo()foo が、 foo?.bar() を呼んでいる間に別スレッドから nil にされてしまう場合とかありそう。
3:44 AM
実用上そういうケースはほぼないだろうけど、これは明確にやってはいけないことなのかどうか。
3:45 AM
バランス的にはほとんどのケースで無駄だろうから、 strong のときは増減してなさそうだけど。
Avatar
omochimetaru 8/10/2018 3:45 AM
あー、それは昔はあったので、+1しているかもしれない
3:45 AM
いまは LoE で禁止されるはず
Avatar
てか、 ?. に限らない? foo.bar() でも foo が書き換えられてインスタンスが解放されることはあり得る?
Avatar
omochimetaru 8/10/2018 3:46 AM
fooという変数それ自体へのアクセスが排他されていて、メソッド呼び出しはreadアクセスです
3:48 AM
こういうのかな
3:48 AM
do while で CAS ロックしてますね
3:48 AM
下請けは C++ の std::atomic です
3:49 AM
実は2017年の2月に参照カウンタの実装がガッツリ変更されていて、前見たときと実装が変わってた(本論とは無関係) (edited)
Avatar
だめだ C++ 力が足りなくて読めない・・・
3:58 AM
いまは LoE で禁止されるはず
↓こういうのはどう? import Dispatch class Foo { func bar() {} } var foo: Foo? = Foo() func a() { foo?.bar() foo = nil } func b() { foo?.bar() foo = nil } DispatchQueue.global(qos: .default).async { a() } DispatchQueue.global(qos: .default).async { b() }
3:59 AM
strong だけどリファレンスカウント増やさないと死ぬケースがありそう。
Avatar
omochimetaru 8/10/2018 3:59 AM
let old = refCount() let new do { if (checkZero) { return } new = old + 1 } while ( CAS (old, new) ) ↑シンプルにこういう形ですよ (edited)
4:00 AM
CASロックループです
4:04 AM
あー
4:04 AM
参照型の変数はメソッド呼び出し中はアクセスじゃないのか
4:04 AM
+1されてそうな気がしてきました
Avatar
↓の oldbits は参照なのか。 auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME);
Avatar
コピーだと何を排他しているの?
4:11 AM
最も重要なのは、コンペア・アンド・スワップ(Compare and swap, CASと省略する)である。
Avatar
えっと、コピーだとそもそも何が共有されてるのかという質問でした。
Avatar
omochimetaru 8/10/2018 4:14 AM
質問文の意味がわからないです、CASの基本イディオムを知らなくて話が通じていない気がしたので↑を貼った
4:15 AM
↑のwikipediaのATMの例が
4:15 AM
そのまんままさに同じアルゴリズムです
4:15 AM
通帳の残高の代わりに参照カウンタを1増やしている (edited)
Avatar
えっと、 oldbitsnewbits が値だったら関数ローカルな存在でどことも共有されてないのでそもそも排他する必要がなくないということなんだけど、それ自体は値だけど中にポインタか参照を持ってるのかな?
Avatar
omochimetaru 8/10/2018 4:23 AM
tryIncrement は 関数じゃなくて メソッドで template <typename RefCountBits> class RefCounts { std::atomic<RefCountBits> refCounts; ... } (edited)
4:24 AM
参照型のオブジェクトはこの RefCounts をフィールドとして持っているので
4:24 AM
このRefCountsを保持しているオブジェクト自体がスレッド間共有されています (edited)
4:25 AM
oldbitsとnewbitsの型は RefCountBits だけどこれは RefCounts テンプレートクラスの型パラメーターで
4:25 AM
厳密にはポインタになったりもするんですけど、値だと思えば良いです
Avatar
でも oldbitsnewbits は値型の関数ローカルの変数で、そこに書き戻したのがどうやってオブジェクトが保持している RefCounts に反映されてるの? (edited)
Avatar
omochimetaru 8/10/2018 4:27 AM
while (!refCounts.compare_exchange_weak(oldbits, newbits, std::memory_order_relaxed)); ↑ここのCASで書き戻してる
4:28 AM
refCountsはRefCounts<RefCountBits>型が持っている std::atomic<RefCountBits>型のフィールドです。 (edited)
Avatar
refCountsoldBits を比較してるのか。
Avatar
やっとわかりました。 compare_exchange_weak が副作用のあるメソッドだとわかってなかった。
4:36 AM
引数を参照でとって下記戻すのかと思ってた。
4:37 AM
よく考えたら第三の値がないといけないんだから、それがレシーバーなのは当たり前か。
Avatar
@Loooop: Now I don't think adjacentPairs(circular: true) will pass the review: in the mind of many members of the forum, ad-hoc boolean arguments are not "swifty". While I wholeheartedly support the idea, it needs polish before we can convince the community. First, what if t...
11:43 AM
2つずつ組にするやつ
Avatar
pair だけでいいのかなぁ。一般的に連続する N 要素の組にしてほしい気がする。
Avatar
omochimetaru 8/12/2018 6:03 AM
僕もそれが気になったけど、提案はtupleになってるから、Nにするとたくさん用意しておくやつになりますね
Avatar
たくさん増やしておくやつになるとして、メソッド名に pair って入ってると辛そう。
Avatar
関数名やメソッド名が名詞だと↓みたいになって困ることないですか? let foo = foo(at: path) // 名前が被ってコンパイルエラー
Avatar
Kishikawa Katsumi 8/13/2018 4:05 AM
ありますねえ。
Avatar
どう対応してますか? self. で済むなら self. を付ける、関数はできるだけ作らない、とかでしょうか?
Avatar
omochimetaru 8/13/2018 4:11 AM
名詞のルールを優先したいので 右辺にself. をつけて解決してます (edited)
Avatar
@omochimetaru 関数は?作らない?
Avatar
omochimetaru 8/13/2018 4:15 AM
func foo(at: Path) を作る。
4:15 AM
ん?
4:15 AM
関数かメソッドかの議論ですか?
4:15 AM
関数だと self がつけれないから?
Avatar
Kishikawa Katsumi 8/13/2018 4:17 AM
selfをつけるか、スコープの短い変数ならlet f = foo(at: path)ですね。 そうじゃなかったらなんとか別の変数名を考える。
🙏 1
Avatar
omochimetaru 8/13/2018 4:19 AM
グローバル関数の場合は渋い顔になりながら <ModuleName>.<funcName> って書く事もあるけど、 だいたいはなにかのクラスのメソッドになってて大丈夫です
Avatar
たしかに関数でもモジュール名を付けて書くことができるか。
Avatar
Result.Resultに破壊されてつらい
Avatar
omochimetaru 8/13/2018 2:00 PM
パッケージ名とクラス名が同じだとそれ系でなんかできない事がある気がする
Avatar
public typealias Result =でexportできないとか
2:02 PM
結構ありますね
Avatar
omochimetaru 8/13/2018 2:02 PM
その問題を避けたかったのでFilePathって型を作るライブラリ作ったときは パッケージ名は FilePathFramework にした。 (edited)
Avatar
sつけるのいいなーとか思ってる
2:03 PM
FilePaths
2:03 PM
javaみがあるけど
Avatar
omochimetaru 8/13/2018 2:04 PM
流行ってればそれでもいいな
Avatar
iOS人間だと○○Kit好きだよね
Avatar
omochimetaru 8/13/2018 2:05 PM
Appleのがそうだしね
Avatar
omochimetaru 8/15/2018 3:14 PM
このへんおもしろかった Data型をFoundationからstdlibに移そうぜスレ https://forums.swift.org/t/move-foundation-data-in-to-the-standard-library/15206 Foundationからネットワーク周りを切り離そうぜスレ https://forums.swift.org/t/pitch-move-urlsession-to-new-foundationnetworking-module/14002/1
This topic has come up a few times over the years, with apparently no objections. The standard library currently exposes no public type for an owned buffer which is released when its last reference becomes unreachable. Currently, the only facility for passing byte-buffers a...
Hi everyone, As we continue to push forward on completing swift-corelibs-foundation, I would like to propose a structural change to help us meet our goals: move URLSession and related types into a new library. Some of the feedback we've received from the SwiftNIO team is th...
👍 1
Avatar
自動生成されたDecodableのイニシャライザをサブクラスでオーバーライドできる様になってた。 @swift-4.1.3 @swift-4.2.4 import Foundation private class Person: Codable { let name: String init(name: String) { self.name = name } } private class Employee: Person { let id: Int init(name: String, id: Int) { self.id = id super.init(name: name) } enum CodingKeys: String, CodingKey { case id } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(Int.self, forKey: .id) try super.init(from: decoder) } override func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try super.encode(to: encoder) } } (edited)
Avatar
exit status: 1 with stderr:<stdin>:29:19: error: method does not override any method from its superclass override func encode(to encoder: Encoder) throws { ~~~~~~~~ ^ <stdin>:28:1: error: 'required' initializer 'init(from:)' must be provided by subclass of 'Person' ^ <unknown>:0: note: 'required' initializer is declared in superclass here (edited)
Avatar
no output (edited)
Avatar
ほお。もともとは生成タイミングの問題があったんですかね
Avatar
Encodableのメソッドも同じだった。
Avatar
@dynamicMemberLookup@dynamicCallable に加えて、 @dynamicConvertible ほしくないですか?今だと PythonObject から Swift に戻すときに↓のようにしないといけなくて面倒。 import Python let np = Python.import("numpy") let a = np.array([[1, 2], [3, 4]]) let b = np.array([[5], [6]]) let c = np.matmul(a, b) let d: Int = Int(c[0, 0])! // ここで明示的変換が必要 print(d)
1:41 AM
前提として Swift では暗黙の型変換は許さないという上で、 @dynamic 系は安全性を崩して書きやすさをとっているので、 dynamic に限って暗黙の型変換を許すのは良いバランスじゃないかということです。
1:41 AM
↓のように書きたい。 import Python let np = Python.import("numpy") let a = np.array([[1, 2], [3, 4]]) let b = np.array([[5], [6]]) let c = np.matmul(a, b) let d: Int = c[0, 0] // 暗黙の型変換 print(d)
1:42 AM
Int を右に書くか左に書くかの違いに見えますが、引数に渡すときに意味があります。
1:43 AM
↓みたいな感じ。 @dynamicMemberLookup @dynamicCallable @dynamicConvertible struct PythonObject { ... func converted() -> Int { ... } func converted() -> Bool { ... } func converted() -> String { ... } func converted() -> (PythonObject, PythobObject) { ... } ... } (edited)
1:44 AM
今は IntBool 等については extensioninit になってるけど、タプルは extension 作れないので PythonObjecttuple2 とかのメソッドが生えてて統一感もない。
Avatar
omochimetaru 8/28/2018 1:45 AM
どうして "dynamic" なんですか?
1:45 AM
"dynamicMemberLookup"と"dynamicCallable"は、型チェックのときはなんでも通る事にしておいて、 実行時にメソッド名やプロパティ名を文字列として渡して
1:46 AM
実行時にシグネチャレベルで動的にディスパッチする点がdynamicと思っていますが
1:46 AM
その例だと普通に Int への暗黙変換 を要求しているように見えます
1:46 AM
特にいま名前のニュアンスは重要でない?
Avatar
たしかにこれだと dynamic になってなさそうだな。乱用されないように dynamic に限定したい。 dynamic に限定して暗黙型変換がほしいという気持ちが先にあって、 converted の例は今適当に書いたから深く考えてなかった。 (edited)
Avatar
omochimetaru 8/28/2018 1:48 AM
なるほど。
1:48 AM
それだったら
Avatar
でも戻り値側から推論させて処理を分ける必要があるから↑のようにならざるを得ない?
1:49 AM
@dynamicMemberLookup が付与されているときのみ @dynamicConvertible にできるとか?
Avatar
omochimetaru 8/28/2018 1:49 AM
extension Int { init(_ : py PythonObject) } ↑これの実装+暗黙呼び出しがしたいって感じですかね init側じゃなくてconvert側でもいいけど
1:49 AM
例えば
1:50 AM
今ってNSDataとDataの相互変換とか
1:50 AM
Dataに対してObjCBridgeable みたいな
1:50 AM
プロトコルを定義して変換処理を設定しておくとできるってかんじだから
Avatar
@dynamicMemberLookup な型を引数にとる init(_:) があれば暗黙型変換とかいう機能でもいいのかもしれないけど (edited)
Avatar
omochimetaru 8/28/2018 1:51 AM
dynamicMemberLookupかdynamicCallableがついてる型に対する変換プロトコルを表明できる機能+それの暗黙呼び出し
Avatar
それだとタプル(というか non-nominal )が対応できない
Avatar
omochimetaru 8/28/2018 1:51 AM
ってかたちで、 Swift <-> ObjC ブリッジと同じカタチに整理できそうですね
1:51 AM
あ〜
1:51 AM
タプルね・・・
1:51 AM
タプルも対応するとなると今まで無かった機能ですね。
1:52 AM
DynamicCallableを使ってコードを書いてみたことがないからわからないけど、書いてみるとその変換の欲しくなるんかな (edited)
Avatar
@dynamic 系ってあえてプロトコルじゃなくしてあって
1:52 AM
@dynamicCallablesubscript の引数って Dictionary じゃなくてもいいし、
1:53 AM
それはプロトコルでも associatedtype でできるか
1:53 AM
↑みたいな converted という名前で解決するパターンだと attribute と親和しそうなんよね。
1:54 AM
@omochimetaru
DynamicCallableを使ってコードを書いてみたことがないからわからないけど、書いてみるとその変換の欲しくなるんかな
Swift の型→ PythonObject は暗黙的に変換されるから
(edited)
1:55 AM
逆もほしくなる。
Avatar
omochimetaru 8/28/2018 1:56 AM
Swift の型→ PythonObject は暗黙的に変換
dynamicMemberLookupのメソッドの引数に渡すときのことですよね?
1:56 AM
PythonObjectを取る通常の関数に Int を渡す事はできないと思ってた
1:56 AM
ん、いや、それも変か
Avatar
import Python let np = Python.import("numpy") let elements: [[Int]] = [[1, 2], [3, 4]] let a = np.array(elements) // OK
1:57 AM
これは、 @dynamicCallablesubscript の引数の型が (edited)
1:57 AM
PythonObject じゃなくて PythonConvertible になってるから。
Avatar
omochimetaru 8/28/2018 1:58 AM
subscript?
Avatar
@dynamicCallable はメソッドコールを subscript に変換する。
Avatar
omochimetaru 8/28/2018 1:58 AM
なるほど
1:59 AM
[[Int]] が PythonConvertible として定義されてて、全部それで受け取るのか。 (edited)
Avatar
a = someValue(keyword1: 42, "foo", keyword2: 19)a = someValue.dynamicallyCall(withKeywordArguments: [ "keyword1": 42, "": "foo", "keyword2": 19 ]) のシュガー。
Avatar
omochimetaru 8/28/2018 1:59 AM
うーん、渡す側に変換がいらないのは
2:00 AM
XxxConvertibleパターンなら、とくにdynamic関係なく、Swiftはいつもそうですよね
Avatar
[[Int]] が PythonConvertible として定義されてて、全部それで受け取るのか。(edited)
多分 extension Array: PythonConvertible where Element: PythonConvertible { ... } だろうね。
Avatar
omochimetaru 8/28/2018 2:00 AM
元の世界に戻してくるときには明示的な変換が必要なのは、普通。
Avatar
言語機能的にはそうだけど、安全性を捨てた dynamic な世界を導入してるのに、戻すところだけ安全にしても意味ない気が。 Python と Swift の世界を行き来するときに戻ってくるときだけ変換が必要で面倒・・・。
Avatar
omochimetaru 8/28/2018 2:02 AM
ああそうか
2:02 AM
x.toSwiftInt() みたいな事をやったところで
2:02 AM
それが生えてるのか正当な変換なのかもよくわからないのか。
2:03 AM
いやPythonObjectにはやしたら生えてることはわかるけど、中身の値の型との保証がないから。
Avatar
うん。今のところ、一応全部 Optional になってて、変換できなかったら nil が返ってくる
2:03 AM
Int(pythonObject) も変換できなかったら nil
2:03 AM
でもこれに失敗するケースってほぼ Logic failure だと思う。
Avatar
omochimetaru 8/28/2018 2:04 AM
確かにそうですね
2:04 AM
右辺の式に関してそもそも何も検査されてないから。
Avatar
norio_nomura 8/28/2018 2:41 AM
暗黙型変換が失敗したらどういう挙動になるの? let d: Int = c[0, 0] // 暗黙の型変換
2:46 AM
Fatal errorになるのかな。
Avatar
Logic failure なので !precondition に失敗したときと同じイメージです。
Avatar
norio_nomura 8/28/2018 3:07 AM
なるほど。
Avatar
norio_nomura 8/29/2018 3:25 AM
Swiftへ移植したいCの参照実装が std::atomic とか使ってたのでstdlib内を探したら _stdlib_atomicCompareExchangeStrongPtr https://github.com/apple/swift/blob/master/stdlib/public/core/Runtime.swift.gyb#L25 とか見つけたのですが、stdlib内で使ってるところが見当たらず。何か違うメカニズムを使ったほうがよいのかな。
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 8/29/2018 3:26 AM
移植というのはSwiftで書き直すという意味ですか?
Avatar
norio_nomura 8/29/2018 3:27 AM
そう。SwiftBacktraceへ、お手軽にクラッシュハンドラを登録できるLLVMEnablePrettyStackTrace()みたいなのを付け加えようとしてるのです。
3:29 AM
DarwinならこういうのがあるけどLinuxクロス要件もあるならう〜ん
3:30 AM
In Windows, atomic operation functions are separated by 32bit and 64bit like this: InterlockedIncrement32 InterlockedIncrement64 Meanwhile, what functions do the same in Linux? What is the functi...
3:32 AM
並列アルゴリズムならDispatchQueueを使うのが良いけど、 std::atomicみたいなローレベルな同期プリミティブになってくると
3:32 AM
Swiftには標準が無いのか・・・? (edited)
Avatar
norio_nomura 8/29/2018 3:33 AM
ざっと探した限り見当たらず。
Avatar
omochimetaru 8/29/2018 3:34 AM
ランタイムの参照カウンタとかはC++だし、そうですよねえ
Avatar
norio_nomura 8/29/2018 3:35 AM
あきらめて_stdlib_atomicCompareExchangeStrongPtr使います。
3:36 AM
ありがとうございます。
Avatar
https://forums.swift.org/t/opaque-result-types/15645 Generalized Existential っぽいけどちょっと違う func returnStringCollection() -> opaque Collection where _.Element == String みたいなのを出来るようにする提案 (edited)
Hello all, Here's a proposal I've been thinking about for a while (I blame Rust), but which came up again due to the review of SE-0222. Now seems like a fine time to pitch it. The complete proposal follows, or you can go look at the rendered version. Introduction This propo...
👀 1
Avatar
これってコンパイル時にチェックできますか? func makeOpaque<T>(_: T.Type) -> opaque Any { /* ... */ } var x = makeOpaque(Int.self) x = makeOpaque(Double.self) // error: "opaque" type from makeOpaque<Double> is distinct from makeOpaque<Int>
3:30 AM
<T> で判断するのかな??
3:31 AM
そういうことか。
Avatar
makeOpaque の実装知らないと判断できない気がするんですけど、モジュール跨いだときどうするんだろう。(まだ読んでない
Avatar
まだよくわかってないですが、なんとなく、ジェネリック関数でできることか、 generalized existential で実現できることしか実現できない気がしますが、そんなことないのかなぁ・・・。
3:35 AM
↓これの最後の行はエラー?? protocol P { } extension Int : P { } extension String : P { } func f1() -> opaque P { return "opaque" } func f2() -> opaque P { return 42 } var a = f1() a = f2()
Avatar
norio_nomura 9/3/2018 4:12 AM
実装詳細を隠すためにexistentialsを返す様にするとダイナミックディスパッチになってパフォーマンスが出ないけど、opaqueなら実装詳細を隠したままconcrete typeを使ってパフォーマンス出せるよ、って事かな?
4:17 AM
↓これの最後の行はエラー?? concrete typeに出来なければエラー、みたいな制限がつくのかな? (edited)
Avatar
omochimetaru 9/3/2018 4:21 AM
半分ぐらいまで読んだ
4:23 AM
Existentialと違ってコンパイルタイムには一つの型だから
4:24 AM
func f() -> P { if Bool.random() { return 17 } else { return "hello, existential" } } こういうのはできないってことらしい
4:24 AM
func f() -> P { /* ... */ } func g() -> opaque P { /* ... */ } let fArray = [f(), f(), f()] // contains a mix of String and Int at run-time let gArray = [g(), g(), g()] // homogeneous array of g()'s opaque result type
4:24 AM
let vf1 = f1() // type of vf1 is the opaque result type of f1()
4:24 AM
関数名ごとに型が解決されて?ついてるから (edited)
4:25 AM
↓これの最後の行はエラー??
それはエラーな気がする。
4:25 AM
"opaque <Protocol>" で型なんじゃなくて、 "opaque <Protocol> from <Function>" ってことじゃないですか?
4:26 AM
それで、解決してる真の型が同一であれば違う関数同士でも同一扱いな気がする。
Avatar
@omochimetaru その場合、 @rintaro さんが言うようにモジュールまたいだらエラーか判定できなくない?それとも、解決された型の情報を埋め込む?
Avatar
omochimetaru 9/3/2018 5:47 AM
モジュールをビルドするときに、解決結果とインターフェースの埋め込みが必要でしょうね。 それか、解決した名前と、Generalized Existentialをそれように実装するか・・・?
5:48 AM
Effect on API resilience Opaque result types are part of the result type of a function/type of a variable/element type of a subscript, which cannot be changed without affecting API resilience. We could allow an API originally specified using an opaque result type to later evolve to specify the specific result type. The result type itself would have to become visible to clients, and this might affect source compatibility, but (mangled name aside) such a change would be resilient.
5:48 AM
結果の型それ自体はクライアントから可視になる必要があるだろう。 ( The result type...
(edited)
5:51 AM
そしてそれはソース互換性に影響を与えるだろう、
but以降は英語がわからん
Avatar
However, the underlying concrete type can change from one version to the next without breaking ABI, because that type is not known to clients of the API. 真の型を変えても ABI が変わらないってことはー、コンパイル時に解決するというのと矛盾しているような。熟読しないとわからないでござる。
Avatar
omochimetaru 9/3/2018 6:00 AM
そこの ABI、 APIのタイポじゃなかろうか・・・
Avatar
いや、Implementation strategy に、「opaque result type を使用するクライアントは、結果値のサイズ、アライメント、レイアウトなどは不明のものとして扱う必要がある」とあるので、型が不明な場合 まんま existential として扱うっぽい。
Avatar
omochimetaru 9/3/2018 6:03 AM
なるほど
6:04 AM
じゃあ、実装としては事実上Genralized Existentialが提供されるけど、言語文法としてはもうちょっと縛ったものになる、という感じ・・・?
Avatar
っぽいですね。 "Opaque result types are uniqued based on the function/property/subscript and any generic type arguments." なので、
それで、解決してる真の型が同一であれば違う関数同士でも同一扱いな気がする。
は違う。
Avatar
omochimetaru 9/3/2018 6:06 AM
なるほどなるほど(あとで、ちゃんと読みます)
Avatar
それって、さっきの var a = f1() a = f2() が同一モジュール内はコンパイルエラーだけど、モジュールまたいだらコンパイル通るということになりませんか?
Avatar
同一モジュールでもエラーになると思います。
Avatar
モジュールをまたいでも、の間違いですか?
Avatar
ああ、質問の意味を取り違えてました。はい「モジュールをまたいでも」です。
Avatar
omochimetaru 9/4/2018 4:06 AM
提案を読み直した
4:06 AM
面白かったところ opaque result型はそれ自身がプロトコルに準拠できる func foo<C: Collection>(_ : C) { } foo(c) // okay: unlike existentials, opaque types work with generics
4:07 AM
返り値のopaque result型のconformanceを、ひとまとめにシグネチャだけオーバーロード(?)できる extension BidirectionalCollection { public func reversed() -> opaque BidirectionalCollection where _.Element == Element where Self: RandomAccessCollection -> _: RandomAccessCollection where Self: MutableCollection -> _: MutableCollection { return ReversedCollection<Self>(...) } }
4:08 AM
↑は3つのシグネチャが同時に書かれていて、 Selfによって、opaque resultが BidirectionalCollectionか、 RandomAccessCollectionか、MutableCollectionか、変わる
Avatar
HigherKindedの穴を埋めるのが目的なのかな (edited)
Avatar
omochimetaru 9/4/2018 4:12 AM
いや、これはもともと、 struct ReversedCollection<C: BidirectionalCollection>: BidirectionalCollection {...} extension ReversedCollection: RandomAccessCollection where C: RandomAccessCollection {}
4:12 AM
こういうふうにしてすでに実現できていた事なんだけど
4:12 AM
↑だったら、ReversedCollection側の conditional conformanceで対応できていたことが
4:13 AM
extension BidirectionalCollection { public func reversed() -> opaque BidirectionalCollection where _.Element == Element { return ReversedCollection<Self>(...) } } (edited)
4:13 AM
opaque化することで、 ↑このopaque BidirectionalCollectionが、 RandomAccessCollectionになることを記述できなくなるので
4:13 AM
extension RandomAccessCollection { public func reversed() -> opaque RandomAccessCollection where _.Element == Element { return ReversedCollection<Self>(...) } }
4:13 AM
冗長に↑も書かないといけなくなってしまう
4:13 AM
という言語機能のデグレが起きるので、 それをカバーするもの。
Avatar
なるほど
Avatar
omochimetaru 9/4/2018 4:15 AM
func h() -> opaque Comparable { return /* ... */ } var hArray = [h(), h(), h()] hArray.sort() // okay! the Element type is Comparable, and all types are the same
4:15 AM
↑こっちは地味に新しくできるようになること
4:17 AM
いままで AnyComparable を作ろうとしたら、 AnyComparableが2つあっても、それらを比較できなかった。 同じComparableが入ってるかわからんから。
4:22 AM
Existentials do not allow such an operation, even with generalized existentials, because two values of the same existential type may have different types at runtime.
4:23 AM
generalized existentialであってもそれができない、と言ってるから、この提案はGeneralized Existentialを超える良いアイデアって形で出てるのか・・・? なんでGEと別の話が湧いてきたのかよくわかっていない。
Avatar
Generics Manifesto は↓だから、新しい話が出てきてもおかしくなさそう。 It is not a plan for Swift 3, nor an official core team communication
1:17 AM
生文字列通った
🎊 1
Avatar
これって SE-200 ってそんな古いプロポーザルだったのか。差し戻しがあったからか。
Avatar
omochimetaru 9/7/2018 1:31 AM
最新が228だからそんなに古くも無いイメージ
Avatar
でも SE-0216 の @dynamicCallable でもずいぶん昔に通ったイメージ。
1:33 AM
0018とか0030とか
1:33 AM
ず〜〜〜〜っと進まなくて、
1:33 AM
時々スレッドで「これどうなった?」「XXが終わらんと無理」
1:33 AM
ってやってる
1:34 AM
0026もちょくちょくみるな
Avatar
いやまあそういうのはあるとして、もっと新しいプロポーザルなのかと思ってた。
Avatar
omochimetaru 9/7/2018 1:35 AM
なるほど
1:35 AM
そうするとやっぱ一回戻った分ですね
1:35 AM
確か、実例が足りない、とかで差し戻されたような。
Avatar
そっこーでマージされてる https://github.com/apple/swift/pull/17668
As per discussion in second pitch of raw strings on swift-evolution https://forums.swift.org/t/pure-bikeshedding-raw-strings-why-yes-again/13866. Work in progress, submitting now to get PR link. Re...
Avatar
omochimetaru 9/7/2018 1:43 AM
この注射アイコンのジョーノさんめっちゃやってた
1:44 AM
リジェクトされた旧仕様も実装してたような
1:44 AM
1:44 AM
てことはmasterでつかえるのか
Avatar
なんか rebase するかもめてるな。
1:45 AM
Reverts apple/swift#19168 to reinstate apple/swift#17668 which missed a “squash” first time around. Implementation for SE-200
1:46 AM
再マージされてた
Avatar
In https://github.com/apple/swift/pull/19151, I'm changing code generation for class convenience initializers so that they only have "allocating" entry points, which are responsible for allocating and initializing the entire object. (See Changing class convenience initializer...
❤ 2
Avatar
omochimetaru 9/7/2018 7:41 AM
!!これはよく読まねば。
Avatar
omochimetaru 9/7/2018 11:07 AM
プロトコル仲介しなくてもselfに代入できるようにするのか。 そしてワン猫サンプルをリンタロさんが書き込んでるw
😅 1
Avatar
ワン猫w
Avatar
omochimetaru 9/7/2018 11:12 AM
ニャー犬と迷ったがワン猫が主流な気がした
Avatar
ワン猫活躍してる
9:53 PM
ワン猫死んだ?
👀 1
Avatar
omochimetaru 9/8/2018 3:47 AM
手が空いたら詳細を調べたい
Avatar
omochimetaru 9/10/2018 2:50 AM
// $ swift -swift-version 5 protocol CopyInitializable { init(copy: Self) } extension CopyInitializable { init(copy: Self) { self = copy } } class Animal : CopyInitializable { convenience init(animal: Animal) { self.init(copy: animal) } }
2:50 AM
a.swift:13:25: error: cannot convert value of type 'Animal' to expected argument type 'Self' self.init(copy: animal) ^~~~~~ as! Self
2:51 AM
> おかしいのは、ここで self.init(_with: ) が呼び出せてしまうことじゃないですか? > AnimalProtocolが引数に受けてる Self は、 AnimalBase が final で無いのだから > 何かのサブクラスである可能性があって (たとえばCat ) > なのに、 obj: AnimalBase を渡せてしまっている
2:51 AM
自分の考えと一致する方向で修正されている〜
🙌 1
Avatar
考え得る中で一番嬉しい修正に見える
Avatar
norio_nomura 9/11/2018 1:31 PM
その修正、1年以上前なのね。 https://github.com/apple/swift/pull/11637
Consider a class initializer that delegates to a protocol extension initializer, for example protocol P {} extension P { init() { ... } } class C : P { convenience init(foo: Int) { self.init()...
Avatar
omochimetaru 9/11/2018 5:01 PM
マジかw
Avatar
@swift-main -swift-version 5 Swift 5 、 NoError 要らずでいい感じ。 enum Result<Value, Error: Swift.Error> { case success(Value) case failure(Error) func get() throws -> Value { switch self { case .success(let value): return value case .failure(let error): throw error } } } extension Result where Error == Never { func get() -> Value { switch self { case .success(let value): return value } } } let a: Result<Int, Never> = .success(42) print(a.get())
👍 2
Avatar
swiftNightly BOT 9/12/2018 2:21 PM
42
Avatar
omochimetaru 9/18/2018 3:08 AM
@swift-4.2.4 enum Result<Value, Error: Swift.Error> { case success(Value) case failure(Error) func get() throws -> Value { switch self { case .success(let value): return value case .failure(let error): throw error } } } extension Result where Error == Never { func get() -> Value { switch self { case .success(let value): return value } } } let a: Result<Int, Never> = .success(42) print(a.get())
Avatar
exit status: 1 with stderr:<stdin>:15:30: error: same-type constraint type 'Never' does not conform to required protocol 'Error' extension Result where Error == Never { ^ <stdin>:24:8: error: type 'Never' does not conform to protocol 'Error' let a: Result<Int, Never> = .success(42) ^ <stdin>:17:9: error: switch must be exhaustive switch self { ^ <stdin>:17:9: note: add missing case: '.failure(_)' switch self { ^
Avatar
omochimetaru 9/18/2018 3:08 AM
5系からNeverがBottomTypeとして振る舞うのか。
Avatar
嬉しいね
Avatar
undefinedが要らなくなります?
Avatar
いらない、fatalErrorでok
3:11 AM
ただ、あれを使うとデフォルト引数にfile function lineを使えるメリットはある
Avatar
なるほど
Avatar
omochimetaru 9/18/2018 3:12 AM
お、それもいけんの?
Avatar
Bottomならいける
Avatar
omochimetaru 9/18/2018 3:12 AM
@swift-main -swift-version 5 let a: Int = fatalError()
Avatar
swiftNightly BOT 9/18/2018 3:12 AM
exit status: 1 with stderr:<stdin>:1:14: error: cannot convert value of type 'Never' to specified type 'Int' let a: Int = fatalError() ^~~~~~~~~~~~
Avatar
なんでやー
3:12 AM
BottomTypeいうたやんか
Avatar
omochimetaru 9/18/2018 3:12 AM
🤔
Avatar
Avatar
omochimetaru 9/18/2018 3:12 AM
BottomTypeになったわけではない。
Avatar
おそらくだが、protocol conformだけでは
Avatar
Errorに適合したわけではない? (edited)
Avatar
omochimetaru 9/18/2018 3:13 AM
オーバーライドはどうなんだ、とか
3:13 AM
サブタイピングにまつわる言語機能がたくさんあってアレ
Avatar
@swift-main -swift-version 5 protocol Animal {} func foo<A: Animal>(_ a: @autoclosure () -> A) {} foo(fatalError())
Avatar
swiftNightly BOT 9/18/2018 3:14 AM
exit status: 1 with stderr:<stdin>:3:1: error: global function 'foo' requires that 'Never' conform to 'Animal' foo(fatalError()) ^ <stdin>:2:6: note: where 'A' = 'Never' func foo<A: Animal>(_ a: @autoclosure () -> A) {} ^
Avatar
オオン
3:14 AM
Errorだけすね
3:15 AM
Errorとsynthesizerの入った幾つかのprotocolだけ特別になったくさい
Avatar
Bottom typeは夢だったのか…
Avatar
露と消えた
Avatar
omochimetaru 9/18/2018 3:18 AM
@swift-main -swift-version 5 func f<E: Error>(_ e: E) {} f(fatalError()) (edited)
Avatar
swiftNightly BOT 9/18/2018 3:18 AM
exit status: 4 with stderr:<stdin>:2:3: warning: will never be executed f(fatalError()) ^ <stdin>:2:3: note: a call to a never-returning function f(fatalError()) ^ Fatal error: : file <stdin>, line 2 Current stack trace: 0 libswiftCore.so 0x00007f9510c6da50 _swift_stdlib_reportFatalErrorInFile + 115 1 libswiftCore.so 0x00007f9510bad167 <unavailable> + 3617127 2 libswiftCore.so 0x00007f95109c0785 <unavailable> + 1599365 3 libswiftCore.so 0x00007f9510bacf92 <unavailable> + 3616658 4 libswiftCore.so 0x00007f95109bf9bd <unavailable> + 1595837 5 libswiftCore.so 0x00007f9510b6581f <unavailable> + 3323935 6 libswiftCore.so 0x00007f95109bf149 <unavailable> + 1593673 8 swift 0x00000000010b39de <unavailable> + 13318622 9 swift 0x00000000010b7a62 <unavailable> + 13335138 10 swift 0x0000000000519d85 <unavailable> + 1154437 11 swift 0x00000000004ee6e5 <unavailable> + 976613 12 swift 0x00000000004e9aa1 <unavailable> + 957089 13 swift 0x0000000000494fa0 <unavailable> + 610208 14 libc.so.6 0x00007f9513136740 __libc_start_main + 240 15 swift 0x0000000000492dd9 <unavailable> + 601561 Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -swift-version 5 -module-name main #0 0x00000000044580a4 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x44580a4) #1 0x0000000004455f70 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4455f70) #2 0x0000000004458252 SignalHandler(int) (/usr/bin/swift+0x4458252) #3 0x00007f9514a0c390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f9510b65823 $Ss17_assertionFailure__4file4line5fla (edited)
Avatar
omochimetaru 9/18/2018 3:18 AM
んっ
3:18 AM
@swift-main -swift-version 5 func f<X: Error>(_ error: X) {} f(fatalError())
Avatar
swiftNightly BOT 9/18/2018 3:18 AM
exit status: 4 with stderr:<stdin>:2:3: warning: will never be executed f(fatalError()) ^ <stdin>:2:3: note: a call to a never-returning function f(fatalError()) ^ Fatal error: : file <stdin>, line 2 Current stack trace: 0 libswiftCore.so 0x00007f6cf4244a50 _swift_stdlib_reportFatalErrorInFile + 115 1 libswiftCore.so 0x00007f6cf4184167 <unavailable> + 3617127 2 libswiftCore.so 0x00007f6cf3f97785 <unavailable> + 1599365 3 libswiftCore.so 0x00007f6cf4183f92 <unavailable> + 3616658 4 libswiftCore.so 0x00007f6cf3f969bd <unavailable> + 1595837 5 libswiftCore.so 0x00007f6cf413c81f <unavailable> + 3323935 6 libswiftCore.so 0x00007f6cf3f96149 <unavailable> + 1593673 8 swift 0x00000000010b39de <unavailable> + 13318622 9 swift 0x00000000010b7a62 <unavailable> + 13335138 10 swift 0x0000000000519d85 <unavailable> + 1154437 11 swift 0x00000000004ee6e5 <unavailable> + 976613 12 swift 0x00000000004e9aa1 <unavailable> + 957089 13 swift 0x0000000000494fa0 <unavailable> + 610208 14 libc.so.6 0x00007f6cf670d740 __libc_start_main + 240 15 swift 0x0000000000492dd9 <unavailable> + 601561 Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -swift-version 5 -module-name main #0 0x00000000044580a4 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x44580a4) #1 0x0000000004455f70 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4455f70) #2 0x0000000004458252 SignalHandler(int) (/usr/bin/swift+0x4458252) #3 0x00007f6cf7fe3390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f6cf413c823 $Ss17_assertionFailure__4file4line5fla
Avatar
omochimetaru 9/18/2018 3:18 AM
oh
3:19 AM
Errorプロトコルになったわけでもないのでは。死んでしまった。 (edited)
Avatar
@swift-main -swift-version 5 func f<X: Error>(_ error: @autoclosure ()->X) {} f(fatalError())
Avatar
swiftNightly BOT 9/18/2018 3:19 AM
no output
Avatar
コンパイルは通ってるっぽい
Avatar
fatalで死んでるだけ
3:19 AM
ややこしいからautoclosure使おう
Avatar
omochimetaru 9/18/2018 3:19 AM
あ、これ実行されるからか。
3:19 AM
良かった。
Avatar
つまりNeverはErrorになった
😇 3
😺 1
3:20 AM
全部Errorに適合させたら実質BottomTypeでは?
3:21 AM
天才
3:21 AM
protocol Animal: Error {}
Avatar
T where T:Errorが無限に書かれる世界
Avatar
omochimetaru 9/18/2018 3:22 AM
ErrorがbottomなんじゃなくてNeverがErrorだから違くない?
Avatar
マジレスするとNeverはErrorでAnimalはErrorなだけなので成り立たない
3:23 AM
これと一緒
😇 1
Avatar
出遅れた。 NeverErrorEquatable になっただけで、 bottom になったわけではないはず。ただ、たしか Chris Lattner か Joe Groff が forum の議論の最初の方で bottom type に言及してた気が。
4:13 AM
で、とりあえず今やることとして、 Equatable 入れるなら Error も入れるのがいいんじゃない?みたいな会話があったと思う。
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
👀 1
4:32 AM
bottom typeについてはAlternatives consideredで言及されてあります (edited)
4:32 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 9/18/2018 4:33 AM
This would have some advantages and might be ideal, but would require a lot more work to determine the design and implement the behavior.
4:33 AM
否定的な観点は設計と実装の都合だけか、良かった
Avatar
bottom type化に一気に行く前にとりあえずError, Equatable, Hashableを先にやったという感じ (edited)
Avatar
前に読んだのは↓っぽい。 Chris Lattner Jun 13 Moderate -1. Never is special because it has no instances - it is uninhabited by design. This means that it can conform to all protocols. I'd rather see a global solution rather than cherry picking these two specific protocols. Joe_Groff Jun 13 If we're cherry-picking protocols to conform Never to, Error seems like another good one to whitelist, since it's useful to use Never to close off the error path in Result<T, Never>-like abstractions. https://forums.swift.org/t/se-0215-conform-never-to-equatable-and-hashable/13586 (edited)
The review of SE-0215 — Conform Never to Equatable and Hashable begins now and runs through June 19, 2018. The proposal is authored by @mdiep. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if yo...
Avatar
omochimetaru 9/18/2018 6:05 AM
@swift-4.2.4 let range: Range<Float> = 0..<1 let x = range.randomElement()
Avatar
exit status: 1 with stderr:<stdin>:2:10: error: ambiguous reference to member 'randomElement(using:)' let x = range.randomElement() ^~~~~ Swift.Collection:11:17: note: found this candidate public func randomElement<T>(using generator: inout T) -> Self.Element? where T : RandomNumberGenerator ^ Swift.Collection:12:17: note: found this candidate public func randomElement() -> Self.Element? ^
Avatar
omochimetaru 9/18/2018 6:05 AM
これなんで??
6:05 AM
引数無いんだから2番目しか無いじゃんと思う
Avatar
Range<Float> は Collection じゃないので、実際には randomElement() 生えていないということだと思います。エラーメッセージも悪いし、Xcode で補完されちゃうのも悪い。
Avatar
omochimetaru 9/18/2018 6:15 AM
あ〜、なるほど。
6:15 AM
ありがとうございます。
Avatar
omochimetaru 9/21/2018 3:18 AM
I need to start with a quick review of Swift's formal access semantics (as described in the ownership manifesto; reading just the three paragraphs under "Accesses" is fine). The evaluation of a storage reference expression in Swift is formally ordered like this: Formal eva...
3:19 AM
ストレージアクセスの中断をどうするかって いうジョンマッコールのPitch
3:19 AM
例えばcomputed propertyをinoutで渡している関数の中で例外が投げられた時
3:20 AM
そのプロパティの書き換えはコミットされるのかされないのか。
3:20 AM
コルーチンによるmodifyアクセサも仕様化されるからそれへの備えもありそう。
3:22 AM
(いつも思うんだけど、mccallの長い英文、難しい・・・
Avatar
#swift-contrib から派生して、↓の挙動に驚いた。 @swift-4.2.4 var a = [2, 3, 5] var b = a[...] a.removeFirst() print(a.startIndex) b.removeFirst() print(b.startIndex)
Avatar
0 1
Avatar
ArraySlicepopFirststartIndex を動かすけど、 removeFirst は動かさずに前に詰める(というか、先頭ポインタを動かして startIndex は動かさない)のかと思ってた。
Avatar
removeFirstpopFirstで返り値型が違うんですね
2:03 AM
removeのほうは空だとFatal errorか。 結果的には詰めてもポインタ動かすだけでも同じなので計算量が少ない方を選ぶのは自然な気がしますね。
Avatar
@t.ae ArrayArraySlice の同じメソッドで startIndex が動くか動かないかという挙動が違う件ですね。
2:05 AM
O(1) で startIndex が動かないようにも実装できるはず。
Avatar
結果的に同じというのは語弊がありますね。最終的な内容物が同じ
Avatar
まだArraySliceremoveFirstの実装がどれなのか確定できてないですが上位プロトコルで実装されててArraySlice以外の事情も絡んでそうな気がしてます。 https://github.com/apple/swift/blob/ae6f5dd60460f340d98cf24c402c6489bb5a4f2b/stdlib/public/core/Collection.swift#L1765-L1781
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
@swift-4.2.4 func foo<C: RangeReplaceableCollection>(_ collection: C) -> C.Index? { var collection = collection if collection.isEmpty { return nil} collection.removeFirst() return collection.startIndex } var a: Array<Int> = [2, 3, 5] var b: ArraySlice<Int> = a[...] print(foo(a)!) print(foo(b)!)
Avatar
0 1
Avatar
これ微妙じゃないのかな?そこは未定義なんだと言えばそうなのかもしれないけど・・・。
Avatar
CollectionIndex は opaque として扱われるべきで、実値は気にするべきではないと思います。
Avatar
そういうものなんですね。まあ ArrayArraySlice は直接関係があるわけでないしいいのかな。
Avatar
例の opaque result types 、例に書かれてる↓みたいな記法になるんだったら generalized existential も似た記法になりそう。個人的には === が並んで読みづらい・・・。 var strings: opaque Collection where _.Element == String = ["hello", "world"]
3:44 AM
Generalized existential の例として書かれてるのが let strings: Any<Sequence where .Iterator.Element == String> = ["a", "b", "c"] だから、書き換えたら↓みたいな感じ? let strings: Sequence where _.Iterator.Element == String = ["a", "b", "c"]
3:44 AM
opaque がなければ Generalized existential になるのか。
3:45 AM
opaque が何かを Swift 初心者に説明するの難しそう・・・。
Avatar
二つのモジュール FooBar があって、両方に Cat という型があって、 Bar モジュールに Bar という型がある場合に、 Foo の中から Bar.Cat を表現するにはどうすればいいですか?↓のようにすると Bar.Bar.Cat を意味してしまってエラーになってしまいました。 // Foo モジュールにて import Bar struct Cat { init(_ cat: Bar.Cat) { ... } } (edited)
8:09 AM
import Bar as B とかできればいいんですが・・・。
Avatar
omochimetaru 10/1/2018 8:24 AM
その問題、僕も困っていて、解決方法を知りたいんですよね。 なので、パッケージ名と、同じ名前の型をそのパッケージに定義しないのが良いと思っています。
8:24 AM
Result は パッケージ名変えて欲しい。
Avatar
norio_nomura 10/1/2018 8:32 AM
Fooのソースの中で必要とするのがBar.Catだけであれば、 import struct Bar.Cat で解決できるかも。
Avatar
おおお、 @norio_nomura さんの方法そのままだと Foo.Cat と被ってしまったけど、別ファイルを作って import struct Bar.Cat typealias BarCat = Bar.Cat として BarCat としてアクセスできました。難点は、 BarCat を使う API が public な場合、 typealias を露出させないといけないこと。
Avatar
omochimetaru 10/1/2018 8:45 AM
マジかそんな方法があったのか
Avatar
これってResult.Resultでも同じ方法できますか?
Avatar
試してないけどできそうな気がします。
Avatar
norio_nomura 10/1/2018 8:48 AM
Hi, I have another Result structure in my code and it's conflicting with this one. How can I use Result.Result for this enum? I'm getting the error Reference to generic type 'Result'...
Avatar
おお
8:49 AM
やっぱアンスコいりますよねぇ
Avatar
アプリ側で利用するならアンスコなしで typealias AntiResult<T, E: Error> = Result<T, E> とかでも良さそうな気も。
8:50 AM
ライブラリだとアンスコ付けますね。
8:51 AM
いや、もしかしたら typealias 露出しないでもいけるかな・・・ (edited)
Avatar
この間試してあんまりうまくいかなかった記憶
Avatar
やっぱ Result だと無理そう・・・
9:02 AM
typealias 以前に、 norio さんが挙げてくれた方法も自モジュールで Result 型を宣言してたら無理そう。 (edited)
9:02 AM
↑のリンクは、あくまで Alamofire で宣言されたものとの alias だから良いだけで。
9:03 AM
さっき僕が挙げた例も、 Foo.CatBar.CatBar.Bar の問題だから回避できたけど、
9:03 AM
Foo.BarBar.BarFoo の中で解決するのはきつそう。
Avatar
↓これの一つ目が 1 Cat にならないのってなんででしょう? 1 Animal の方のメソッドがジェネリックでないから? @swift-4.2.4 class Animal<T> {} class Cat<T, U>: Animal<T> {} struct Hoge { func foo(_: Animal<Hoge>) { print("1 Animal") } func foo<U>(_: Cat<Hoge, U>) { print("1 Cat") } } Hoge().foo(Cat<Hoge, Int>()) // 1 Animal func foo<T>(_: Animal<T>) { print("2 Animal") } func foo<T, U>(_: Cat<T, U>) { print("2 Cat") } foo(Cat<Hoge, Int>()) // 2 Cat (edited)
Avatar
1 Animal 2 Cat (edited)
Avatar
PatialKeyPathWritableKeyPath でこのパターンでオーバーロードして死んだ。
Avatar
omochimetaru 10/2/2018 8:44 AM
Comparing 2 viable solutions --- Solution #0 --- Fixed score: 0 0 0 0 0 0 0 0 0 0 0 ... Constraint restrictions: Cat<Hoge, Int> to Animal<Hoge> is [superclass] Cat<Hoge, Int> to Cat<Hoge, Int> is [deep equality] ... --- Solution #1 --- Fixed score: 0 0 0 0 0 0 0 0 0 0 0 ... Constraint restrictions: Cat<Hoge, Int> to Cat<Hoge, Int> is [deep equality] ...
8:45 AM
comparing solutions 1 and 0 Comparing declarations func ffoo<U>(_: Cat<Hoge, U>) { } and func ffoo(_: Animal<Hoge>) { } comparison result: not better Comparing declarations func ffoo(_: Animal<Hoge>) { } and func ffoo<U>(_: Cat<Hoge, U>) { } comparison result: better
8:45 AM
swift -Xfrontend -debug-constraints a.swift
8:45 AM
比較して勝った事はわかるけどなんでなのかがよくわからないけど、↑の出力からわかる気がする
8:47 AM
Comparing declarations func foo<T>(_: Animal<T>) { } and func foo<T, U>(_: Cat<T, U>) { } comparison result: not better Comparing declarations func foo<T, U>(_: Cat<T, U>) { } and func foo<T>(_: Animal<T>) { } (found solution 0 0 0 0 0 0 0 0 0 0 0) comparison result: better (edited)
Avatar
もちろん比較して勝ってるから選ばれてるんだけど、この挙動は意図的なのかな?
8:49 AM
↓ Kotlin の場合 open class Animal<T> class Cat<T, U>: Animal<T>() class Hoge { fun foo(a: Animal<Hoge>) { println("1 Animal") } fun <U> foo(a: Cat<Hoge, U>) { println("1 Cat")} } fun <T> foo(a: Animal<T>) { println("2 Animal") } fun <T, U> foo(a: Cat<T, U>) { println("2 Cat") } fun main(args: Array<String>) { Hoge().foo(Cat<Hoge, Int>()) // 1 Cat foo(Cat<Hoge, Int>()) // 2 Cat } (edited)
Avatar
omochimetaru 10/2/2018 8:49 AM
その詳細が、↑のデバッグ出力から読み取るんじゃないかと思って。
Avatar
なるほど
8:50 AM
この場合 1 Cat が自然だと思うんだけどなぁ。
Avatar
omochimetaru 10/2/2018 8:50 AM
1については、Genericメソッドよりnon genericメソッドが常に優先するルールな気がします
8:51 AM
2はGenericメソッド同士だからそこは同ランクで、次の比較が引数の型が詳細な方、かなあ。
8:51 AM
どっかに文書化されてましたっけ
Avatar
それがサブクラスで特殊化されてるのより強いのが納得いかない。
8:52 AM
文書はわからないです。
8:53 AM
もし non generic が常に強いとすると、 PartialKeyPath<T> と、そのサブクラスである KeyPath<T, U>WritableKeyPath<T, U> でオーバーロードして、 TSelf とか入れたときに後者が勝つ方法がなさそう。
8:53 AM
UAny にしてしまえば勝てるだろうけど・・・。 (edited)
8:54 AM
だめか? Any にしても variance がうまく働かない?
8:55 AM
ダメっぽい。 @swift-4.2.4 let a: KeyPath<[Int], Int> = \[Int].count let b: KeyPath<[Int], Any> = a
Avatar
exit status: 1 with stderr:<stdin>:2:30: error: cannot convert value of type 'KeyPath<[Int], Int>' to specified type 'KeyPath<[Int], Any>' let b: KeyPath<[Int], Any> = a ^
Avatar
omochimetaru 10/2/2018 8:56 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
8:56 AM
// A concrete type is better than an archetype. // FIXME: Total hack. if (type1->is<ArchetypeType>() != type2->is<ArchetypeType>()) { if (type1->is<ArchetypeType>()) ++score2; else ++score1; continue; }
8:56 AM
これかなあ?
Avatar
それっぽい感じはするね。
Avatar
omochimetaru 10/2/2018 8:57 AM
@ukitaka この辺わかりますか〜
Avatar
ぱっとはわからんです、あとでみます〜
🙏 2
Avatar
↓最小ケースできた。 @swift-4.2.4 class Animal {} class Cat<T>: Animal {} func foo(_: Animal) { print("Animal") } func foo<T>(_: Cat<T>) { print("Cat") } foo(Cat<Int>())
Avatar
Animal
Avatar
omochimetaru 10/2/2018 9:18 AM
@swift-4.2.4 class Animal { func fooImpl() { print("Animal") } } class Cat<T>: Animal { override func fooImpl() { print("Cat") } } func foo(_ animal: Animal) { animal.fooImpl() } func foo<T>(_ cat: Cat<T>) { cat.fooImpl() } foo(Cat<Int>())
Avatar
Cat
Avatar
omochimetaru 10/2/2018 9:19 AM
こういうワークアラウンドを思いついたけど、PartialKeyPathは既存の型だから無理ですねえ
Avatar
func foo<T> 意味ないw
Avatar
omochimetaru 10/2/2018 9:20 AM
func foo(_ animal: Animal) func foo<T>(_ cat: Cat<T>)
9:21 AM
↑この2つがあるときに、foo<T> って完全に腐ってる?
Avatar
@omochimetaru @swift-4.2.4 class Animal {} class Cat<T>: Animal {} func foo(_: Animal) { print("Animal") } func foo<T>(_: Cat<T>) { print("Cat") } let f: (Cat<Int>) -> Void = foo f(Cat<Int>())
Avatar
Cat
Avatar
omochimetaru 10/2/2018 9:24 AM
なるほど・・・
Avatar
でもこれで普通に書いて Animal 優先は辛い・・・
Avatar
omochimetaru 10/2/2018 9:25 AM
無意味にパラメータを足したりしようとしたけどダメだった(コンパイルが通らない
Avatar
↓なら Cat @swift-4.2.4 class Animal {} class Cat<T>: Animal {} func foo<X>(_: X, _: Animal) { print("Animal") } func foo<X, T>(_: X, _: Cat<T>) { print("Cat") } foo((), Cat<Int>())
Avatar
Cat
Avatar
omochimetaru 10/2/2018 9:27 AM
呼び出し側で埋める必要が出てしまう
Avatar
はい。
9:28 AM
9:28 AM
そこをデフォルト引数とかできないかな?
Avatar
omochimetaru 10/2/2018 9:28 AM
やってみたんだけど、だめ
Avatar
@swift-4.2.4 class Animal {} class Cat<T>: Animal {} func foo<T: Animal>(_: T) { print("Animal") } func foo<T>(_: Cat<T>) { print("Cat") } foo(Cat<Int>())
Avatar
Cat
Avatar
Never が bottom でも無理? 無理か。初期値に入れられない。 (edited)
Avatar
omochimetaru 10/2/2018 9:28 AM
Avatar
なるほど・・・
Avatar
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 10/2/2018 9:30 AM
おー。
Avatar
@rintaro これって意図的なのか、今実装がそうなってるだけなのかってわかります? AnimalCat<T> だと Cat<T> を優先してほしいのが自然な感覚な気がするんですが、継承で型パラを足すというのがレアケースなので考慮漏れの可能性もあるかなと思うんですが。確か、初期の Swift は継承で型パラ足すのできなかったですよね?
Avatar
初期の Swift は継承で型パラ足すのできなかったですよね?
これは覚えてないですが、フォーマルな仕様が無い以上、意図的か否かを気にすることに意味は無いと思います。
Avatar
バグレポ投げて意見を聞いてみるとかがいいですか?
Avatar
とはいえ、これ変更するとレアケースとはいえ Source Breaking になるので、なかなかハードル高いとは思います。
9:36 AM
バグレポで良いと思いますよ 👍
🙂 1
Avatar
バグレポ出してみます。あと、とりあえず現状の問題は @rintaro さんのワークアラウンドで解決できました。ありがとうございました。
Avatar
僕だったら意図的か否かを訊かずに、"I believe the latter should be selected." と主張してしまいます🙃
🙂 1
Avatar
意図的ですか?は京都弁っぽさを感じるw
😅 1
Avatar
思いつかなかったけど、non generic優先が好ましいと思えるパターンはあるのかな
Avatar
同じくおもいつかなかったけど、これ Animalprotocol の場合も同結果になるのは結構きついと思った。 (edited)
10:57 AM
↑気づかずに非効率な方に流されちゃってる場合が結構ありそう。という意味で。
Avatar
なるほど。継承避けてプロトコル指向で組んでても踏むかもしれない・・
Avatar
お、
Mark Lacey is working on improving this situation.
Avatar
omochimetaru 10/3/2018 1:36 AM
non genericかgenericかどうかは優先度に影響しないようになるのかな
Avatar
Swift Bugs 、リアクションで絵文字付ける機能ないけど、こういうとき、いいね的なコメントをすべきなのか迷う。ゴミになる気もするし。絵文字一つだけのコメントを投稿すればいいのかな・・・。リアクションがないと見てないみたいだし。
Avatar
omochimetaru 10/3/2018 6:19 AM
絵文字リアクションなんて昔は無かったのに・・・
Avatar
そもそも絵文字が存在してない
Avatar
omochimetaru 10/3/2018 6:19 AM
慣れすぎて無くて困ってる人だ。
Avatar
Githubのリアクションも絵文字のバリエーションが足りなくて困る
Avatar
omochimetaru 10/3/2018 6:19 AM
ウケる
Avatar
なんで👎😕 しかないんや
Avatar
わかる < Githubのリアクションも絵文字のバリエーションが足りなくて困る
Avatar
Xcode 9/Swift 4.1.2ではコンパイル通ってたコードで、Xcode 10にしたらSwift 4.2でも4.1でもコンパイラがSEGVするのに出会って、結局ジェネリクスにする必要が今のところなかったのでパターン2の方向で対応したんですが、ジェネリクス使ったままコンパイル通す方法とかありそうでしょうか。 https://gist.github.com/r-plus/3c5076c1f1c314cec0fe88536ea12159
Swift compiler SEGV in Xcode10. GitHub Gist: instantly share code, notes, and snippets.
Avatar
omochimetaru 10/9/2018 6:19 AM
class A {} protocol BProtocol { associatedtype Info: A var info: Info? { get set } } class B<T1: A>: BProtocol { var info: T1? } protocol CProtocol { associatedtype Property: BProtocol var property: Property? { get set } } class C<T2>: CProtocol where T2 : BProtocol { var property: T2? }
6:20 AM
ちょっと情報は落ちちゃってますがコレで通りました。
Avatar
めっちゃいいおやつなんだけどタスク積んでるから待って
Avatar
おぉ、なるほど。whereにするといけるのか。 <T2: B<A>> で二重になってたのが悪かったんですかね、やっぱり。
Avatar
omochimetaru 10/9/2018 8:14 AM
いえ、 CのT2の制約を B から BProtocol に変更してます
8:15 AM
class A {} protocol BProtocol { associatedtype Info: A var info: Info? { get set } } class B<T1: A>: BProtocol { var info: T1? } protocol CProtocol { associatedtype Property: BProtocol var property: Property? { get set } } // vvvvvvvv ここが違う class C<T2 : BProtocol>: CProtocol { var property: T2? } (edited)
8:18 AM
二重になってたのが悪かったんですかね
(それを書く事自体は)悪くはないはずで、コンパイラのバグとして bugs.swift.org に報告するのが良いと思います
(edited)
Avatar
<T2: BProtocol> にしても当初表現したかった形としては成立してるので、その形に修正しようかな。。ありがとうございます。
Avatar
最新 master ではコンパイル通ったので放っておいても直ると思いますが、再現コードがあると嬉しいので、bugs.swift.org は有り難いです。
Avatar
お、わかりました、最新では通るということはresolvedでしょうけど類似探してなければあげておきます。
Avatar
最新 master ではコンパイル通ったので放っておいても直る Swift 5っていつ頃リリース予定でしたっけ?
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
9:57 PM
例年通りなら春頃?
Avatar
おお、そんなところに記載が。ありがとうございます。
🙂 1
Avatar
例年のSwiftの大きめの春リリースはSpring表記(Swift 2.2も3.1もその表記で3月でした)だったので、Swift 5のEarly表記ならもう少し早めかなと思っていました(英語の意味的には多分1-3月指していて、少し手こずって結局同じく3月になる可能性とかもありそうですが)。
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
This post describes the goals, release process, and estimated schedule for Swift 3.1.
Avatar
early って初頭なんですね。前半くらいの意味かと思ってました。
Avatar
はい、明確な定義は無さそう(初めの四半期くらいと言っている人もいましたが)ですが、早めのニュアンスだと思いました。 (edited)
✅ 1
Avatar
Optional Chaining が Optional を flatten することが引き起こすちょっと微妙な(おもしろい?)例。 @swift-4.2.4 func foo(_ x: [Int?]?) -> Any { return x?[0] as Any } func bar<T>(_ x: [T]?) -> Any { return x?[0] as Any } let a: [Int?]? = [2, 3, 5] print(String(describing: foo(a))) print(String(describing: bar(a))) (edited)
👀 1
Avatar
Optional(2) Optional(Optional(2)) (edited)
Avatar
↑この前話してた Optional Chaining と flatten に絡んで > @omochimetaru (edited)
8:43 AM
一見 TInt? を埋めたら同じコードに見えるけど結果が異なる。
Avatar
うーむなるほど ジェネリックなTのときはflattenしないからか。 (edited)
Avatar
今コード書いてて思い付いた。
Avatar
vicktorManuel 10/13/2018 3:24 AM
面白い
Avatar
vicktorManuel 10/13/2018 5:28 PM
@swift-4.2.4 enum Sample<T> { case Foo(T) case Bar(T) } indirect enum Sample1<T> { case Foo(T) case Bar(T) } enum Sample2<T> { indirect case Foo(T) case Bar(T) } enum Sample3<T> { indirect case Foo(T) indirect case Bar(T) }`
Avatar
no output
Avatar
vicktorManuel 10/13/2018 5:36 PM
Recursive Enumerations
5:40 PM
@swift-4.2.4 enum ArithmeticExpression { case number(Int) indirect case addition(ArithmeticExpression, ArithmeticExpression) indirect case multiplication(ArithmeticExpression, ArithmeticExpression) } let five = ArithmeticExpression.number(5) let four = ArithmeticExpression.number(4) let sum = ArithmeticExpression.addition(five, four) let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2)) print(sum) print(product)`
Avatar
addition(main.ArithmeticExpression.number(5), main.ArithmeticExpression.number(4)) multiplication(main.ArithmeticExpression.addition(main.ArithmeticExpression.number(5), main.ArithmeticExpression.number(4)), main.ArithmeticExpression.number(2))
Avatar
vicktorManuel 10/13/2018 5:44 PM
@swift-4.2.4 enum ArithmeticExpression { case number(Int) indirect case addition(ArithmeticExpression, ArithmeticExpression) indirect case multiplication(ArithmeticExpression, ArithmeticExpression) } let five = ArithmeticExpression.number(5) let four = ArithmeticExpression.number(4) let sum = ArithmeticExpression.addition(five, four) let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2)) func evaluate(_ expression: ArithmeticExpression) -> Int { switch expression { case let .number(value): return value case let .addition(left, right): return evaluate(left) + evaluate(right) case let .multiplication(left, right): return evaluate(left) * evaluate(right) } } print(evaluate(product))`
Avatar
18
Avatar
Hi all, I wrote an Automatic Differentiation Manifesto, as the start to push for world's first general-purpose differentiable programming language.
1:46 AM
Swift for TensorFlow の自動微分機能の、本家Swift向けのPitchが出た。
Avatar
class A<E> { convenience init<X>(_ array: [X]) where X : Equatable, X == E { self.init(array, { (a, b) in a == b }) } init(_ array: [E], _ eq: @escaping (E, E) -> Bool) {} }
Same-type requirement makes generic parameters 'X' and 'E' equivalent
これコンパイル通らないんですが、簡単な方法って無いんでしょうか
(edited)
6:36 AM
ちなみにinitじゃなくてstatic funcならイケました。
Avatar
extension A where E: Equatable の中に生やすとか?
Avatar
あ〜できたー
6:41 AM
なるほどそうか・・・ ありがとう〜
🙌 1
Avatar
@swift-4.2.4 struct KeySortedArray<Element, Key : Comparable> { init(_ array: [Element], _ getKey: @escaping (Element) -> Key) {} } extension KeySortedArray where Element : Comparable, Element == Key { init(_ array: [Element]) { } } class Cat { init() { KeySortedArray(self.blocks, { $0.time }) } }
Avatar
exit status: 11 with stderr:#0 0x000000000410b054 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x410b054) #1 0x0000000004108ee2 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4108ee2) #2 0x000000000410b202 SignalHandler(int) (/usr/bin/swift+0x410b202) #3 0x00007f0b420d2390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00000000016b1b09 swift::FunctionType::get(swift::Type, swift::Type, swift::AnyFunctionType::ExtInfo const&) (/usr/bin/swift+0x16b1b09) #5 0x00000000017fde74 swift::GenericFunctionType::substGenericArgs(swift::SubstitutionMap const&) (/usr/bin/swift+0x17fde74) #6 0x00000000017fdd02 swift::GenericFunctionType::substGenericArgs(llvm::ArrayRef<swift::Substitution>) (/usr/bin/swift+0x17fdd02) #7 0x000000000147abe0 swift::UncurriedCandidate::UncurriedCandidate(swift::ValueDecl*, unsigned int) (/usr/bin/swift+0x147abe0) #8 0x000000000147da0f swift::CalleeCandidateInfo::collectCalleeCandidates(swift::Expr*, bool) (/usr/bin/swift+0x147da0f) #9 0x00000000014667e1 (anonymous namespace)::FailureDiagnosis::visitApplyExpr(swift::ApplyExpr*) (/usr/bin/swift+0x14667e1) #10 0x000000000144d4d6 swift::ASTVisitor<(anonymous namespace)::FailureDiagnosis, bool, void, void, void, void, void>::visit(swift::Expr*) (/usr/bin/swift+0x144d4d6) #11 0x0000000001446642 swift::constraints::ConstraintSystem::diagnoseFailureForExpr(swift::Expr*) (/usr/bin/swift+0x1446642) #12 0x000000000144cb76 swift::constraints::ConstraintSystem::salvage(llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::Expr*) (/usr/bin/swift+0x144cb76) #13 0x0000000001352138 swift::TypeChecker::solveForExpression(swift::Expr*&, swift::DeclContext*, swift::Type, swift::FreeTypeVariableBinding, swift::ExprTypeCheckListener*, swift::constraints::ConstraintSystem&, llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::OptionSet<swift::TypeCheckExprFlags, unsigned int>) (/usr/bin/swift+0x1352138) #14 0x0000000001356465 swift::TypeChecker::typeCheckExpression(swift::Ex
Avatar
コンパイラ死ぬコード見つけた
11:26 AM
コード自体壊れてるので、実害?は無い?けど。
Avatar
vicktorManuel 10/18/2018 5:17 PM
@swift-4.2.4 let display.Name: String = "hola" print(display.Name)`
Avatar
exit status: 1 with stderr:<stdin>:2:12: error: consecutive statements on a line must be separated by ';' let display.Name: String = "hola" ^ ; <stdin>:2:17: error: consecutive statements on a line must be separated by ';' let display.Name: String = "hola" ^ ; <stdin>:2:17: error: expected expression let display.Name: String = "hola" ^ <stdin>:2:5: error: type annotation missing in pattern let display.Name: String = "hola" ^ <stdin>:2:13: error: reference to member 'Name' cannot be resolved without a contextual type let display.Name: String = "hola" ~^~~~
Avatar
SwiftってdeinitがあるからRAIIパターンが書けるっていうメリットがあるとされてると思うんですが、 例えばinitでファイルハンドルを開いてdeinitで閉じるようなパターンを実装する時、 閉じるときに生じた例外をハンドリングできないという問題があると思ってて それについて最近思ったのが、 deinitがthrowsつけられてもよいのでは?ということで そうすると、throwing deinitな型をスコープに持っている関数がthrows化するのと、 そういう型の var に対する代入文が throws化するんだけど、 どう思います?
4:21 AM
func writeData() throws { // ここにclose失敗のthrowsが必要, スコープ脱出時だからtry catchはできない let stream = try OutputStream() try stream.write("aaa") } (edited)
Avatar
直感曰くクラスフィールドに持たせた時に難しそう
Avatar
setterがthrows付きになる
4:21 AM
あとsubscriptもか。
4:21 AM
現状仕様だとそれが通らんね・・・
Avatar
throws deinitをフィールドに持つならそのクラスもthrows deinit扱いにする必要があるが
Avatar
お、たしかに。
Avatar
シェアされている場合もありなかなか難しそうだ
Avatar
stored propertyで持っている場合は throws deinit が伝搬するけど、 computed property の場合はそうではないね
Avatar
現状だとどうするのが良いのかな
4:24 AM
errorhandlerをアタッチするしか無い?
Avatar
deinitから外に通知するしか無いと思う
Avatar
deinit時はproperties全部生きてるよね、errorHandlerで良さそうかなとは思う
Avatar
生きてる
Avatar
スコープ脱出時だからtry catchはできない
これについては do で囲んだらちょうどスコープ脱出時になるのでは?
Avatar
お、たしかに。
4:27 AM
変数を置くためのスコープを作るdoがcatch用のdoと共用できますね
Avatar
do { let stream = try OutputStream() try stream.write("aaa") } catch ... { // stream が破棄されて deinit の throws も catch }
4:28 AM
変数を置くためのスコープを作るdoがcatch用のdoと共用できますね
だね
Avatar
↑そう書ければそれ自体は良さそうに感じるんだけどなあ
Avatar
Javaはデストラクタでthrowsあるんでしたっけ
Avatar
If an uncaught exception is thrown during the finalization, the exception is ignored and finalization of that object terminates.
4:31 AM
Possible Duplicate: method finalize and exceptions The garbage collector invokes finalize() method when an object is about to released from memory. What happens when an exception is raised in ...
Avatar
これってでもすごく難しいような・・・ struct Foo { var a: Any func bar(_ out: OutputStream) { a = out } func baz() { do { let stream = try OutputStream() bar(stream) } catch let error { // ここで stream が破棄されるか調べるのが大変 ... } } }
Avatar
自動的に無視されるようだ
Avatar
明示的に呼び出せないdeinitthrowsにするのは無茶な気がする。
Avatar
Ownershipで endScope<T>(T) が入ると明示的に呼び出せる・・・
4:32 AM
endScopeに渡した変数はそのスコープでそれ以降使用できない。(初回代入をする前のletのような扱い
4:32 AM
Any型が全部throwになっちゃうのか!w
Avatar
あー
Avatar
オシマイみがあるな
Avatar
それはそうなる、やばそう
Avatar
親の deinitthrows がついてないと子の deinitthrows つけられないし厳しそう
4:34 AM
いや、それはそれでいいのか
Avatar
それ自体はコンパイラで保証できますね
4:34 AM
そうなってなければ型エラー
Avatar
Java みたいにすべてのクラスが Object を継承してるわけじゃないから。
4:35 AM
Any はクラスじゃないし。でも existential が破綻するのか。
Avatar
破綻するというかAnyとかExistentialとかスーパータイプ的なやつらは全部 deinit throws になっちゃいますね
Avatar
deinit throwsを格納するための型アノテーションが必要そう
Avatar
それか逆に、 Anyとそれとは別に Any<throwing deinit> みたいな型をわけるか。
Avatar
throws AnyはAnyのスーパータイプ (edited)
Avatar
throwing deinitな型はthrowing deinitなスーパータイプにしかアップキャストできない、とする。
Avatar
関数のthrowsと似た扱いなのかな
Avatar
deinit throwsが公開されてる型なのかチェックしないといけないとか、無理すぎる。
Avatar
endScopeがあるなら
4:38 AM
明示的deinitを追加してそっちでやる方が健全ぽいけど
Avatar
@swift-4.2.4 func run(_ body: @escaping () -> Void) { body() } class Foo { var a: Int = 42 func bar() { run { a += 1 } } }
Avatar
exit status: 1 with stderr:<stdin>:9:13: error: reference to property 'a' in closure requires explicit 'self.' to make capture semantics explicit a += 1 ^ self.
Avatar
@swift-4.2.4 @swift-main func run(_ body: @escaping () -> Void) { body() } class Foo { var a: Int = 42 func bar() { func incrementA() { a += 1 } run(incrementA) } }
Avatar
no output
Avatar
swiftNightly BOT 10/23/2018 6:08 AM
no output
Avatar
↑ってローカル関数の場合は self. いらないんですっけ?仕様?チェック漏れ?
Avatar
仕様です
6:09 AM
{ } で書いたときと func で書いた時で self の暗黙キャプチャ挙動が変わる
🤔 1
6:10 AM
funcのときも self 明記しようぜ ってスレも何度か立ってますよ
😀 1
Avatar
funcのときも self 明記しようぜ
メソッドでなく、メソッドの中のローカル func (↑の incrementA )について?
(edited)
Avatar
そうですね
👌 1
Avatar
↓こんなメソッド( write(to:) )あるの初めて知った。 @swift-4.2.4 var out = "" "abc".write(to: &out) "def".write(to: &out) print(out)
Avatar
abcdef
Avatar
知りませんでした。 + 演算子と何が違うん?と思いましたが、 to: の先は TextOutputStream なんですね。
Avatar
しかも、 StringTextOutputStream というのがおもしろいです。
8:30 AM
String は可変長配列のように末尾に効率的に文字列を追加できるので、文字列を書き出す対象になれるということですね。一方で、(値型なので)他の言語でよくあるイミュータブルな文字列インスタンスと同じような性質も持っていると。
8:36 AM
Java の StringStringBuilderWriter を合わせたような感じの役割を果たしてる感じでしょうか。
👀 1
Avatar
dump(to:) も同じ感じですね。これが TextOutputStream な理由は、(1) 標準出力とかに吐き出す都合で直接吐けた方が楽 or (2) 単にでかいテキストの末尾追加が発生しやすいから、のどちらかだと思うんですが、多分 1 ? https://developer.apple.com/documentation/swift/1641218-dump# (edited)
Avatar
@Kuniwak 値型 String なことで stream 的な性質を併せ持つこともできたということじゃないでしょうか?できるならそうしたいけど参照型のイミュータブルな String ではできなかったという意味合いで。
3:23 PM
@swift-4.2.4 func foo(_ x: UInt8) { print("UInt8: \(x)") } func foo(_ x: Int) { print("Int: \(x)") } foo(.max)
Avatar
exit status: 1 with stderr:<stdin>:10:6: error: ambiguous use of 'max' foo(.max) ^ Swift.UnsignedInteger:4:23: note: found this candidate public static var max: Self { get } ^ Swift.SignedInteger:4:23: note: found this candidate public static var max: Self { get } ^
Avatar
@swift-4.2.4 func foo(_ x: UInt8) { print("UInt8: \(x)") } func foo(_ x: Int) { print("Int: \(x)") } foo(.max - 1)
Avatar
Int: 9223372036854775806
Avatar
1Int と推論されて、それによって .max の型が Int と推論され、 Int.max になってる?
3:25 PM
.max じゃダメだけど .max - 1 だと OK なのが、おもしろいというかわかりにくいというか・・・
Avatar
リテラルについてはambiguityがないようになってるんですねぇ
Avatar
リテラルはLiteralConvertibleとは別に、デフォルト型が定まってるからかな
Avatar
@swiftbot func foo(_ x: UInt8) { print("UInt8: \(x)") } func foo(_ x: UInt16) { print("Int: \(x)") } foo(.max+0)
🛠 1
Avatar
Author icon
t.ae
func foo(_ x: UInt8) { print("UInt8: \(x)") } func foo(_ x: UInt16) { print("Int: \(x)") } foo(.max+0)
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:9:9: error: ambiguous use of operator '+' foo(.max+0) ^ Swift.UInt8:9:24: note: found this candidate public static func + (lhs: UInt8, rhs: UInt8) -> UInt8 ^ Swift.UInt16:9:24: note: found this candidate public static func + (lhs: UInt16, rhs: UInt16) -> UInt16 ^
Avatar
優先順位じゃなくてデフォルトIntが決まってるだけなんですね。
12:56 AM
確かに自作の型とか入ってくると優先順位付けようがないですしね。
Avatar
ExpressibleBy...Literal があるから任意の型に任意のリテラルを設定できるけど、何も指定しなかった場合のデフォルトは決まってて、その関係で 1 の型が決定されて .max の型も推論されてると思われる。
2:38 AM
@swift-4.2.4 let a = .max - 1 print(a) let b: UInt8 = .max - 1 print(b)
Avatar
9223372036854775806 254
Avatar
↓はコンパイルエラー @swift-4.2.4 let a = .max
Avatar
exit status: 1 with stderr:<stdin>:2:10: error: reference to member 'max' cannot be resolved without a contextual type let a = .max ~^~~
Avatar
@Kuniwak 値型 String なことで stream 的な性質を併せ持つこともできたということじゃないでしょうか?できるならそうしたいけど参照型のイミュータブルな String ではできなかったという意味合いで。
む、ここの koher さんの意図がわかりませんでした。。。
Avatar
@Kuniwak 僕が @Kuniwak さんの言いたかったことをちゃんと理解してない気がしてきました。
dump(to:) も同じ感じですね。これが TextOutputStream な理由は、(1) 標準出力とかに吐き出す都合で直接吐けた方が楽 or (2) 単にでかいテキストの末尾追加が発生しやすいから、のどちらかだと思うんですが、多分 1 ?
この「これが TextOutputStream な理由」の前には「○○ではなく」が隠れている気がするんですが、「○○」は何でしょう? String ?標準出力?
Avatar
@swift-4.2.4 -Xfrontend -debug-constraints func foo(_ x: UInt8) {} func foo(_ x: Int) {} foo(.max - 1)
Avatar
stderr:---Constraint solving for the expression at [<stdin>:6:1 - line:6:13]--- ---Initial constraints for the given expression--- (call_expr type='()' location=<stdin>:6:1 range=[<stdin>:6:1 - line:6:13] arg_labels=_: (overloaded_decl_ref_expr type='$T0' location=<stdin>:6:1 range=[<stdin>:6:1 - line:6:1] name=foo number_of_decls=2 function_ref=single decls=[ main.(file).foo@<stdin>:2:6, main.(file).foo@<stdin>:4:6]) (paren_expr type='($T6)' location=<stdin>:6:10 range=[<stdin>:6:4 - line:6:13] (binary_expr type='$T6' location=<stdin>:6:10 range=[<stdin>:6:5 - line:6:12] (overloaded_decl_ref_expr type='$T1' location=<stdin>:6:10 range=[<stdin>:6:10 - line:6:10] name=- number_of_decls=20 function_ref=unapplied decls=[ Swift.(file).Float.-, Swift.(file).Double.-, Swift.(file).Float80.-, Swift.(file).UInt8.-, Swift.(file).Int8.-, Swift.(file).UInt16.-, Swift.(file).Int16.-, Swift.(file).UInt32.-, Swift.(file).Int32.-, Swift.(file).UInt64.-, Swift.(file).Int64.-, Swift.(file).UInt.-, Swift.(file).Int.-, Swift.(file).FloatingPoint.-, Swift.(file).Numeric.-, Swift.(file).BinaryInteger.-, Swift.(file).Strideable.-, Swift.(file).Strideable.-, Swift.(file).Strideable.-, Swift.(file).Strideable.-]) (tuple_expr implicit type='($T4, $T5)' location=<stdin>:6:5 range=[<stdin>:6:5 - line:6:12] (unresolved_member_expr type='$T4' location=<stdin>:6:6 range=[<stdin>:6:5 - line:6:6] name='max' arg_labels=') (integer_literal_expr type='$T5' location=<stdin>:6:12 range=[<stdin>:6:12 - line:6:12] value=1))))) Score: 0 0 0 0 0 0 0 0 0 0 0 Type Variables: $T0 [lvalue allowed] subtype_of_existential involves_type_vars bindings={} @ locator@0x68fcd10 [OverloadedDeclRef@<stdin>:6:1] $T1 [lvalue allowed] subtype_of_existential involves_type_vars bindings={} @ locator@0x68fce60 [Ove
Avatar
--- Solution #0 --- Fixed score: 0 0 0 0 0 1 0 0 0 0 0 Type variables: $T1 as (UInt8, UInt8) -> UInt8 @ locator@0x68fce60 [OverloadedDeclRef@<stdin>:6:10] --- Solution #1 --- Fixed score: 0 0 0 0 0 0 0 0 0 0 0 Type variables: $T1 as (Int, Int) -> Int @ locator@0x68fce60 [OverloadedDeclRef@<stdin>:6:10]
3:44 AM
enum ScoreKind { // These values are used as indices into a Score value. /// A fix needs to be applied to the source. SK_Fix, /// A reference to an @unavailable declaration. SK_Unavailable, /// An implicit force of an implicitly unwrapped optional value. SK_ForceUnchecked, /// A user-defined conversion. SK_UserConversion, /// A non-trivial function conversion. SK_FunctionConversion, /// A literal expression bound to a non-default literal type. SK_NonDefaultLiteral, /// An implicit upcast conversion between collection types. SK_CollectionUpcastConversion, /// A value-to-optional conversion. SK_ValueToOptional, /// A conversion to an empty existential type ('Any' or '{}'). SK_EmptyExistentialConversion, /// A key path application subscript. SK_KeyPathSubscript, /// A conversion from a string, array, or inout to a pointer. SK_ValueToPointerConversion, SK_LastScoreKind = SK_ValueToPointerConversion, };
3:44 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
3:44 AM
スコアの6つ目の要素が NonDefaultLiteral だから
3:45 AM
UInt8が選択された場合、これが1点になって、Intの0点が優先、っぽい。
Avatar
@koher
この「これが TextOutputStream な理由」の前には「○○ではなく」が隠れている気がするんですが、「○○」は何でしょう? String ?標準出力?
「戻り値 string ではなく」引数 inout TextOutputStream な理由みたいな感じですね
(edited)
Avatar
なるほど
Avatar
omochimetaru 11/8/2018 7:02 AM
@hironytic
そういえば、Existentialがそれ自身のプロトコルには準拠しない、っていうやつの理由は何なんでしょう?
@ukitaka によると https://qiita.com/ukitaka/items/8bcff4348c79d820ba32 Existential は { ∃X where X: Animal, X } の事で 、その考え方ではプロトコルに準拠してるのはXであって Existential ではないから、という説明になるらしいですけど、僕はよくわかってないです。
iOSのDiscordで定期的にあがる話題として「protocol型の値がそのprotocol自身にconformしていないのはなぜ?」というものがあります。 例えば以下のようなコードです。 ```swift protocol An...
Avatar
そうですよね。その @ukitaka さんのやつは何度か読んだことがあって、そちらの理由としては「Existential とはそういうものだから」ってことになるんだと思うんですけど、SwiftはExistentialを言語の裏側に隠していて、まるでプロトコルが型であるかのように、メソッドを呼び出したら暗黙的にOpening existentialを行うという振る舞いをさせているわけで。それなら、さらにExistentialがプロトコルに準拠してるように振る舞わせた方がわかりやすくはなりますよね。
7:30 AM
まあ、そうなったものをExistentialと呼んでいいのかどうかは知りませんが。
Avatar
omochimetaru 11/8/2018 7:34 AM
そうですね。パッケージングと unpackage + メソッド呼び出し に関しては Existential ではないかのように暗黙に実現されているのであれば、現状は中途半端で、その方針で突き進めたら普通に準拠してる扱いで良さそうだし、便利なのでは?と思います。
Avatar
Existential の乱用が始まりそうな気も。
Avatar
omochimetaru 11/8/2018 7:37 AM
ExistentialにExistentialが埋め込めちゃう問題もありますね
Avatar
ExistentialにExistentialが埋め込まれるパターンってできるんですかね?Existentialとしては見せてないから裏側で埋め込まずにうまくできそうな気もしますが。あくまで気がするだけでよくわかってません。
Avatar
omochimetaru 11/8/2018 7:42 AM
func package<T: P>(_ t: T) -> P { return t } let p0: P = package(Cat()) let p1: P = package(p0) こうすると入れ子になると思います。実装上それを避ける事はできそうですが、変なケースが生じないかとか、入れ子にならないことが正しいのか?とか気になります。 (edited)
Avatar
@swift-4.2.4 protocol P { var x: Any { get set } } struct S: P { var x: Any } let p: P = S(x: 42)
Avatar
no output
Avatar
Any も existential だからすでに埋め込めるのでは?
Avatar
omochimetaru 11/8/2018 7:44 AM
AnyをAnyで受けるときはprotocolで受けてないですよね
Avatar
↓でもいいか。 @swift-4.2.4 protocol Q {} protocol P { var x: Q { get set } } struct T: Q {} struct S: P { var x: Q } let p: P = S(x: T()) (edited)
Avatar
omochimetaru 11/8/2018 7:45 AM
ExistentialのAnyをExistentialのAnyに代入しているだけ
Avatar
no output
Avatar
埋め込むの言いたいことがわかってないのかも。↑の P には Q が埋め込まれてない?
Avatar
@omochimetaru Existentialを作るところで埋め込まずにコピーするとかできそうな気はしますが、本当に大丈夫かというのとflattenしていいのかというのは確かによくわからないですね。 (edited)
Avatar
omochimetaru 11/8/2018 7:46 AM
埋め込むというのは <T> T: P のときに T を P にアップキャストする挙動のことです
7:47 AM
プロパティでhas-aにするという事ではないです
Avatar
あ、 has-a のことかと思ってた。
Avatar
それって Existential がプロトコルに準拠するのと同じことを言ってない?? (edited)
Avatar
omochimetaru 11/8/2018 7:49 AM
func package<T: P>(_ t: T) -> P { // ここでPのExistentialが作られて、Tはその中に保持される return t } // これは普通 let p0: P = package(Cat()) // このとき、callee側ではPではなくT: Pとして来るので、 // 同じように T を保持する P が作られて、 結果的に P { P { T } } になりそう。 let p1: P = package(p0)
Avatar
その意味で捉えてましたが、これは has-a ではない?
7:50 AM
あ、「プロパティで」か。
Avatar
omochimetaru 11/8/2018 7:50 AM
has-a ではない、といったのは、koherの書いた protocol P { var x: Q { get set } } ↑ここを見て言いました
7:50 AM
Existentialの仕組み自体は has-a 的ですね。
Avatar
そのときは t を使おうとした瞬間に open されてもう一度 existential container に包まれるんじゃないのかなぁ。
Avatar
omochimetaru 11/8/2018 7:51 AM
tの型は P ではなく <T: P> だから、 open するコードが吐けなそう。
7:52 AM
一回目の呼び出しと同じ関数なので。
7:52 AM
P である Cat や、 P である Dog と同様に、 P である P としか見えない
Avatar
PT として扱おうとした時点で、暗黙的に open するんじゃない?
Avatar
omochimetaru 11/8/2018 7:52 AM
let p1: P = package(p0 /* あ〜ここか */)
Avatar
func foo<T: P>(_ t: T) { t.foo() }
Avatar
omochimetaru 11/8/2018 7:53 AM
たしかにそれなら。
Avatar
そっちじゃなくてコール側かと思ってたけど、
Avatar
omochimetaru 11/8/2018 7:53 AM
つまり実行時に もし func package の中で print(type(of: )) したときは、 Cat が得られるってことですね。
Avatar
↑のようなコードを考えたら TP でも動かないといけないわけで
7:54 AM
選択肢は open してから渡すか
7:54 AM
Existential でも普通のインスタンスのように振る舞わせる何かが間に挟まるか
7:54 AM
どっちかかなぁと思って、後者をイメージしてた。けど前者の方が素直かも。
Avatar
omochimetaru 11/8/2018 7:58 AM
Existential でも普通のインスタンスのように振る舞わせる何かが間に挟まるか
もしこの場合は、外側から見て区別がつかないので、入れ子になってしまいそう。
Avatar
たしかにそうかも。
Avatar
@swift-4.2.4 let b = Bool.random() switch b { case true: print("T") case false: print("F") }
Avatar
F
Avatar
↑が網羅性チェック通るのってなぜ? Bool だけ特殊?
Avatar
お、 @dynamicCallable の PR が作り直されていて [WIP] も外れてる。 https://github.com/apple/swift/pull/20305
This PR introduces the @dynamicCallable attribute, which enables nominal types to be "callable" via a simple syntactic sugar. This is the implementation of SE-0216. Read the proposal for ...
Avatar
omochimetaru 11/9/2018 1:24 AM
Swift5 branchingに間に合いそうですね
Avatar
あと一週間。ギリギリだなぁ。マージされてほしい。
Avatar
AnyHashable の実装みてたんですが、 associatedtype無しの Self 制約だけであれば protocol で type erasure 書けるんですねー。
3:17 AM
@swift-4.2.4 protocol Equattable { func equaals(to other: Self) -> Bool } extension Int: Equattable { func equaals(to other: Int) -> Bool { return self == other } } extension String: Equattable { func equaals(to other: String) -> Bool { return self == other } } protocol _AnyEquattableBox { func _unbox<T: Equattable>() -> T? func _equaals(to box: _AnyEquattableBox) -> Bool? } struct _ConcreteEquattableBox<Base: Equattable> : _AnyEquattableBox { var _baseEquattable: Base init(_ base: Base) { self._baseEquattable = base } func _unbox<T: Equattable>() -> T? { return (self as _AnyEquattableBox as? _ConcreteEquattableBox<T>)?._baseEquattable } func _equaals(to box: _AnyEquattableBox) -> Bool? { guard let rhs: Base = box._unbox() else { return nil } return _baseEquattable.equaals(to: rhs) } } struct AnyEquattable: Equattable { var _box: _AnyEquattableBox init<E: Equattable>(_ base: E) { _box = _ConcreteEquattableBox(base) } func equaals(to rhs: AnyEquattable) -> Bool { return _box._equaals(to: rhs._box) ?? false } } let intVal1 = AnyEquattable(1) let intVal2 = AnyEquattable(1) let intVal3 = AnyEquattable(2) let strVal = AnyEquattable("test") assert(intVal1.equaals(to: intVal2)) assert(!intVal1.equaals(to: intVal3)) assert(!intVal1.equaals(to: strVal))
Avatar
no output
Avatar
omochimetaru 11/9/2018 3:19 AM
!!ww
3:19 AM
classの継承関係にしてfatalErrorを書かないといけないところが、 protocol + struct になっているのか?
3:19 AM
TypeErasure 新方式だ
Avatar

Type erasure

swift では protocol を使うのが人気です。ある protocol を満たす複数の型があるとき、それらのどれでも代入できる互換性のある型が欲しくなることがあります。そのような型を type ...
Avatar
omochimetaru 11/9/2018 3:23 AM
なるほど・・・ Existentialが使える場合→associatedtypeがある場合→さらにSelfも使っている場合 っていう風にその記事を書いたときは整理したけど
3:23 AM
associatedtypeが無いけどSelfを使っている場合 というのが存在して
3:23 AM
その場合にはそのパターンが使えるんですね。
Avatar
https://github.com/apple/swift/blob/e7dd1c17b23d3080af490cd69c535d267052af52/stdlib/public/core/AnyHashable.swift#L59-L63 これの意味がわからない。_canonicalBox というのが何故必要なのか?
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 11/9/2018 3:30 AM
AnyHashable has numerous edge cases where two AnyHashable values compare equal but produce different hashes. This breaks Set and Dictionary invariants and can cause unexpected behavior and/or traps...
Avatar
https://github.com/apple/swift/blob/e7dd1c17b23d3080af490cd69c535d267052af52/stdlib/public/core/Dictionary.swift#L1670 などで、concrete type ごとにカスタマイズしているからでした。
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 11/9/2018 3:30 AM
ちょうどたどり着きつつ会った
3:33 AM
起点となるのは、AnyHashable.init冒頭の (base as? _HasCustomAnyHashableRepresentation)?._toCustomAnyHashable() ですね
3:33 AM
これでAnyHashableの中で捕まえておくboxを型固有のboxにできる穴が空いている
3:35 AM
let a = (42 as Int as AnyHashable) let b = (42 as NSNumber as AnyHashable) let c = (42 as Double as AnyHashable) a == b // true b == c // true a == c // was false(!), now true
3:35 AM
AnyHashable経由だと Int(42) == Double(42) なの・・・?
Avatar
むむ。
Avatar
@swift-4.2.4 print(AnyHashable(42 as Int) == AnyHashable(42.0 as Double))
Avatar
true
Avatar
omochimetaru 11/9/2018 3:36 AM
↑はそのcanonicalBoxが追加されたコミットのコミットメッセージ。
3:37 AM
@swift-4.1.3 print(AnyHashable(42 as Int) == AnyHashable(42.0 as Double))
Avatar
false
😨 1
Avatar
omochimetaru 11/9/2018 3:37 AM
ワーオw
Avatar
41の方が正しそう
Avatar
omochimetaru 11/9/2018 4:24 AM
@tarunon その前の話題の新しいErasureも見て
Avatar
いまみてる
Avatar
サブクラス問題を解決できなさそう
Avatar
omochimetaru 11/9/2018 5:24 AM
サブクラス問題って何?
Avatar
@swift-4.2.4 protocol AnyEquatableBox { func _unbox<T: Equatable>() -> T? func _equals(to box: AnyEquatableBox) -> Bool? } struct ConcreteEquatableBox<Base: Equatable>: AnyEquatableBox { var base: Base init(_ base: Base) { self.base = base } func _unbox<T>() -> T? where T : Equatable { return ((self as AnyEquatableBox) as? ConcreteEquatableBox<T>)?.base } func _equals(to box: AnyEquatableBox) -> Bool? { guard let rhs: Base = box._unbox() else { return nil } return base == rhs } } struct AnyEquatable: Equatable { var box: AnyEquatableBox init<E>(_ base: E) where E: Equatable { box = ConcreteEquatableBox(base) } static func == (lhs: AnyEquatable, rhs: AnyEquatable) -> Bool { return lhs.box._equals(to: rhs.box) ?? false } } class Animal: Equatable { static func == (lhs: Animal, rhs: Animal) -> Bool { return lhs === rhs } } class Cat: Animal { } let cat1 = Cat() let cat2 = cat1 as Animal assert(AnyEquatable(cat1) == AnyEquatable(cat2))
Avatar
exit status: 4 with stderr:Assertion failed: : file <stdin>, line 46 Current stack trace: 0 libswiftCore.so 0x00007fde1b750fa0 _swift_stdlib_reportFatalErrorInFile + 215 1 libswiftCore.so 0x00007fde1b4a95c1 <unavailable> + 1504705 2 libswiftCore.so 0x00007fde1b6e60c2 <unavailable> + 3850434 3 libswiftCore.so 0x00007fde1b4a8d0a <unavailable> + 1502474 4 libswiftCore.so 0x00007fde1b6e5f5c <unavailable> + 3850076 5 libswiftCore.so 0x00007fde1b4a8d0a <unavailable> + 1502474 6 libswiftCore.so 0x00007fde1b642a28 <unavailable> + 3181096 7 libswiftCore.so 0x00007fde1b4a85a9 <unavailable> + 1500585 9 swift 0x0000000001043efe <unavailable> + 12861182 10 swift 0x0000000001048022 <unavailable> + 12877858 11 swift 0x00000000004f8b42 <unavailable> + 1018690 12 swift 0x00000000004df0bb <unavailable> + 913595 13 swift 0x00000000004da3f0 <unavailable> + 893936 14 swift 0x000000000048a348 <unavailable> + 566088 15 libc.so.6 0x00007fde1e0f5740 __libc_start_main + 240 16 swift 0x0000000000488009 <unavailable> + 557065 #0 0x000000000410ac94 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x410ac94) #1 0x0000000004108b22 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4108b22) #2 0x000000000410ae42 SignalHandler(int) (/usr/bin/swift+0x410ae42) #3 0x00007fde1f9cb390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007fde1b642a30 $Ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtFTf4nxnnn_n (/usr/lib/swift/linux/libswiftCore.so+0x308a30) #5 0x00007fde1b4a85a9 (/usr/lib/swift/linux/libswiftCore.so+0x16e5a9) #6 0x0000
Avatar
これってBox式もそうだっけ
Avatar
omochimetaru 11/9/2018 5:32 AM
同じ気がする クラッシュ回避のためにEquatableについてはboxの型が同じかどうかをチェックしても良さそう
Avatar
しかし生成時に型が焼き込まれてしまうのでうまく動かすのは難しそうだなぁ
Avatar
omochimetaru 11/9/2018 5:38 AM
ああ読み違えてた CatとDogじゃなくてCatとAnimalか
Avatar
norio_nomura 11/9/2018 5:43 AM
print(AnyHashable(42 as Int) == AnyHashable(42.0 as Double))の挙動は意図したものなのね。 https://github.com/apple/swift/pull/17396
AnyHashable has a few corner cases where it's not correctly conforming to Equatable and Hashable. This breaks Set and Dictionary invariants and can cause unexpected behavior and/or traps. This ...
Avatar
omochimetaru 11/9/2018 6:04 AM
@swift-4.2.4 class Animal : Hashable { static func ==(a: Animal, b: Animal) -> Bool { return a === b } func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } } class Cat : Animal {} class Dog : Animal {} let a = Cat() let b: Animal = a let c: Animal = Dog() print(AnyHashable(a) == AnyHashable(c), 3) (edited)
Avatar
false 3 (edited)
Avatar
omochimetaru 11/9/2018 6:09 AM
@tarunon なんかAnyHashableはサブクラス問題大丈夫っぽい
Avatar
hashは型情報いらないからね
Avatar
omochimetaru 11/9/2018 6:10 AM
Hashable is Equatableだよ
Avatar
だとすると、AnyHashableに包んで==比較すると
Avatar
omochimetaru 11/9/2018 6:11 AM
AnyHashableに入れるためにはHashableに準拠させるためにstatic func ==とfunc hash(into:) の実装が必要
Avatar
hashは取れるけどequatabiltyは壊れてるのがAnyHashableという理解
6:12 AM
boxに詰めたオブジェクトについて保証されないのでは
Avatar
omochimetaru 11/9/2018 6:12 AM
仮にそうだったとしたらDictionaryのKeyやSetのElementとして使い物にならんけど・・・どういうこっちゃ
Avatar
norio_nomura 11/9/2018 6:25 AM
AnyHashableを作るときに、どんな_AnyHashableBoxを使うかカスタマイズできる_HasCustomAnyHashableRepresentationってのがあって、元がDoubleでもInt64(exactly:)で表現可能なら、_IntegerAnyHashableBoxを使う仕組みになってる。 https://github.com/apple/swift/blob/master/stdlib/public/core/FloatingPointTypes.swift.gyb#L1820-L1831
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
👀 1
Avatar
omochimetaru 11/9/2018 6:26 AM
exactlyの正しい使い方だ
Avatar
norio_nomura 11/9/2018 6:27 AM
それによりAnyHashable(42 as Int) == AnyHashable(42.0 as Double)trueになる。
Avatar
omochimetaru 11/9/2018 6:27 AM
じゃあその右辺値が評価された時点で、本当に同じ構成のオブジェクトになってるんですね
6:28 AM
比較する時点でやるよりそのほうが処理も早そうだ
Avatar
norio_nomura 11/9/2018 6:32 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
6:38 AM
_AnyHashableBoxinternalだから、stdlib外の型ではカスタマイズ出来ないな。
Avatar
@swift-4.2.4 protocol AnyEquatableBox { func _unbox<T: Equatable>() -> T? func _equals(to box: AnyEquatableBox) -> Bool? } struct ConcreteEquatableBox<Base: Equatable>: AnyEquatableBox { var base: Base init(_ base: Base) { self.base = base } func _unbox<T: Equatable>() -> T? { return self.base as? T } func _equals(to box: AnyEquatableBox) -> Bool? { guard let rhs: Base = box._unbox() else { return nil } return base == rhs } } struct AnyEquatable: Equatable { var box: AnyEquatableBox init<E>(_ base: E) where E: Equatable { box = ConcreteEquatableBox(base) } static func == (lhs: AnyEquatable, rhs: AnyEquatable) -> Bool { return lhs.box._equals(to: rhs.box) ?? false } } class Animal: Equatable { static func == (lhs: Animal, rhs: Animal) -> Bool { return lhs === rhs } } class Cat : Animal {} class Dog : Animal {} let a = Cat() let b: Animal = a let c: Animal = Dog() assert(AnyEquatable(a) == AnyEquatable(b)) assert(AnyEquatable(a) != AnyEquatable(c)) assert(AnyEquatable(b) == AnyEquatable(a)) assert(AnyEquatable(b) != AnyEquatable(c)) assert(AnyEquatable(c) != AnyEquatable(a)) assert(AnyEquatable(c) != AnyEquatable(b))
Avatar
no output
Avatar
_unbox を シンブルな conditional cast に変えただけ。
Avatar
omochimetaru 11/9/2018 6:53 AM
lhsがConcreteEquatableBox<Cat> の場合は、box._unbox()が T == Cat で呼び出されて、内部で as? Cat、 Cat.== が呼ばれる rhsがConcreteEquatableBox<Animal> の場合は、 box._unbox() が T == Animal で呼び出されて、内部で as? Animal、 Animal.== が呼ばれる か
6:54 AM
Cat.== と Animal.== の反射律は Cat と Animal の実装が責任を持ってるからおかしなことはナシと
6:54 AM
そっかそれだけか
Avatar
norio_nomura 11/9/2018 7:27 AM
それだと_ObjectiveCBridgeableの影響を受けそう。
Avatar
@rintaro ちゃんとできてる!ありがとうございます ところでこのパターン、シンプルなBoolを返す場合はいいけど、そこそこ込み入ったオブジェクトを返す場合は使えなさそうですね
Avatar
この前の↓だけど、このロジックでいけば JSONDecoder.decode とかは throws じゃなくて -> Result<...> であるべきということになりそうだけどどうだろう?
I think throws and Result can be seen as addressing different corners of the design space. As the rationale describes, throws was designed for systemic errors, which tend to have a large distance between error source and error handler, so source and handler end up needing to be rather loosely coupled, which was a motivator for the exception-like propagation and lack of specific typing in the current throws feature. Result on the other hand is great for conditions that are intended to be immediately handled by the caller, for which being an regular return value with a more specific failure type is in fact the more convenient representation.
https://forums.swift.org/t/adding-result-ii-unconstrained-boogaloo/17128/18
+1 to an unconstrained, two-argument Result type. Referring back to @John_McCall's original error handling rationale, I think throws and Result can be seen as addressing different corners of the design space. As the rationale describes, throws was designed for systemic errors...
4:04 AM
I/O エラーやネットワークエラーみたいなのを "systemic errors" と呼んでいるとすると、それらを Recoverable Error として throws で扱うのに対して、 JSON のデコードの失敗はもっと確定的な処理で、 "an regular return value with a more specific failure type" に適しているように感じる。一種の Simple Domain Error になる?
Avatar
これはそんな気がします
4:16 AM
throwsはエラーの原因とハンドラに距離があるときに適してて
4:17 AM
一方、JSONのデコードにおけるエラーは JSONのデータ構造と値だけにほぼ依存してて
4:17 AM
どこがどうおかしいとかキーパスで知りたいし
4:18 AM
JSONDecodeError みたいな型付きで戻ってきたら便利だと思う
4:19 AM
でも実際のところアプリケーションでそれによってハンドルすることがほぼないから、微妙だな
4:19 AM
ログがdumpできて、ユーザには「通信エラー」とだけ出しとけばいい、みたいなやつだから、型はいらないっちゃいらない
Avatar
そうすると、↑のロジックを正当化して Result が追加されると、既存 API を変更するか、もしくは言語の期待する使い分けと異なるデザインの API が放置されるかという状況になって、どっちになっても結構辛そうな気がする。
4:49 AM
そういう意見を投げたいところだけど、レビュー期間が終わってしまった。
Avatar
その場合、既存APIを変更するのが正しい道だと思います
5:05 AM
それで過去に引っ張られたら言語の進化がそこで止まってしまう。
Avatar
既存 API 変更できればいいけど、できないんじゃないかなぁ。
5:07 AM
String(data:using:) とかも Resultreturn すべきってことになるよね。
Avatar
なるほど
Avatar
あと、ユーザビリティの問題として、↓とかが throws じゃなくて Result になったらずいぶん使いづらいと思う。 https://developer.apple.com/documentation/swift/keyeddecodingcontainer/2921334-decode (edited)
Avatar
Kishikawa Katsumi 11/14/2018 5:09 AM
Resultを返す別のAPIを追加したらよくて、Decodableの場合は別のJSONDecoderを追加したらいい。
5:09 AM
String(data:using:) の例も別のメソッド/イニシャライザでOK
Avatar
@Kishikawa Katsumi それだと "addressing different corners of the design space" ということにならなくないですか?
5:10 AM
Joe Groff は "systrmic error" に throws を使うべきと言っていて
5:11 AM
両方用意しておけば良いということになれば、 API 設計がぐちゃぐちゃになりそうに思います。
Avatar
Kishikawa Katsumi 11/14/2018 5:12 AM
Resultsとthrowsはそれぞれ別の問題を、、、というは多分同意で、 それでJSONDecoderも一部のエラーはResultの方が良いというのも私は多分同意
Avatar
僕は多くのケースで最適なものを用意しておいて、それが適さないケースでは適宜変換して使う(簡単に変換できる)というのが望ましいと思います。
Avatar
Kishikawa Katsumi 11/14/2018 5:12 AM
ただ既存のAPIをどうするという問題はあってそれは別問題で、
その場合、既存APIを変更するのが正しい道だと思います それで過去に引っ張られたら言語の進化がそこで止まってしまう。
Avatar
なるほど。「既存のAPIをどうするという問題」への対処として、ということですね。
Avatar
Kishikawa Katsumi 11/14/2018 5:13 AM
^ これに対する応答として、一般的な解は一時的に共存しつつ、どちらかを漸進的にDeprecateしていくようにすべき、
5:13 AM
という意見です。
🙂 1
Avatar
なるほど。
Avatar
Kishikawa Katsumi 11/14/2018 5:14 AM
それで過去に引っ張られたら言語の進化がそこで止まってしまう。
^ 実はこれには完全同意なんですけど、もはやそれをしてはいけないという意見も同時に私の中にある。
Avatar
「もはやそれをしてはいけない」の「それ」は「進化」ですか?
5:15 AM
それとも「止ま」ること?
Avatar
Kishikawa Katsumi 11/14/2018 5:15 AM
いや、破壊的な変更を伴う、です。
5:15 AM
進化は必要でどこかで古いものを捨てる、破壊するは必要なんですけど、
💪 1
Avatar
(破壊的な変更を伴う)「進化」ということですね。
Avatar
Kishikawa Katsumi 11/14/2018 5:16 AM
JSONのAPIだけに限るとしても、フルスクラッチみたいなことをするのは良くない、と思いますね。
5:17 AM
これは個人的な意見ですけど、Resultを入れると既存のサードパーティ製のResultを使ったコードが死ぬ、というのは現段階では気にしなくて良いと思います。この感覚の違いを言語化するのは難しいんですけど。
Avatar
難しいところですね。現実的にはある程度長期に( 5 年とか)互換性を保つことを保証しつつ、その保証期間を超えるときにまとめて破壊して進化とかでしょうねー。
5:18 AM
本当はそれがメジャーバージョンアップな気がしますが、 Swift のメジャーバージョンは軽く扱われてるので・・・。
5:19 AM
Resultを入れると既存のサードパーティ製のResultを使ったコードが死ぬ、というのは現段階では気にしなくて良いと思います。
これは僕も気にしなくて良いと思います。
5:20 AM
ただ、今の Swift はまだその段階(互換性を気にすべき)に達していないと思っていて、
5:21 AM
Swift のバージョンの前には 0. を付けた感じだと思うんですよね。
5:21 AM
今は 0.4.2 みたいな。
5:21 AM
で、これを 1.0 にした段階で 1.x の間は後方互換を保ち、そのスパンが 5 年くらいがいいのかなと。
5:22 AM
サポート期間はもっと長くてもいいのかも。
Avatar
Kishikawa Katsumi 11/14/2018 6:11 AM
ただ、今の Swift はまだその段階(互換性を気にすべき)に達していないと思っていて
これはまあ実際そうだと思いますが、 これは自然に訪れるものではなくて、理想を求めたらいつまでも終わらないので、 公開して使ってもらう、そして公開した以上は互換性を(ある程度)守りながら進化させていくっていうのは必要かなと。
Avatar
そういう意味では、現状は「公開した以上は互換性を(ある程度)守りながら進化させていく」になってそうですね。現状で目に見えている問題( async/awaitactor, typed throws など)が片付くまではそういう形を続けて、それらが片付いたらもう少しきっちり互換性を守るべきなのかなぁと思います。
Avatar
throws は "systemic error" に用いるべきというのもちょっと懐疑的で、↓のようになるのが望ましいと思えない・・・。結局 Resultthrows のための get だらけ。 extension Foo: Decodable { init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.a = try container.decode(Int.self, forKey: .a).get() self.b = try container.decode(String.self, forKey: .b).get() } }
6:44 AM
しかもinitResultreturn できないから throws にせざるを得ない。
Avatar
init(from decoder:) が throws じゃなくて JSONError を返す Result になる気がする。
6:44 AM
initだからできないというのはそうですね。
6:44 AM
てか、その目的で置換するなら先にtyped throws が必要なのでは。
Avatar
init? のようなものを導入するなら、昔僕が提案してたみたいな | を導入して、 T|EResult<T, E> のシュガーにした上で、 init| とか導入しないと・・・。
Avatar
init(from decoder: ) throws(JSONError) とか。
Avatar
それだと typed throws と Resultreturn の両方を扱えないよ。
Avatar
returnの両方?
Avatar
initthrow する場合と Resultreturn する場合の両方を扱えないといけないはず。
Avatar
あ、そこで区切るのか。
Avatar
String.init(data:using:)Resultreturn したいけど、 Database.init(path:)throw したいはず。
Avatar
ふむ throwsと -> Result の扱いを分けないといけないのか
Avatar
正直、適切に使い分けられると思えないので、コミュニティで二つのスタイルが混在してコード書きづらくなりそう。
Avatar
ユーザ側で取り扱いたいときだけ Result { try hoge() } で Result化すればいいような気がしてきたな
Avatar
多分本当に Result が必要なのって、 async/await に対する Future みたいなもので、局所的にしかたなく使うものであって、 API に現れる種類のものじゃないと思うんよね。
6:54 AM
↑を init じゃなくて Resultreturn するメソッドとすると↓になる。 extension Foo: Decodable { static func from(_ decoder: Decoder) -> Result<Foo, DecodeError> { return Result { let container = try decoder.container(keyedBy: CodingKeys.self) let a = try container.decode(Int.self, forKey: .a).get() let b = try container.decode(String.self, forKey: .b).get() return Foo(a: a, b: b) } } }
6:54 AM
何もうれしくない。
6:54 AM
もし間に getthrows への変換を挟まないともっと悲惨になる。
6:56 AM
extension Foo: Decodable { static func from(_ decoder: Decoder) -> Result<Foo, DecodeError> { let container = try decoder.container(keyedBy: CodingKeys.self) let a: A switch container.decode(Int.self, forKey: .a) { case .success(let value): a = value case .failure(let error): return .failure(error) } let b: B switch container.decode(Int.self, forKey: .b) { case .success(let value): b = value case .failure(let error): return .failure(error) } return .success(Foo(a: a, b: b)) } } (edited)
6:58 AM
decodeResultreturn するようにしても何がうれしいのかさっぱりだし、 decodethrows のままにするならどこで Result 使うの?って感じ。
6:58 AM
すごく限定的な用途しかなさそう。
7:02 AM
それか Functional な道を開いて↓になる。さすがにこれはない。 extension Foo: Decodable { static func from(_ decoder: Decoder) -> Result<Foo, DecodeError> { return decoder.container(keyedBy: CodingKeys.self).flatMap { container in return curry(Foo.init) <^> container.decode(Int.self, forKey: .a) <*> container.decode(String.self, forKey: .b) } } }
Avatar
John McCall の↓はより限定的な Result の利用を推奨してる? I want to clarify that I favor adding Result only to address situations where manual propagation is necessary. Manual propagation will always occasionally be useful; adding async/await (or whatever we end up doing) will surely eliminate most of the most common situations, but they'll still exist, e.g. when using futures (which are the equivalent of manual propagation for async/await and accordingly trigger similar requirements). I will continue to recommend against using Result as an alternative mechanism for ordinary propagation of errors, although I have no doubt that some people will insist on doing so; and I continue to believe that using a different error type than Error is generally misguided for the same reason it's generally misguided with ordinary error-handling. I also worry that the ergonomics of this type are significantly hurt by the attempt to support typed errors and (especially) non-Error-conforming errors. https://forums.swift.org/t/se-0235-add-result-to-the-standard-library/17752/129
I want to clarify that I favor adding Result only to address situations where manual propagation is necessary. Manual propagation will always occasionally be useful; adding async/await (or whatever we end up doing) will surely eliminate most of the most common situations, bu...
Avatar
レビュー期間終わってたけど気になったので書いてみた。 https://forums.swift.org/t/se-0235-add-result-to-the-standard-library/17752/183
Although the review period is over, please let me leave my comment. I have been thinking about it for days. If I correctly understood what you intended in the comment below you linked, it seems to suggest that JSONDecoder.decode(_:from:) returns Results instead of throwing...
Avatar
SE-0235: Add Result to the Standard Library has been revised and is now open for review through Sunday, December 2nd. Based on the first round of feedback, the core team agrees that this feature is worth adding to Swift, and we are now looking for feedback on our proposed re...
11:35 PM
https://github.com/apple/swift-evolution/commit/db086de27804f6103ab8cde8801d41eb67edca38 -public enum Result<Value, Error> { - case success(Value), failure(Error) +public enum Result<Value, Error: Swift.Error> { + case value(Value), error(Error) } (edited)
Revise SE-0235 with core team feedback and put it back in review
Avatar
Avatar
情報量が濃厚だ ちゃんと訳してみよう
Avatar
大分好みな感じになった。
1:28 AM
変なメソッドが除去されて必要最小限でいい感じ。
1:28 AM
Error: Swift.Error になったのもいいと思う。
1:30 AM
Result 乱用は絶対に起こると思うけど、 Result 追加するなら考えられる限りほぼベストな実装だと思う。
Avatar
ErrorのExistentialがErrorのprotocolにconformするようになってしまったのだけモニョる、他のExistentialもそうならいいけど特別扱いはなぁ (edited)
Avatar
たしかに。
Avatar
書いた。結局、 JSONDecoder.decode(_:from:)Resultreturn するのがいいの?それともしないのがいいの?って聞いてみた。 https://forums.swift.org/t/revised-se-0235-add-result-to-the-standard-library/18371/26
I agree on the changes. In particular, it looks great to me that the Error type parameters is constrained to conform to Swift.Error, with self-conformance, and the Result type has minimum APIs. I want a guideline when to use the Result type. Opinions seems divided even in ...
Avatar
Lifting this restriction in general is out of scope for Swift 5, but it can be lifted specifically for Swift.Error, making it conform to itself. Making that change is part of this proposal.
↑なので、 Swift 5 ではやらないけど Swift 6 以降のどこかではやるつもりなんじゃないでしょうか?
Avatar
↑それレス何番ですか?
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
👍 1
Avatar
あー、0235の提案書が、書き換えられてるのか。
Avatar
うん、実装(ってかインタフェース)も書かれてていい感じ。 @_frozen public enum Result<Value, Error: Swift.Error> { case value(Value) case error(Error) public func map<NewValue>( _ transform: (Value) -> NewValue ) -> Result<NewValue, Error> public func mapError<NewError>( _ transform: (Error) -> NewError ) -> Result<Value, NewError> public func flatMap<NewValue>( _ transform: (Value) -> Result<NewValue, Error> ) -> Result<NewValue, Error> public func flatMapError<NewError>( _ transform: (Error) -> Result<Value, NewError> ) -> Result<Value, NewError> public func unwrapped() throws -> Value } extension Result where Error == Swift.Error { @_transparent public init(catching body: () throws -> Value) } extension Result : Equatable where Value : Equatable, Error : Equatable { } extension Result : Hashable where Value : Hashable, Error : Hashable { }
Avatar
いきなりURLSEssionの例が
3:14 AM
Errorの場合のURLResponseのことが消えてるような
Avatar
あー、なんか変な気がしたけど、元がどうだったけなと思って読み飛ばした。
3:15 AM
Error: Swift:Error じゃできないことだった気がするから
3:15 AM
ああ、そうか
3:15 AM
Error の場合でも URLResponse を持ちたかったのか。
Avatar
URLSession.shared.dataTask(with: url) { (result: Result<(URLResponse, Data), (Error, URLResponse?)>) in // Type added for illustration purposes. switch result { case .success(let response): handleResponse(response.0, data: response.1) case .failure(let error): handleError(error) } }
3:15 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
3:16 AM
古いコミットのときの当該箇所。
3:16 AM
responseってプロパティを持ったエラー型にするのでもよいけど、いずれにせよResultのErrorパラメタがSwift.Errorで埋められているので、そうなってもいない。
Avatar
うん。消えてるね、これ。
3:18 AM
まあ、 Error 型のプロパティでやるのが順当だろうけど、元が Obj-C で NSError だからなぁ。
Avatar
NSErrorのエラー型は
3:18 AM
Domainに基づいてBridgeできるのでそこは大丈夫では。
3:18 AM
CocoaErrorとかURLErrorとか。
Avatar
URLResponse をすでに持ってる型なの?
3:20 AM
ブリッジできても URLRespose を持ってないのであれば解決しない気が。
Avatar
extension URLError { /// The URL which caused a load to fail. public var failingURL: URL? { get } /// The string for the URL which caused a load to fail. public var failureURLString: String? { get } /// The state of a failed SSL handshake. public var failureURLPeerTrust: SecTrust? { get } }
3:20 AM
URLResponseは持ってないですね。
Avatar
じゃあ同等にはならないね・・・
3:20 AM
ってかさ、
3:21 AM
(result, response) を受け取るんでいいのでは?
3:21 AM
ちがうか
3:21 AM
成功のときに
3:21 AM
URLResponseOptional にしたくないのか。
3:22 AM
エラーケースはレスポンス以前に失敗してる可能性があるから Optional だけど
3:22 AM
成功ケースは確実にレスポンスが存在する。
Avatar
そもそもResponseが取れたけどエラーになるケースってなんなんだろう (edited)
3:22 AM
404だったりしたときでも、Dataに404ページのHTMLが入ってる気がする。
Avatar
うーん、たしかにレスポンスが存在する = Data が存在するな気もするな。
Avatar
ResponseはとれたけどResponse Bodyを全部受信できずにネットワークが死んだときとか?
Avatar
ヘッダーだけのときとか?
Avatar
その場合でも、「途中まで取れた分のData」は来るのかな・・・
Avatar
URLSession って 404 はエラーになるんだっけ?
Avatar
ならなかった気もする。
Avatar
レスポンスが存在する = 成功な気もするなぁ。
Avatar
https://developer.apple.com/documentation/foundation/nsurlsession/1407613-datataskwithrequest
If the request completes successfully, the data parameter of the completion handler block contains the resource data, and the error parameter is nil. If the request fails, the data parameter is nil and the error parameter contain information about the failure. If a response from the server is received, regardless of whether the request completes successfully or fails, the response parameter contains that information.
なので、data と error は exclusive だけど、response はエラー時でも入る可能性あることになっていますね。
🙏 1
Avatar
ありがとうございます。
3:27 AM
前見た時よくわからなかった記憶だったけどちゃんと書いてあった。
Avatar
じゃあやっぱり Proposal の例は URLResponse がエラーケースで失われてるのか・・・
Avatar
それはちょっと許容できないですね、ブリッジして何か減っちゃまずい。
Avatar
スレッド追ってみて誰も突っ込んでなければ書き込んでおこう。
3:47 AM
もともとの提案者のJonさんが
3:47 AM
ErrorパラメータにSwift.Errorの制約つけるんであれば、
3:47 AM
valueよりsuccessのほうがいいんじゃない?
3:47 AM
って言ってて面白い。
Avatar
Contribute to koher/SwiftResult development by creating an account on GitHub.
Avatar
クソリプ失礼した感あるけど書き込んどいた。
4:11 AM
@koher 公式が待てない人用・・・
Avatar
antitypical とかをこれで置き換えておけば移行が簡単。
Avatar
わかるけどスーパーニッチだ・・・
4:13 AM
@koher case value, errorには賛成なんですか?
4:13 AM
success/failureにしようって意見が結構投稿されてる。
Avatar
特に強い主張はないけど、 value, error でもいいんじゃないかなって感じ。
4:15 AM
↓返事もらえないけど変なこと言ってるかなぁ。 https://forums.swift.org/t/revised-se-0235-add-result-to-the-standard-library/18371/26
I agree on the changes. In particular, it looks great to me that the Error type parameters is constrained to conform to Swift.Error, with self-conformance, and the Result type has minimum APIs. I want a guideline when to use the Result type. Opinions seems divided even in ...
Avatar
nickさんが11で投稿している
4:15 AM
Success is the status of the Result. The Result was success, and the fruit of that success was a value. The value is not the status, especially (as others have pointed out) since that value may be of type Void in situations where we only care about the status.
4:15 AM
これが、なるほどと思いました。僕は。
4:20 AM
@koher 変では無さそう
Avatar
Result をいつ使うべきかが示されないと throws との使い分けで混乱を生みそう。
4:21 AM
示されても確実にそれが守られなくて混乱を生むだろうけど。 (edited)
Avatar
proposalで示されている例では非同期と
4:21 AM
すでにthrowsなやつをResult.init(catching:)で捕まえるシナリオだけですね
4:22 AM
最初からResultを返す同期関数の例はないし
Avatar
manual propagation が本当に必要な場合に限定するのか、
Avatar
JoeGroffも「エラー処理の主なやり方を変えるために導入するのではない」的なことを書いてますね
4:23 AM
Result is a way of storing potential errors; the idea here is not to promote it as a primary way of handling errors.
4:23 AM
しかも例のやつだとそれゆえに全部 <Error>が<Swift.Error>なんですよね
4:23 AM
<Error>を具体的なエラー型で埋めることで網羅検査できる話が出てこない・・・
Avatar
↑の Joe Groff のってどのコメント? (edited)
Avatar
レス20番。
🙏 1
Avatar
まあ、それだと JSONDecoder.decodethrows のままでいいって考えなのかなぁ?
Avatar
We know this because some of them have posted in the pitch and review mentioning that they already use their own Result type instead of try-throw-catch. That we can’t actually stop them from doing that is clear from the fact that they’re doing it now
JohnMccallのこのコメントを見てても、
4:27 AM
このスレの1を見てても、
4:27 AM
すでにResult使う人達がいる以上、公式のがあったほうがいいよね、みたいな
4:27 AM
気持ちを感じるというか・・・
Avatar
それを言い出したら、関数型スタイルで書く人がいるからモナドサポートした方がいいよねってなってしまう。
Avatar
うーんでも実際のところ
4:29 AM
そういうスレッドは
4:29 AM
そんなややこしいのいらなくね、みたいなコメントも付きがち
Avatar
すでにResult使う人達がいる以上
これの 9 割は async/await で解決できる非同期処理だと思うんよね。
Avatar
Several people expressed hope that a future async/await model would obsolete the most important use-case for Result. The core team agrees that async/await is likely to greatly diminish the importance of this type, but not so much as to make it completely useless, and the type will help standardize existing practice in ways that are likely to be useful for async/await.
Avatar
うん
Avatar
async/awaitで greatly diminishするって言ってますね。
Avatar
manual propagation が本当に必要な箇所で Result を使うのはいいとして
4:31 AM
Joe Groff のこれ↓は意外だったから、どういう気持なのかを聞きたい。 https://forums.swift.org/t/adding-result-ii-unconstrained-boogaloo/17128/18 (edited)
+1 to an unconstrained, two-argument Result type. Referring back to @John_McCall's original error handling rationale, I think throws and Result can be seen as addressing different corners of the design space. As the rationale describes, throws was designed for systemic errors...
Avatar
「それでも完全に不要にはならないし、既存のpracticeで使われてるから標準化すると便利だろう」てつないでるからなあ
4:32 AM
あ、でも、既存のpracticeでいえば、RxSwift/RACでの用法は
4:32 AM
Observableはasync/awaitで置換できないから
4:32 AM
そのあたりはガッツリ残るのでは。
Avatar
それはそうだね。
Avatar
Result on the other hand is great for conditions that are intended to be immediately handled by the caller, for which being an regular return value with a more specific failure type is in fact the more convenient representation.
4:36 AM
この発言をしたときの
4:36 AM
想像してた具体的なシナリオが気になりますね。
4:38 AM
もしかしたら、JSONのdecodeを持ってきたところにすれ違いがあって、よくわからんって思われたのかも?
Avatar
うーん、
I think throws and Result can be seen as addressing different corners of the design space. As the rationale describes, throws was designed for systemic errors, which tend to have a large distance between error source and error handler, so source and handler end up needing to be rather loosely coupled, which was a motivator for the exception-like propagation and lack of specific typing in the current throws feature.
↑は JSON の decode を含まなさそうだけどなぁ。
Avatar
Note that it's equally unclear how to translate that into async/await, which is not coincidental. async throws -> Data with an inout URLResponse? parameter?
6:02 AM
URLResponseの件、 async/awaitにするときどうすんだべってJohnがw
Avatar
そもそも dataTaskURLSessionDataTaskreturn してるから async/await にできない。
Avatar
むむ。
Avatar
で、これは API 設計の問題だと思ってて、 URLSessionDataTaskfunc completion() async throws -> (Data, URLResponse) というメソッドを追加するのがいいと思う。
Avatar
おお〜
Avatar
で、ショートカットでキャンセラーがいらないときは
Avatar
でもそれだとまだ、エラーのときのURLResponse問題は残ってますね。
Avatar
それは Typed Throws でかいけつする。
Avatar
struct URLSessionDataTaskError : Error { var response: URLResponse? var error: Error } (Result<(Data, URLResponse), URLSessionDataTaskError>) -> Void
6:09 AM
↑この路線ですか?
Avatar
URLSessionDataTask に func completion() async throws URLSessionDataTaskError -> (Data, URLResponse) (edited)
Avatar
いま41として書き込んだんですけど。
6:10 AM
これちょっと変なんですよね
6:10 AM
エラーの実体は内側にあって、そこの型がいろいろかわるので
6:10 AM
responseをアタッチしてるだけのエラー型は
6:10 AM
それ自体エラーを表してるというのは変な気がする。
6:10 AM
Typed throwsも本来はエラーの種類?を表すはずなのに
6:11 AM
「エラーのときの付加情報」を追加するために新しいエラー型が産まれてるのが変な感じが。
Avatar
理想的には
6:11 AM
URLSessionDataTaskenum で色んな case を持ってて
Avatar
// vvvvvvv ここが気に食わない struct URLSessionDataTaskError : Error {
Avatar
URLResponse を持つ場合だけその caseresponse を保持するのがいいんじゃない?
6:12 AM
enum URLSessionDataTaskError: Error { case ... case ...(URLResponse) ... }
Avatar
いろんなcaseっていうのは
6:13 AM
URLErrorの中身をそこに昇格するってことですか?
Avatar
URLSessionDataTask がエラーになりうる様々な case
6:13 AM
うん。
6:13 AM
理想的な API にならない理由は Foundation 依存なことだから
6:13 AM
URLSessionDataTaskError 導入してる時点で Foundation との整合性を考える必要性はないのでは。
Avatar
ふーむ
Avatar
completion の話だけ書き込んでおくか。
Avatar
もらったレスの英文が全然わからん。
6:23 AM
NSErrorがURLResponseを保持しない事に驚いたって言ってるのかな・・・
Avatar
Because dataTask(with:completionHandler:) returns a URLSessionDataTask, it is impossible to be converted into async/await directly. I think we need an extension method like below. extension URLSessionDataTask { func completion() async throws -> (Data, URLResponse) { ... ...
6:25 AM
completion の件書いておいた
6:28 AM
NSErrorがURLResponseを保持しない事に驚いたって言ってるのかな・・・
概ねそんな感じかと。
Avatar
なるほど・・・
Avatar
なぜか↓が Linux でだけ失敗する・・・。エラーが起こるけど .dataCorrupted にマッチしてないっぽい。 let jsonData: Data = "".data(using: .utf8)! let result = Result<[Int], Error> { try JSONDecoder().decode([Int].self, from: jsonData) } switch result { case .value(let value): XCTFail("\(value)") case .error(DecodingError.dataCorrupted(let context)): XCTAssertTrue(context.codingPath.isEmpty) case .error(let error): XCTFail("\(error)") } https://travis-ci.org/koher/SwiftResult/jobs/461127891
6:42 AM
この Result 、 covariance はなくていいんだろうか。特に Result<Int, FooError>Result<Int, Error> に代入できないの辛そう。
Avatar
b = a.mapError { $0 as Error } ですね。
Avatar
The throwing overload of flatMap should be removed. It is composable from flatMap and init(catching:) , and it is generally frowned upon to overload just on whether something is throwing or not.
6:44 AM
↑と組み合わせると a.flatMap { Result { try foo() }.mapError { $0 as Error } } となって辛そう。
6:45 AM
あ、逆か (edited)
6:45 AM
a.flatMap { Result { try foo() }.mapError { $0 as! FooError } }
Avatar
そうですねえ
6:56 AM
init(catching:)でuntyped throwsを経由することでエラー型が消え去り、でもわかってるから as! でダウンキャスト
6:56 AM
っていうのは微妙なパターンですよね。
Avatar
まあ Result<Foo, Error> を使ってれば問題ないか。
6:58 AM
Error の self-conform で特別扱いするなら、 Result<Value, Error: Swift.Error = Swift.Error> も認めて Result<Foo> って書けるようにしてほしい。
Avatar
デフォルトジェネリックパラメータ機能が欲しいって意味ですか?
Avatar
とりあえず Result にだけデフォルト型パラを認めてくれたら便利そう。 (edited)
Avatar
なんかその特別扱いは実装が結構大変そうですね
Avatar
Sema あたりでちょちょいとできないかなぁ。 Result で第二型パラがなかったら Swift.Error と解釈するとか。
Avatar
import Foundation @objc protocol Animal {} func take<X: Animal>(_ a: X) {} func outer(_ a: Animal) { take(a) }
7:34 AM
proposal読んでて書いてあったんだけど、たしかに、@objcだとself-conformしてる・・・
Avatar
どうやら Swift 4.2 / Linux だと↓のエラーが DecodingError ではなく NSError になるっぽい・・・。 import Foundation do { _ = try JSONDecoder().decode([Int].self, from: "".data(using: .utf8)!) } catch let error { print(error) }
Avatar
あ、ブリッジが無いからか。
Avatar
Swift 4.2.1 では解決されてる。
Avatar
そんなタイムリーな。
Avatar
CI がコケるけど手元の Linux 環境で試してもコケないからなんでかと思ったら、 CI の設定が 4.2 で手元は 4.2.1 だった。 4.2.1 に設定しなおしたら CI も通るようになった。
8:35 AM
Linux だけかと思ったけどもしかして macOS でも 4.2 だと NSError なのか。
8:36 AM
@swift-4.0.3 @swift-4.1.3 @swift-4.2.4 import Foundation do { _ = try JSONDecoder().decode([Int].self, from: "".data(using: .utf8)!) } catch let error { print("\(type(of: error)): \(error)") } (edited)
Avatar
DecodingError: ⚠️ [DecodingError.dataCorrupted: The given data was not valid JSON.] (edited)
Avatar
NSError: The operation could not be completed (edited)
Avatar
NSError: The operation could not be completed (edited)
Avatar
いや、macOS や iOS は 4.2 で も CI 通ってるんだった。 (edited)
Avatar
値の取り出しが case let と unwrapped() だけになったのもかなり思い切ってる気がする
2:01 AM
これはこれでいいとは思うが
Avatar
Result のための構文の必要性についても話し合われていたので、将来的に追加されるかもしれませんね。たとえば↓のような構文とかいいかもしれません。 guard let number = result else let error { // error を使うオペレーション } // number を使うオペレーション
Avatar
Introduce a WinSDK overlay for Windows. This allows us to define some shared constants that are not correctly imported right now. This cleans up the logic in the swift side of things and aids in ...
6:40 AM
@_exported import WinSDK // Clang module // WinBase.h public let HANDLE_FLAG_INHERIT: DWORD = 0x00000001 // WinBase.h public let STARTF_USESTDHANDLES: DWORD = 0x00000100 // WinBase.h public let INFINITE: DWORD = DWORD(bitPattern: -1) // WinBase.h public let WAIT_OBJECT_0: DWORD = 0 // minwindef.h public let FALSE: BOOL = 0 // minwindef.h public let TRUE: BOOL = 1
6:40 AM
WindowsSDKのオーバーレイ!
Avatar
omochimetaru 12/6/2018 1:28 AM
Hello, Swift Community. The review for the revisions to SE-0235: Add Result to the Standard Library ran from November 28th through December 2nd. You can find the review thread here. There was also an earlier round of review for the initial proposal. The community provided...
1:28 AM
Result型Accepted
👀 3
Avatar
@swift-main protocol P1 { associatedtype Input } protocol P2 { associatedtype Input } struct Box<T> {} extension Box: P1 where T: P1 { typealias Input = T.Input } extension Box: P2 where T: P2 { } func inputType<T>(_ type: T.Type) -> T.Input.Type where T: P2 { fatalError() } struct A: P2, P1 { typealias Input = Int } let _ = inputType(Box<A>.self) (edited)
Avatar
swiftNightly BOT 12/17/2018 2:01 AM
exit status: 134 with stderr:swift: /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-16_04/llvm/include/llvm/Support/Casting.h:106: static bool llvm::isa_impl_cl<swift::SugarType, const swift::TypeBase *>::doit(const From *) [To = swift::SugarType, From = const swift::TypeBase *]: Assertion `Val && "isa<> used on a null pointer"' failed. Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -I /Libraries/.build/x86_64-unknown-linux/debug -I /Libraries/.build/checkouts/swift-nio-b68c973e/Sources/CNIOZlib/include -I /Libraries/.build/checkouts/swift-nio-b68c973e/Sources/CNIOHTTPParser/include -I /Libraries/.build/checkouts/swift-nio-b68c973e/Sources/CNIOSHA1/include -I /Libraries/.build/checkouts/swift-nio-b68c973e/Sources/CNIOAtomics/include -I /Libraries/.build/checkouts/swift-nio-b68c973e/Sources/CNIODarwin/include -I /Libraries/.build/checkouts/swift-nio-b68c973e/Sources/CNIOLinux/include -module-cache-path /Libraries/.build/x86_64-unknown-linux/debug/ModuleCache -D DEBUG -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOZlib.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOHTTPParser.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOSHA1.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOAtomics.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIODarwin.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOLinux.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/swift-nio-zlib-support-c4b8a10c/module.modulemap -module-name main -lLibraries #0 0x000000000460a1c4 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x460a1c4) #1 0x0000000004607f90 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4607f90) #2 0x000000000460a372 SignalHandler(int)
Avatar
同名associatedtypeがある時のワークアラウンドあったりしますか?
Avatar
Kishikawa Katsumi 12/17/2018 6:30 AM
@swiftbot --version latest protocol P1 { associatedtype Input } extension P1 { typealias InputP1 = Input } protocol P2 { associatedtype Input } extension P2 { typealias InputP2 = Input } struct Box<T> {} extension Box: P1 where T: P1 { typealias InputP1 = T.InputP1 } extension Box: P2 where T: P2 { typealias Input = T.InputP2 } func inputType<T>(_ type: T.Type) -> T.Input.Type where T: P2 { fatalError() } struct A: P2, P1 { typealias Input = Int } let _ = inputType(Box<A>.self)
🛠 1
Avatar
Author icon
kishikawakatsumi
protocol P1 { associatedtype Input } extension P1 { typealias InputP1 = Input } protocol P2 { associatedtype Input } extension P2 { typealias InputP2 = Input } struct Box<T> {} extension Box: P1 where T: P1 { typealias InputP1 = T.InputP1 } extension Box: P2 where T: P2 { typealias Input = T.InputP2 } func inputType<T>(_ type: T.Type) -> T.Input.Type where T: P2 { fatalError() } struct A: P2, P1 { typealias Input = Int } let _ = inputType(Box<A>.self)
Version:
swift-DEVELOPMENT-SNAPSHOT-2018-12-15-a
Output:
Error:
Fatal error: file /usercode/main.swift, line 28 Current stack trace: 0 libswiftCore.so 0x00007f51ac83c200 _swift_stdlib_reportFatalErrorInFile + 115 1 libswiftCore.so 0x00007f51ac7773fc <unavailable> + 3396604 2 libswiftCore.so 0x00007f51ac7774ee <unavailable> + 3396846 3 libswiftCore.so 0x00007f51ac582f2a <unavailable> + 1347370 4 libswiftCore.so 0x00007f51ac742f42 <unavailable> + 3182402 5 libswiftCore.so 0x00007f51ac5822f9 <unavailable> + 1344249 8 swift 0x0000000000cec7de <unavailable> + 9357278 9 swift 0x0000000000cf09f2 <unavailable> + 9374194 10 swift 0x0000000000515eff <unavailable> + 1138431 11 swift 0x00000000004eae3e <unavailable> + 962110 12 swift 0x00000000004e6712 <unavailable> + 943890 ...
6:30 AM
Avatar
Kishikawa Katsumi 12/17/2018 6:30 AM
^ よくわかってないけど、Extensionで別名をつける?
Avatar
@swiftbot --version latest protocol P1 { associatedtype Input } extension P1 { typealias InputP1 = Input } protocol P2 { associatedtype Input } extension P2 { typealias InputP2 = Input } struct Box<T> {} extension Box: P1 where T: P1 { typealias InputP1 = T.InputP1 } extension Box: P2 where T: P2 { typealias Input = T.InputP2 } func inputTypeP2<T>(_ type: T.Type) -> T.Input.Type where T: P2 { return T.Input.self } func inputTypeP1<T>(_ type: T.Type) -> T.Input.Type where T: P1 { return T.Input.self } struct A: P2, P1 { typealias Input = Int } print(inputTypeP1(Box<A>.self)) // セグフォ print(inputTypeP2(Box<A>.self))
🛠 1
Avatar
Author icon
kateinoigakukun
protocol P1 { associatedtype Input } extension P1 { typealias InputP1 = Input } protocol P2 { associatedtype Input } extension P2 { typealias InputP2 = Input } struct Box<T> {} extension Box: P1 where T: P1 { typealias InputP1 = T.InputP1 } extension Box: P2 where T: P2 { typealias Input = T.InputP2 } func inputTypeP2<T>(_ type: T.Type) -> T.Input.Type where T: P2 { return T.Input.self } func inputTypeP1<T>(_ type: T.Type) -> T.Input.Type where T: P1 { return T.Input.self } struct A: P2, P1 { typealias Input = Int } print(inputTypeP1(Box<A>.self)) // セグフォ print(inputTypeP2(Box<A>.self))
Version:
swift-DEVELOPMENT-SNAPSHOT-2018-12-15-a
Output:
Error:
swift: /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-16_04/llvm/include/llvm/Support/Casting.h:106: static bool llvm::isa_impl_cl<swift::SugarType, const swift::TypeBase *>::doit(const From *) [To = swift::SugarType, From = const swift::TypeBase *]: Assertion `Val && "isa<> used on a null pointer"' failed. Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret /usercode/main.swift -disable-objc-interop -module-name main /usr/bin/swift[0x4608a04] /usr/bin/swift[0x46067d0] /usr/bin/swift[0x4608bb2] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f533b723390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f5339e62428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f5339e6402a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7f5339e5abd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7f5339e5ac82] /usr/bin/swift[0x19464f3] /usr/bin/swift[0xef6b2c] /usr/bin/swift[0xf0af9e] /usr/bin/swift[0xf0eb07] /usr/bin/swift[0xef3041] /usr/bin/swift[0xe7e311] ...
7:03 AM
Avatar
@Kishikawa Katsumi これだと P1 の方が死んじゃいました
Avatar
😩
Avatar
Kishikawa Katsumi 12/17/2018 7:05 AM
難しいな
7:07 AM
しかし、まだこんなくらいのコードでクラッシュさせられるんですね。
12:30 PM
報告した
Avatar
Typealiases in constrained extensions aren't actually constrained today
10:54 PM
コメントが付いたw
Avatar
Hello everyone! I'd like to pitch the formalization of ordered collections as well as the addition of diffing functionality and related types necessary to provide easy creation, representation, and application of ordered collection state transitions. Formalizing the notion ...
1:32 AM
標準ライブラリに差分計算入れる話
👀 4
Avatar
norio_nomura 1/7/2019 6:29 AM
https://github.com/apple/swift/blob/master/include/swift/Runtime/SwiftDtoa.h に入ってるswift_decompose_double(), swift_decompose_float(), swift_decompose_float80()swift_format_exponential()をYamsで使いたかったのだけど、libswiftCoreからexportされていないので、SwiftDtoa.hSwiftDtoa.cppをソースコードごとコピーしてくるしか手が無い。 (edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
6:31 AM
ソースがデカイのと、ライセンスを変えないといけなさそうという理由で、とりあえずクローズ。 https://github.com/jpsim/Yams/pull/151
Use SwiftDtoa.(h|cpp) for formatting FloatingPoint into String Support Float80 as ScalarConstructible and ScalarRepresentable On Linux, Supporting Float80 requires Swift 4.2+, since swift_decompos...
Avatar
omochimetaru 1/7/2019 6:31 AM
C関数ってヘッダだけ持ってきたらだめなんですっけ
Avatar
norio_nomura 1/7/2019 6:31 AM
ライブラリでexportされていないとダメです。 (edited)
6:32 AM
nm -gU /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftCore.dylibで出てくるものならリンクできる。
Avatar
omochimetaru 1/7/2019 6:33 AM
ふむふむ
6:33 AM
-g Display only global (external) symbols. -U Don't display undefined symbols.
Avatar
norio_nomura 1/7/2019 6:54 AM
リクエストしておいた。 https://bugs.swift.org/browse/SR-9610
Avatar
omochimetaru 1/9/2019 12:58 AM
https://github.com/apple/swift-syntax/pull/57 SwiftSyntax公式に、サンプルとして @Kishikawa Katsumi@inamiy の作ったやつへのリンクが追加されそう😀
Avatar
Kishikawa Katsumi 1/9/2019 1:04 AM
載せてもらいました 💗
Avatar
SwiftってC言語の可変長引数関数、呼び出せなかったのか
12:02 PM
ブリッジできるのはva_listの場合か・・・
Avatar
norio_nomura 1/11/2019 3:59 AM
Swift 5のmacOS版のData.withUnsafeBytes(_:)は、Dataが小さい場合にスコープ外で無効となるポインタをクロージャへ渡す場合がある。 https://bugs.swift.org/browse/SR-9578
4:00 AM
「immutableならスコープ外でも使えるポインタだろう」という前提で使っていて、Swift 5になってバグった。
Avatar
omochimetaru 1/11/2019 4:02 AM
なるほど
4:03 AM
この挙動のときは、Data自体がコンテンツを持っていて、ヒープアロケートを回避してるんですかね
4:03 AM
Small String Optimizationみたいな感じで。
4:04 AM
あ、じゃあ String の withCString { } とかも同じ事がありえるのかな
4:04 AM
逆にどんなときテンポラリなポインタが来るのか気になってたけどこういうケースがあるんだなあ
Avatar
norio_nomura 1/11/2019 4:14 AM
withCString(_:)は、null termination追加があるから以前から毎回一時メモリじゃないかな。 (edited)
Avatar
omochimetaru 1/11/2019 4:15 AM
文字列ライブラリってとりあえずCに備えて いつもnullつけてバッファ保持したりもするのでそれを期待してました
Avatar
Swift5 の通常の String のストレージは UTF8 で null terminated になるで、 5 からは大抵ストレージへの直ポインタになりそう。
Avatar
norio_nomura 1/11/2019 4:18 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
String’s ABI and UTF-8 We just landed String’s proposed final ABI on master. This ABI includes some significant changes, the primary one being that native Swift strings are stored as UTF-8 where they were previously stored either as ASCII or UTF-16 depending on their cont...
Avatar
norio_nomura 1/11/2019 4:22 AM
Small UTF-8 Stringsも言及されてますね。
Avatar
norio_nomura 1/11/2019 4:41 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
4:41 AM
swift-corelibs-foundationには無い。
3:03 AM
Adds an on_stack version of partial_apply It does not take ownership of its non-trivial arguments, is a trivial function type and therefore must not be destroyed. The compiler must make sure to ext...
Avatar
omochimetaru 1/17/2019 3:05 AM
おー
3:05 AM
クロージャの環境オブジェクトがスタックに作れるようになったのかな?
Avatar
norio_nomura 1/17/2019 3:06 AM
Avatar
omochimetaru 1/17/2019 3:06 AM
17倍のやつやばいですね
Avatar
norio_nomura 1/17/2019 3:09 AM
non-escaping functionsの変遷を簡単に解説してる。 https://twitter.com/slava_pestov/status/1085691914328920066 (ツイート内のリンクは上記PR) (edited)
Short history of non-escaping functions:
  • Swift 4.1 and earlier: type checker enforcement; same ABI as escaping
  • Swift 4.2: new ABI - the context is a trivial pointer and not ref-counted like with escaping
  • now: non-escaping contexts allocated on stack https://t.co/gIl...
Avatar
omochimetaru 1/17/2019 3:10 AM
non-escapingの時にtrivial pointerになったのって4.2だったのか。ちょうど最近見た。
Avatar
protocol Animal {} protocol Cat: Animal {} protocol Owner { associatedtype Pet var pet: Pet { get } } func callBark(_ animal: Animal){} func callPetBark<T: Owner>(_ t: T) where T.Pet == Animal { callBark(t.pet) } func callPetBark<T: Owner>(_ t: T) where T.Pet == Cat { callBark(t.pet) } struct Lion: Cat {} struct Breeder: Owner { typealias Pet = Animal var pet: Animal { return Lion() } } let owner = Breeder() callPetBark(owner) assoctypeが「あるexistentialのサブタイプである」、っていう制約を書きたい (edited)
3:47 AM
要はcallPetBarkのオーバーロードを無くしたいんですけど、なんかいい方法無いですか? (edited)
Avatar
norio_nomura 1/18/2019 4:01 AM
BreederpetAnimalである時点で無理そう。 error: protocol type 'Animal' cannot conform to 'Animal' because only concrete types can conform to protocols にハマる。
Avatar
omochimetaru 1/18/2019 4:08 AM
protocol Animal {} protocol Cat: Animal {} protocol Owner { associatedtype Pet var pet: Pet { get } } func callBark(_ animal: Animal){} func callPetBark<T: Owner>(_ t: T) where T.Pet : Animal { callBark(t.pet) } struct Lion: Cat {} struct GenericBreeder<T>: Owner { typealias Pet = T init(pet: T) { self.pet = pet } var pet: T } struct AnyAnimal : Animal { var value: Animal } struct AnyAnimalBreeder : Owner { init<X: Animal>(pet: X) { self.pet = AnyAnimal(value: pet) } var pet: AnyAnimal } struct ConcreteLionBreeder : Owner { typealias Pet = Lion var pet: Lion { return Lion() } } let o1 = GenericBreeder<Lion>(pet: Lion()) callPetBark(o1) let o2 = AnyAnimalBreeder(pet: Lion()) callPetBark(o2) let o3 = ConcreteLionBreeder() callPetBark(o3)
4:08 AM
直接の解答は思いつかなかった。代替を3種↑
Avatar
norio_nomura 1/18/2019 4:09 AM
やはりそうなるよね。
Avatar
うーんやっぱりそうですねーー
Avatar
omochimetaru 1/18/2019 4:09 AM
ex.Animal と ex.Cat の間にはサブタイピング関係があるけど、 素直に where T.Pet : Animal と書いてしまうと、exisとは関係ないプロトコル制約の意味になっちゃって、 それが使えないねえ
Avatar
そうなんですよ、 where句でexistentialとprotocolが区別できればいいんですけど。
Avatar
omochimetaru 1/18/2019 4:14 AM
うーんどこに歪みがあるのかもよくわからんなこの話
4:15 AM
Animalを避けてAnyAnimalを手実装するのがマシな路線な気がする
Avatar
既存コードの後方互換を保つのが目的なのでBreederにできるだけ変更入れたく無いんですよね。。
4:23 AM
大人しくオーバーロード書くことにします 😿
Avatar
@swift-4.2.4 import Foundation enum Key: String, Decodable { case a, b, c } let json = """ { "a": "__a__", "b": "__b__", "c": "__c__" } """.data(using: .utf8)! do { print(try JSONDecoder().decode([String: String].self, from: json)) let ret = try JSONDecoder().decode([Key: String].self, from: json) print(ret) } catch { print(error) } (edited)
Avatar
["a": "__a__", "c": "__c__", "b": "__b__"] ⚠️ [DecodingError.typeMismatch: Value of type 'Array<Any>' required for key ''.] (edited)
Avatar
今更ですが、Decodable の Dictionary のキーは String か Int しか受け付けてなかったんですね 😇 (入力が配列であれば任意のキーで Dictionary にはできるっぽいですが。。) https://github.com/apple/swift/blob/master/stdlib/public/core/Codable.swift.gyb#L1893
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 1/18/2019 7:03 AM
extension Dictionary : Decodable where Key : Decodable, Value : Decodable {
↑このとおり、KeyがDecodableなら、StringやIntではない型も使えると思います
7:03 AM
ただ、StringとIntじゃないと、KeyedContainerにならないので
7:04 AM
それ以外のものでDecodableの場合は、UnkeyedContainerからkeyとvalueを交互に取り出すっていう
7:04 AM
挙動になりますね
7:04 AM
JSONのobjectからデコードするという意味だとStrintとIntしか駄目ですが、 JSONのarrayからなら変なKeyもいける。
👏 1
Avatar
今まで [Int: User] だったものを [UserId: User] のような感じにしたかったんですが、直接やるのは少し難しいですね 😢 (edited)
Avatar
omochimetaru 1/18/2019 7:27 AM
それだと一度 [Int: User]でdecodeしてからmapするのが良さそうですね
Avatar
keyのmapって面倒くさくなかったでしたっけ
7:28 AM
mapValuesはあるけどmapKeysは無いような 🤔
Avatar
omochimetaru 1/18/2019 7:29 AM
let a: [Int: String] = [1: "a", 2: "b"] let b: [String: String] = Dictionary(uniqueKeysWithValues: a.map { ("\($0)", $1) })
7:30 AM
// むりやり左から右の流れに・・・ let c: [String: String] = Optional(a.map { ("\($0)", $1) }).map(Dictionary.init)!
Avatar
norio_nomura 1/18/2019 7:36 AM
Dictionaryの代わりを作るとか…
Avatar
ありがとうございます。ひとまず map で凌ごうと思います。 (確かに独自 Dictionary はインターフェース的にきれいに表現できそうです 😄
Avatar
これはちょっと僭越なんですが、Responseの段階では単なる[User]になってた方が取り回しが良さそう… (edited)
Avatar
norio_nomura 2/1/2019 12:02 AM
https://discordapp.com/channels/291054398077927425/291054454793306112/539692829606281243 encodedOffsetdeprecatedにする提案をswift-5.0-RELEASEへ入れるには遅すぎた、という結論へ至ったらしい。まあ仕方ない。 https://forums.swift.org/t/se-0241-explicit-encoded-offsets-for-string-indices/19929/36 (edited)
The original proposal sought to solve 3 problems: SE-0180’s encodedOffset, meant for serialization purposes, needs to be parameterized over the encoding in which the string will be serialized in Existing uses of encodedOffset need a semantics-preserving off-ramp for Swift...
😍 1
Avatar
norio_nomura 2/1/2019 12:12 AM
あいや、swift-5.0-RELEASEへ入れるのを諦めるのは各offsetに対応したAPIを追加する事で、encodedOffsetdeprecatedにして代替となるString.Index.utf16Offset(in:)String.Index.init(utf16Offset:in:)だけはswift-5.0-RELEASEへ入れようという方向へ切り替わったのか? https://github.com/apple/swift-evolution/blob/master/proposals/0241-string-index-explicit-encoding-offset.md (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 2/1/2019 1:50 AM
Detailed Designが全然違うものになってるw
Avatar
omochimetaru 2/1/2019 2:02 AM
ジェレミーさんの指摘の 「That is trivially composable.」は全くそのとおりだなあ
Avatar
omochimetaru 2/1/2019 7:46 AM
エンコード違いの文字列同士の間のIndexが半順序(partially order)になるというの面白いですね
7:46 AM
なかなかpartially orderって現実で直面する事が無いけどこの例は身近だし。
Avatar
omochimetaru 2/1/2019 8:12 AM
やっと読めた。
8:12 AM
The original proposal sought to solve 3 problems: SE-0180’s encodedOffset, meant for serialization purposes, needs to be parameterized over the encoding in which the string will be serialized in Existing uses of encodedOffset need a semantics-preserving off-ramp for Swift...
8:14 AM
コアチーム的に新しい事をSwift5.0に追加するにはおそすぎるけど、 内部がUTF-8になる事によって、元々のUTF-16のつもりでやってたやつを移行する(semantics-preserving)APIだけは緊急に必要で(urgent fixes)
8:16 AM
という話か。一つ前の>>35でも興味深い指摘がされてますね。
8:17 AM
元々正しい書き換えして出ていた、 string.utf16.index(string.startIndex, by: offset) という書き方だと (edited)
8:17 AM
もともとは String.Index(encodedOffset: offset) でパラメータがoffsetだけだったのに対して
8:17 AM
対象のstringが必要になっちゃってる
8:18 AM
で、NSString系のNSRangeが返ってくる系のコールバックだと
8:18 AM
func processEdit(editedNSRange: NSRange, changeInLenght delta: Int) { let editedRange = Range<String.Index>(uncheckedBounds: ( String.Index(encodedOffset: editedNSRange.lowerBound), String.Index(encodedOffset: editedNSRange.upperBound) )) ...
8:18 AM
こういうふうに元々stringなしでNSRangeからRange<String.Index>に持っていけてたから
8:19 AM
この用途をカバーするAPIが必要なんですね。
8:20 AM
あれ?修正提案でも public init<S: StringProtocol>(utf16Offset offset: Int, in s: S) { こうなってるな。
Avatar
norio_nomura 2/1/2019 10:39 AM
String.Indexはオフセットが同じでも、対象となるStringにより中身が変わってきます。 コメントに構造が記されてます。 https://github.com/apple/swift/blob/master/stdlib/public/core/StringIndex.swift#L17-L33 /* String's Index has the following layout: ┌──────────┬───────────────────┬────────────────┬──────────┐ │ b63:b16 │ b15:b14 │ b13:b8 │ b7:b0 │ ├──────────┼───────────────────┼────────────────┼──────────┤ │ position │ transcoded offset │ grapheme cache │ reserved │ └──────────┴───────────────────┴────────────────┴──────────┘ - grapheme cache: A 6-bit value remembering the distance to the next grapheme boundary - position aka `encodedOffset`: An offset into the string's code units - transcoded offset: a sub-scalar offset, derived from transcoding The use and interpretation of both `reserved` and `grapheme cache` is not part of Index's ABI; it should be hidden behind non-inlinable calls. However, the position of the sequence of 14 bits allocated is part of Index's ABI, as well as the default value being `0`. */ (edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 3/1/2019 12:35 AM
Hey all, I'm very excited to bring this pitch today to get more feedback from the community—it's an effort that my team at Google has been doing in collaboration with @dabrahams (co-author) and many other folks on the Swift team. SE pull request. An Official Style Guide ...
12:37 AM
グーグルがしこしこ作ってたフォーマッターのピッチが書き込まれた
12:37 AM
6時間で70レスついてる
Avatar
norio_nomura 3/1/2019 12:50 AM
Should the Swift language adopt an official style guide and formatting tool? これに割かれるリソースを想像すると、賛成しづらいね。 (edited)
Avatar
omochimetaru 3/1/2019 1:00 AM
現状だとxcodeの微妙なフォーマットが半分オフィシャルみたいなもので、 それとswiftlintが併用されてたりするから、
1:01 AM
言語オフィシャルが決まればxcodeも追従するとしたら、それが嬉しいな
1:02 AM
go fmtやpython pep8はどうやって決着したんだろ
Avatar
norio_nomura 3/1/2019 1:30 AM
Official Style Guideが決まったとしても、apple/swift自体がそれを使ってなければ説得力に欠けるよね。
Avatar
Kishikawa Katsumi 3/1/2019 1:44 AM
極端に変じゃなくて自動的に適用される環境が簡単に手に入るようになれば使われるはず。
Avatar
omochimetaru 3/1/2019 1:48 AM
公式として提供するのはフォーマットシステムにしてプロジェクト単位でカスタムできる機構があるといい、みたいな意見がちらほら書かれてるなあ
Avatar
norio_nomura 3/1/2019 4:29 AM
まあ、標準でToolchainに入ってれば使うのかな?というか今入ってるのは、使われてるのかな? @swift-4.2.4 format --help
Avatar
swift42 BOT 3/1/2019 4:29 AM
exit status: 1 with stdout:OVERVIEW: Swift Format Tool USAGE: swift [options] <inputs> OPTIONS: -help Display available options -in-place Overwrite input file with formatted file. -indent-switch-case Indent cases in switch statements. -indent-width <n> Number of characters to indent. -line-range <n:n> <start line>:<end line>. Formats a range of lines (1-based). Can only be used with one input file. -o <file> Write output to <file> -tab-width <n> Width of tab character. -use-tabs Use tabs for indentation.
Avatar
omochimetaru 3/1/2019 4:31 AM
rzyzanowskim Marcin Krzyzanowski 7h I just want to mention this probably the most forgotten tool that is part of the toolchain for a long time already.
4:31 AM
それに誰も触れないからスレの終盤で指摘があった
4:31 AM
akyrtzi Argyrios Kyrtzidis This is wrapping the C++ code that is doing indentation only and is not a good base to build a proper formatter on; it would be much better to use a formatter tool written in Swift.
4:32 AM
akyrtziさんはSyntaxチームの人
6:10 AM
Google CodeLabでpython notebook風にSwift For TensorFlow動いとる
Avatar
norio_nomura 3/10/2019 4:53 AM
Linuxは#available(macOS 10.13, *)trueになる。 @swift-5.0.3 if #available(macOS 10.13, *) { print("#available(macOS 10.13, *)") } else { print("not #available(macOS 10.13, *)") }
Avatar
#available(macOS 10.13, *)
Avatar
norio_nomura 3/10/2019 5:10 AM
この挙動はあてにしても良いのだろうか?
Avatar
おや・・・ protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foo1() -> F func foo2() -> F } struct S { func foo1() -> __opaque Foo { return 2 } func foo2() -> __opaque Foo { return 3 } } let s = S() var a = s.foo1() let b = s.foo2() a = b /path/to/opaque-result.swift:17:5: error: cannot assign value of type '(__opaque main.(file).S.foo2()@/path/to/opaque-result.swift:11:10)' to type '(__opaque main.(file).S.foo1()@/path/to/opaque-result.swift:10:10)' a = b ^ as! (__opaque main.(file).S.foo1()@/path/to/opaque-result.swift:10:10) (edited)
4:03 PM
↓こちらをビルドして試した結果。 https://github.com/jckarter/swift/tree/opaque-type-ast
The Swift Programming Language. Contribute to jckarter/swift development by creating an account on GitHub.
4:03 PM
↓こっちの方がいいのかな? Proposal からリンクされてた PR のブランチは↑だけど。 https://github.com/jckarter/swift/tree/opaque-type-runtime (edited)
The Swift Programming Language. Contribute to jckarter/swift development by creating an account on GitHub.
4:08 PM
↓こっちはそもそも -> (some Foo, some Foo) が現時点で許されてなかった。 protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foos() -> (F, F) } struct S { func foos() -> (__opaque Foo, __opaque Foo) { return (2, 3) } } let s = S() var (a, b) = s.foos() a = b /path/to/opaque-result-2.swift:9:21: error: 'opaque' types are only implemented for the declared type of properties and subscripts and the return type of functions func foos() -> (__opaque Foo, __opaque Foo) { return (2, 3) } ^ (edited)
Avatar
SS: P にできてなかった・・・
4:19 PM
protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foo1() -> F func foo2() -> F } struct S: P { func foo1() -> __opaque Foo { return 2 } func foo2() -> __opaque Foo { return 3 } } let s = S() var a = s.foo1() let b = s.foo2() a = b /path/to/opaque-result.swift:9:8: error: type 'S' does not conform to protocol 'P' struct S: P { ^ /path/to/opaque-result.swift:5:20: note: ambiguous inference of associated type 'F': '(__opaque main.(file).S.foo2()@/path/to/opaque-result.swift:11:10)' vs. '(__opaque main.(file).S.foo1()@/path/to/opaque-result.swift:10:10)' associatedtype F: Foo ^ /path/to/opaque-result.swift:11:10: note: matching requirement 'foo2()' to this declaration inferred associated type to '(__opaque main.(file).S.foo2()@/path/to/opaque-result.swift:11:10)' func foo2() -> __opaque Foo { return 3 } ^ /path/to/opaque-result.swift:10:10: note: matching requirement 'foo1()' to this declaration inferred associated type to '(__opaque main.(file).S.foo1()@/path/to/opaque-result.swift:10:10)' func foo1() -> __opaque Foo { return 2 } ^ /path/to/opaque-result.swift:17:5: error: cannot assign value of type '(__opaque main.(file).S.foo2()@/path/to/opaque-result.swift:11:10)' to type '(__opaque main.(file).S.foo1()@/path/to/opaque-result.swift:10:10)' a = b ^ as! (__opaque main.(file).S.foo1()@/path/to/opaque-result.swift:10:10)
4:22 PM
Sfoo1foo2__opaque Foo が別の型とみなされてるっぽい。
4:22 PM
↓は OK protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foo() -> F } struct S: P { func foo() -> __opaque Foo { return 42 } } let s = S() var a = s.foo() let b = s.foo() a = b
Avatar
一個までならいけるんですかね
4:22 PM
おおーーー
Avatar
↓これなら複数 API の戻り値型間で代入できました。 protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func makeFoo(from: Int) -> F func foo() -> F } struct S: P { func makeFoo(from: Int) -> __opaque Foo { return from } func foo() -> F { return makeFoo(from: 42) } } let s = S() var a = s.foo() let b = s.makeFoo(from: -1) print(a) a = b print(a) 42 -1
Avatar
Avatar
なぜか同じ要領で foo1foo2 を作るとエラーになる・・・
Avatar
フーム
Avatar
仕様なのか、作りかけなのか判断できませんね・・・
4:34 PM
このブランチが opaque-type-ast で、最近 Joe Groff が触ってるっぽい opaque-type-runtime が別にありますし。
Avatar
宣言箇所が一箇所ならok?
Avatar
お、↓も通った。 protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foo() -> F func foos() -> (F, F) } extension P { func foos() -> (F, F) { return (foo(), foo()) } } struct S: P { func foo() -> Int { return Int.random(in: 0..<100) } } let s = S() var (a, b) = s.foos() print(a) a = b print(a) 9 52
Avatar
typealias F = some Foo にして返り値はF
Avatar
typealias で opaque result type はまだ許されてないようです。 protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foo() -> F } struct S: P { typealias F = __opaque Foo func foo() -> F { return 42 } } let s = S() var a = s.foo() let b = s.foo() a = b /path/to/opaque-result-0.swift:9:19: error: 'opaque' types are only implemented for the declared type of properties and subscripts and the return type of functions typealias F = __opaque Foo ^
Avatar
うーんわからん
Avatar
associatedtype を確定する typealias とは別ですが、一般的な typealias は今回の Proposal 外の Future Directions に入ってるので、 protocol でも将来的なサポートになるかもです。 https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md#opaque-type-aliases (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
4:43 PM
とりあえず、↑の実験から、 associatedtype の型を具象型側で some Foo にした場合、 some Foo を返す複数 API 間で同一の型として扱えそうです。
4:50 PM
=== 明示的に記述しなければ (some Foo)? 作れた🤔 protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foo() -> F func fooOrNil() -> F? } struct S: P { func foo() -> __opaque Foo { return 42 } func fooOrNil() -> F? { return Bool.random() ? foo() : nil } } let s = S() var a = s.fooOrNil() print(String(describing: a)) let b: Int? = -1 a = b // Error /path/to/opaque-result-3.swift:19:5: error: cannot assign value of type 'Int?' to type '(__opaque main.(file).S.foo()@/path/to/opaque-result-3.swift:10:10)?' a = b // Error ^ as! (__opaque main.(file).S.foo()@/path/to/opaque-result-3.swift:10:10) (edited)
Avatar
これはw
Avatar
エラーの行コメントアウトしたらコンパイルも通って実行もできます。
Avatar
omochimetaru 3/12/2019 1:50 AM
Another way we could conceivably notate this is by putting the output parameters after the ->, as a number of people suggested:
makeFoo() -> <F: Foo> F ↑この記法は何が起きてるかわかりやすいと思った
(edited)
1:50 AM
In Swift, this would mean that:
func foo(x: some P) { /* ... */ }
would be sugar for:
func foo<T: P>(x: T) { /* ... */ }
(edited)
1:52 AM
some P ってのは結局、暗黙のジェネリックパラメータで、引数部分で使う場合は通常のジェネリクスと同じ事 返り値で使う場合だと、パラメータをcallerではなくcalleeが決定するという違いが出る
1:52 AM
その点で、 makeFoo() -> <F: Foo> F ←これは見た目的に直感的にそれが伝わる
Avatar
使う側は明示的に指定できない?
Avatar
omochimetaru 3/12/2019 1:57 AM
opaque result typeはその名の通り本当の型は関数側で静的に決まってて、受け取り側(caller)がジェネリックコンテナで受け取るというだけなので
1:58 AM
使う側からの明示的な指定は無理、だと思います
Avatar
あと、戻り値以外のケースでも問題ないかな? let a: <F: Foo> F = makeFoo() typealias Bar = <F: Foo> F
Avatar
omochimetaru 3/12/2019 1:59 AM
こういうのはいけるか、今回の提案だと範囲外?だけど func makeColl<X>() -> some Collection<.Element == X> (edited)
Avatar
同じ見た目の型間で代入できない問題があって、それなら使う側が名前をつけて区別できてもいいと思うけどなぁ。
2:00 AM
some Foosome Foo なら英語的に別の型を意味しそうという利点はある。
Avatar
omochimetaru 3/12/2019 2:00 AM
使う側が名前をつけてってどういう意味ですか?
2:00 AM
名前がほしいならそもそもの(Motivationの) struct LazyMapCollection で書けば良い気がしますが (edited)
Avatar
foo1 の返す some Foo には Bar と名前をつけて、 foo2 の返す some Foo には Baz と名前をつければ↓のようなことは起こらない。 var a: some Foo = foo1() let b: some Foo = foo2() a = b // `some Foo` と `some Foo` は字面上同じ型っぽいけど別の型なのでエラー
2:02 AM
名前がほしいならそもそもの(Motivationの) struct LazyMapCollection で書けば良い気がしますが
実装上の型を露出しない上での話。
Avatar
omochimetaru 3/12/2019 2:03 AM
でも Foo は実際にはプロトコル名だから、some Fooを変えようがないような (edited)
Avatar
↓みたいな何かでもいいのかもしれないけど、 -> <F: Foo> F のような記法を導入するなら何かジェネリクス的な記法で解決できないかなと。特に具体的なアイデアがあるわけじゃないけど。 typealias Bar = foo1.(some Foo) typealias Baz = foo2.(some Foo)
Avatar
omochimetaru 3/12/2019 2:05 AM
↑opaque typealiasをつけたところで、 依然として some Fooで受ける形にかけちゃいますよね
Avatar
↓みたいにすると、 foo1some Foo 間で別名を付けれてしまうので微妙。 var a: Bar = foo1()<Bar> let b: Baz = foo2()<Baz> a = b // エラー: `Bar` を `Baz` に代入できないのは自然に見える let c: Qux = foo1()<Qux> a = c // `foo1` の `some Foo` に別の名前を与えられてしまっている
2:06 AM
↑opaque typealiasをつけたところで、 依然として some Fooで受ける形にかけちゃいますよね
なので、 some Foo ではなく -> <F: Foo> F を採用したとして、うまく馴染む記法はないかなぁと。
2:08 AM
=== ↓これ、 where 後置記法を導入しちゃったから where でやろうとすると混ざっちゃうよね。 <> の中に書けばいけるかもだけど、引数側の型パラと並ぶとややこしそう。
こういうのはいけるか、今回の提案だと範囲外?だけど
func makeColl<X>() -> some Collection<.Element == X>
(edited)
2:10 AM
↓みたいになりそう。 func makeColl<X: Foo>() -> <C: Collection where C.Element == X> C where X.Bar == Int (edited)
2:10 AM
しかも、戻り値側の where だけ後置できないの微妙。
2:10 AM
あまり where の後置好きじゃない。
Avatar
omochimetaru 3/12/2019 2:11 AM
そもそも、: some Foo をつけずに var a = foo1() let b = foo2() a = b // エラー
2:11 AM
これだったら、普通のことだから、
2:11 AM
そこの特殊性が some という新しいキーワードによって表現されていて (edited)
2:12 AM
これまでにRustぐらいでしかない概念だからなじまないだけで、プログラマの常識がアップデート前だから変に感じちゃうだけな気もする。
2:13 AM
エラーメッセージでは関数名まで含んだ匿名な型名が出てくるしそこで理解できる気も。
as! (__opaque main.(file).S.foo()
2:14 AM
func makeColl<X: Foo>() -> <C: Collection where C.Element == X> C where X.Bar == Int ↑これを推してる人もいるっぽいですね。明示的なCが手に入るのが良いところ
Avatar
全てのsome Fooが代入不可ならシュッと受け入れられるんですけど、代入できるやつとできないやつが同じ型で表現されるのが… と思ったけどエラーメッセージに関数プレフィックス付くんですね
Avatar
全てのsome Fooが代入不可ならシュッと受け入れられるんですけど、代入できるやつとできないやつが同じ型で表現されるのが…
うん、これが引っかかってて、可読性が落ちそう・・・。エラーメッセージで出ても、レビューしてるときとか、すぐに同じ型かどうか判断できなさそう。
Avatar
omochimetaru 3/12/2019 2:18 AM
明示的なCがあると、 func makeColls() -> <C: Collection, D: Collection> (C, D) where D.Element ==C { return ([1,2,3] , [ [1], [2] ]) } こういうのが書けますね
2:18 AM
たしかに「代入できる場合である」ことの可読性は低いですねえ。
Avatar
ただ、とりあえず現状( opaque-type-ast ブランチ)では変数の型として some Foo を書くことはできないみたいです。仕様なのか現状の実装状況がそうなだけなのかわからないけど。
Avatar
omochimetaru 3/12/2019 2:19 AM
public protocol P { mutating func flip() } private struct Witness: P { mutating func flip() { /* ... */ } } public var someP: some P = Witness()
2:19 AM
プロポーザルとしては↑をふくんでいますよ
Avatar
public がついてるのはグローバル変数だから、ローカル変数とは扱いが異なるかも。
Avatar
internalな変数なら実装都合の型が露見しても良いってことですかね (edited)
Avatar
omochimetaru 3/12/2019 2:22 AM
let strings: some Collection = ["hello", "world"]
2:22 AM
その上に↑これがあった
Avatar
internalな変数なら実装都合の型が露見しても良いってことですかね
たしかにそれなら露見しても良さそうだけど、型推論なら some Foo で受けられるわけだし、変数で禁止する必要もなさそうに思います。
(edited)
Avatar
omochimetaru 3/12/2019 2:22 AM
For computed properties, the concrete type is determined by the return statements in the getter. Opaque result types can also be used in stored properties that have an initializer, in which case the concrete type is the type of the initializer:
Avatar
どこかに variables とも書いてあった気がするんだけど、
2:23 AM
現状では、プロパティはいいけど変数はダメだぜ的なエラーメッセージが出る。
Avatar
omochimetaru 3/12/2019 2:25 AM
internalな変数なら実装都合の型が露見しても良い
そもそも右辺値に来るfuncのシグネチャ定義の時点でopaque typeだから、実装の型はわからんのでは
(edited)
Avatar
単純に例として挙げてるのかと思ったら明確にエラーになるんですね、そうすると分からなくなってきた
Avatar
omochimetaru 3/12/2019 2:28 AM
型推論に対する明示的な記法みたいに、 opaque typeに対する明示的な記法として、caller側で、 var a: some Foo (S.foo1) = s.foo1() let b: some Foo (S.foo2) = s.foo2() a = b // 納得できる代入エラー (edited)
2:28 AM
みたいに書けたらどうでしょう?
2:30 AM
protocolによるassociated typeでfoo1とfoo2が同じsome Fooとして拘束されている場合は var a: some Foo (P.FooType) = s.foo1() let b: some Foo (P.FooType) = s.foo2() a = b と書かないとだめ。 (edited)
2:31 AM
opaque type の真の型が難しいのは、func固有の型だったり、型固有の型(inner typeのような)だったりする場合があることですよね。
2:32 AM
とすると、caller側でそのコンテキストを明記しておいてそれをコンパイラが検証すれば
2:32 AM
わかってあってればあってることが確認できる。
Avatar
引数 some Foo はシンタックスシュガーになるみたいなので、戻り値 some Foo も後からシュガーにできるのかな? func makeFoo() -> some Foo { /*...*/ } // ↑を↓のシュガーにできる? func makeFoo() -> <F: Foo> F { /*...*/ }
Avatar
omochimetaru 3/12/2019 2:33 AM
上から下はいけるけど、下から上は駄目な場合がありそう。
2:34 AM
下だと書けるパターンが出てくる気がする。
Avatar
func useFoo(_ foo: some Foo) { /* ... */ } // ↑は↓のシュガーとして将来的に導入される模様 func useFoo<F: Foo>(_ foo: F) { /* ... */ }
Avatar
omochimetaru 3/12/2019 2:34 AM
func makeFooPair() -> <F: Foo> (F, F) { /*...*/ }
Avatar
上から下だけでいいんじゃない?
Avatar
omochimetaru 3/12/2019 2:35 AM
コメントの↑と↓が(相互に)って意味かと思った。
2:35 AM
上から下だけはいけると思う。
Avatar
ただ、上が先に導入されることで、下の表現力がなくなってしまって、 -> <F: Foo> (F, F) みたいなのを ABI 上位表現できなくなったりしないかなと。
Avatar
omochimetaru 3/12/2019 2:35 AM
それは追加的だからどうにかなりそうです
2:36 AM
上の表現に収まる場合は上のABIでコード生成して
2:36 AM
はみ出る場合は新しいABIで生成すれば、古いバイナリが新しい機能をリンクしようとすることがないので。
Avatar
なるほど。別に統一の機構で表現しなくてもいいか。
Avatar
omochimetaru 3/12/2019 2:37 AM
よく「これはadditiveだからええんや」って言ってるのはそういう気持ちだと思ってます
Avatar
opaque result type 、 ABI additive でも、標準ライブラリに適用したときに API の互換性がぶっ壊れまくりそう・・・
Avatar
omochimetaru 3/12/2019 2:38 AM
APIとしてはそもそも破壊的ですね
2:38 AM
もともとLazyMapCollecitonを返してるやつがsome Collectionになってしまうんだから
2:38 AM
let c: LazyMapCollection = xs.lazy.map { ... }
2:38 AM
↑過去にこう書いてたら死ぬ
2:39 AM
そっちの問題はどうなるんでしょうね
2:39 AM
提案の方では議論されてないように見える。
2:39 AM
stdlibはもう塩漬けなのかしら。
Avatar
古いバイナリで標準ライブラリ使ってて、 API 変更されたら OS アップデートで死ぬ?
Avatar
omochimetaru 3/12/2019 2:39 AM
あいや、いいのか
2:40 AM
古いバイナリ向けには古い形式のstdlibを配布すればよいので、死ななそう。
Avatar
stdlibはもう塩漬けなのかしら。
Proposal のどこかに、 API にとっては破壊的だけどやる価値があるって書いてあった気がする。
Avatar
omochimetaru 3/12/2019 2:41 AM
APIについてのソースマイグレーションは、自動修正でなんとなく対応して
2:41 AM
バイナリについては昔のstdlibも配布すればいいからなんとかなりそう。
2:42 AM
If opaque result types are retroactively adopted in a library, it would initially break source compatibility (e.g., if types like EnumeratedSequence, FlattenSequence, and JoinedSequence were removed from the public API) but could provide longer-term benefits for both source and ABI stability because fewer details would be exposed to clients.
2:42 AM
ほんとだ、書いてあった。 (edited)
8:59 AM
2016年から無限放置されてたProperty Behavior(SE-0030)に急に動きが。 (edited)
9:00 AM
AST - Semaまで作ってあるっぽい。
9:00 AM
struct Wrapper<T> { var value: T } func testParsing() { let wrapped1: Int by Wrapper let wrapped2: Int by Wrapper = Wrapper(value: 5) let wrapped3 by Wrapper = Wrapper(value: 5) _ = wrapped1 _ = wrapped2 _ = wrapped3 }
9:01 AM
Kotlinみたいに型の後ろにby句を与えるスタイルっぽい
9:02 AM
func testSuppressUnwrap() { var wrapped1 by WrapperWithInitialValue = 5 let z = ^wrapped1 }
9:02 AM
謎のキャレットオペレータ
Avatar
話を戻してしまうけど、 Joe Groff の↓の Chris Lattner への反論、めちゃくちゃおもしろいこと言ってる気がする。 https://forums.swift.org/t/se-0244-opaque-result-types/21252/69 読み違えなければ、 Rust では existential type を記述するときに( Swift と違って)明示的に dyn キーワードを付けるようにするという決定が下されて、 Swift での過去の議論では同様のキーワードとして any が議論されていた。そして、そうなれば、 any Foo は existential type に、 some Foo は opaque type になると見越している?
Indeed, this is pretty much what opaque types boil down to, is the ability for a function to "output" generic parameters in addition to taking them as inputs. Another way we could conceivably notate this is by putting the output parameters after the ->, as a number of people ...
Avatar
omochimetaru 3/15/2019 9:29 AM
someキーワードが 、ExistentialをAnyHogehogeとして慣習的に使ってる事の対としてキレイって意見自体は、someの打診をしたスレで言ってた気がする
9:30 AM
このレスでは、Generalized Existential Typeを Any<P0> とか any P0 で書けるような文法が将来的に産まれたときうまいこといくというメリットも見据えてるよ、って補足かな?
Avatar
any Foosome Foo すごくキレイだと思うんだけど、それなら top type と bottom type も Ceylon みたいに AnythingNothing だったらキレイだったのになぁ。
9:47 AM
これ、英語に合わせる言葉遊びじゃなくて、英語の any, some, no の概念が良くできてるということな気がする。
Avatar
omochimetaru 3/15/2019 9:50 AM
AnyとNeverの方がオシャレな感じがします
9:51 AM
-thingだと1単語だけど2語みたいな感じだからゴツイ
Avatar
その感覚は理解できるけど、 Nothing の方が bottom type の本質を表している気がする。そして Nothing の対比としては Anything だろうなと。
9:56 AM
Kotlin は AnyNothing だし、 Any は top type じゃなくて Any? が top とかグダグダ。
9:57 AM
AnyNone とかでもいいのかもだけど、 AnyNone が対として自然なのかわからない・・・。
Avatar
omochimetaru 3/15/2019 9:57 AM
たしかにCeylonのやつが理論的にスキがないのはわかります
9:58 AM
Noneはoptionalで使っちゃったし、someの意味がここに来て2つ出来ちゃったのはしんどいですね
Avatar
まあ Optionalsome はほぼ使うことがないからいいんじゃないかな?
9:59 AM
別に .some はキーワードじゃなくてただの enumcase だし。言語の一部ではない。
Avatar
厳密にはそうすね
Avatar
パターンマッチにしても if case let .some(foo) = foo { ... }if case let foo? = foo { ... } みたいなシュガーが用意されてるから、 Optional.some を使うケースってほぼない気がする。
Avatar
omochimetaru 3/18/2019 7:19 AM
ORTスレ、クリスラトナーが、全く異なるアプローチ?のドラフトを投稿して、会話が伸びてる https://forums.swift.org/t/se-0244-opaque-result-types/21252/119?u=omochimetaru
Ok, here is a draft of the document, please take a look. In comparison to the proposal outlined here, this approach requires no new keywords or grammar productions (just adds a decl modifier, and undisables an existing grammar production in type aliases), it composes properl...
7:20 AM
opaque public typealias CertainMutableCollection<T> : MutableCollection & RangeReplaceableCollection = [T] (edited)
7:20 AM
こうやると、名前だけモジュール外にexposeできる、というアイデア。
7:21 AM
現状だと、internalな型は、publicなfuncの返り値はできないから、publicな型にして露出させちゃうけど、
7:21 AM
名前だけpublicにするって仕組み
Avatar
omochimetaru 3/18/2019 7:41 AM
Paulさんのこの文うける
Two of my tried and true Swift heuristics are “Joe Groff knows best” and “Chris Lattner knows best,” and these competing proposals put them in conflict!
Avatar
ワロタ
Avatar
omochimetaru 3/18/2019 7:51 AM
ラトナーが結構厳しい事言ってるなあ
7:53 AM
「このプロポーザルの第一の目的はAPI詳細隠蔽、Rustのimpl Traitはこの目的とはゴールが違う、彼らはstable ABIを気にしてないので世界が違う、ORTは過剰に複雑で侵略的な機能で、多くの技術的負債とコンパイラの複雑さをもたらすだろう」 (edited)
Avatar
omochimetaru 3/18/2019 8:31 AM
既存のExistential型を禁止して、anyキーワードをつけないといけないようにすると、綺麗になりそうだなあ
8:32 AM
<T: P>(T)と(P)の違いはわかりにくいけど、<T: P>(T)と(any P)ならわかりやすいと思うし、 前者が (some T) になれば (some T)と(any T)が違うものだと明らか
Avatar
@omochimetaru そうなんよねー。 any Foosome Foo だとめちゃくちゃキレイ。 https://forums.swift.org/t/se-0244-opaque-result-types/21252/140
It seems so beautiful. // generics func useAnimal( animal: A) { /* ... */ } // opaque argument types (sugar of ^) func useAnimal( animal: some Animal) { /* ... / } // existential (argument) types func useAnimal(_ animal: any Animal) { / ... */ } // "reverse generics" fu...
Avatar
anyとsomeは好きですねぇ
Avatar
Existentialに明示的にキーワード付けないといけなくするのも濫用を防げそうでいいですよね。インタフェース感覚で使われることを防止する効果もありそう。
9:36 AM
フォーラムのスレッド見てても ORT の概念に混乱してる人多そうだし、 ORTの前に reverse generics を提案した方が良かったのかな。
Avatar
PR のブランチをチェックアウトしてコンパイラをビルドすれば… CIによってビルドされたmacOS用toolchainがPRのコメントに載っているので、それをダウンロードすれば自分でビルドしなくても試せます。 コメント: https://github.com/apple/swift/pull/21137#issuecomment-468118328 toolchain: https://ci.swift.org/job/swift-PR-toolchain-osx/216//artifact/branch-master/swift-PR-21137-216-osx.tar.gz (edited)
WIP towards a prototype of an MVP subset of https://forums.swift.org/t/opaque-result-types/15645 . For an initial implementation, this won't include the resilience, second-order where constrain...
🙏 1
Avatar
いただいたコメントを追記しておきました。
👍 1
Avatar
The review of SE-0250: Swift Code Style Guidelines and Formatter begins now and runs through April 10, 2019. The proposal is written by @allevato and @dabrahams. Please note that there has been significant discussion already on the pitch thread. The Core Team will incorpor...
12:40 AM
スタイルガイドのレビューだ。どんどん来るな。
Avatar
このプロポーザルは公式スタイルガイドとフォーマットツールをSwiftプロジェクトに取り込むことを決めるだけで、 スタイルそれ自体はこれが通ったあとで別のプロポーザルでやっていくと
Avatar
フォーマッタ欲しいよね
Avatar
このレビュー4/10までやっててだいぶ長い
Avatar
レビュー期間ってどういう風に決められてるんだろ?内容からCore TeamかReview Managerが決めてるのかな?
Avatar
omochimetaru 3/21/2019 2:59 AM
そう思う SEプロセスの説明のとこに書いてあるかも?
Avatar
reverse generics を提供してる言語ってあるかな?
Avatar
↓と同じことって opaque type alias ならできるけど opaque result type ではできなくない? func makeAnimals() -> <A: Animal> (A, A) { return (Cat(), Cat()) } (edited)
9:53 AM
// opaque type alias opaque typealias A: Animal = Cat func makeAnimals() -> (A, A) { return (Cat(), Cat()) }
9:54 AM
opaque type alias って reverse generics と等価(単に面倒な構文なだけ)な気がするんだけどそんなことない? (edited)
Avatar
norio_nomura 3/26/2019 2:22 PM
Xcode 10.2のSwift 5.0と https://swift.org/download/ からダウンロードした swift-5.0-RELEASE とで、SourceKitのレスポンスが違う…
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
🤔 2
Avatar
norio_nomura 3/26/2019 2:33 PM
Xcode 10.2はGitHubで公開されてるコミットに追従できていない疑いがある。
Avatar
@norio_nomura 詳細知りたいです。
3:04 PM
これで、DocInfoTests.testDocInfoRequest()の結果がXcode 10.2と https://swift.org/download/ からダウンロードしたものの結果が違うのです。
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
ありがとうございます。見てみますー。
Avatar
norio_nomura 3/26/2019 3:06 PM
PRはXcode 10.2の出力を前提に書かれてるので、チェックアウトして $ xcrun --toolchain org.swift.5020190325a swift test --filter testDocInfoRequest で再現できます。 (edited)
Avatar
現象自体は確認できました。もし可能であれば単体のテストケース作って bugs.swift.org にいただけるとありがたいです。
Avatar
Homebrewで配布しているsourcekittenを使ったテストでも良いですか?
Avatar
ぜんぜん大丈夫です
11:37 PM
JIRAはいつになったら絵文字使えるようになるのだろう。
Avatar
ありがとうございます!
Avatar
マルチラインドキュメンテーションコメントの、末尾が違うみたいです。 key.request: source.request.docinfo key.sourcetext: " /** Multiple line commented function. **/ func multiLineCommentedFunc() { } "
Avatar
* が普通の文字列として判定されるか、リストの bullet として判定されるかの差異ですね。 (edited)
Avatar
なるほど。
Avatar
SourceKittenで各バージョンのSwiftが返す値をテストして来ましたが、Xcodeと https://swift.org/download/ のツールチェインで結果が違うというのは初めて遭遇したかな。
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
JIRA にコメントされてますが、
  • CommonMark に10.2と5.0-RELEASEで差異がある
  • 10.2の方が新しいCommonMarkであり、本来は5.0-RELEASEも10.2と同じ動作をすべき
  • リリースのミス。5.1では同じ間違いをしないようにします
Avatar
norio_nomura 3/27/2019 2:52 AM
ありがとうございます。把握してもらえて安心しました。
Avatar
omochimetaru 3/27/2019 4:22 AM
cmarkの差なのか、なるほどすごいコーナー
10:30 PM
キーパスが関数になった
Avatar
おおー
Avatar
今後のオシャレテク
Avatar
これはいいね
Avatar
↓これはできない? let bar: Bar = \Foo.bar(foo) (edited)
Avatar
どうでしょう
Avatar
それはできないですね。それだと func bar(_: Foo) メソッドを呼び出す keyPath になってしまう。
Avatar
ああ、カッコをつけるとどうでしょう?
Avatar
(\Foo.bar)(foo) どうでしょう。
Avatar
↓はできるみたいですけどどこまでできるんでしょうね。 let bar = (\Foo.bar as (Foo) -> Bar)(foo)
Avatar
メソッドを呼び出す keyPath になってしまう
なるほどw
Avatar
(foo)let bar: Bar から (Foo) -> Bar を期待していると解釈してくれれば let bar: Bar = (\Foo.bar)(foo) でも通る可能性あるかな?さすがにきついかな…。
Avatar
The review of SE-0257: Eliding commas from multiline expression lists begins now and runs through April 18, 2019. The proposal is written by @nate_chandler and @anandabits. Reviews are an important part of the Swift evolution process. All review feedback should be either on...
Avatar
提案にも書かれてる、次の行とつながるパターンとの兼ね合いが不安
Avatar
基本的には , 無い場合は普通のfunc ボディ内に書いたのと同じルールで分割されるので、ルール上の問題はないのですが、
12:43 AM
_ = [ "foo": foo .method() "bar": baz ] こういうのはつらい。<コーディング規約で禁止するしかない。 (edited)
Avatar
fooのメソッドなのか、そこの型コンテキストに対するドット式なのか曖昧?
Avatar
ですね。
12:46 AM
func test() { foo .method() bar }func test() { foo.method(); bar; } であり、そのルールで動くので、上に書いた例でも問題はなくパースできるのですが、リーダビリティ的には止めて欲しいっていう意味です。 (edited)
Avatar
そのケースに限って言えばフォーマッタが.methodの行を1段下げてくれれば問題なさそうだなあ
12:52 AM
揃ってる状況だと人間が先読みしないとパースできないのでつらいけど。
Avatar
omochimetaru 4/10/2019 8:27 AM
let solutions = [ 2*(1-sqrt(a))*sqrt(b+sqrt(b)) -(1+sqrt(a))(sqrt(2*b)-sqrt(2)) ] // two solutions let solutions = [ 2*(1-sqrt(a))*sqrt(b+sqrt(b)) - (1+sqrt(a))(sqrt(2*b)-sqrt(2)) ] // one solution
8:28 AM
厳しい
Avatar
docker image作った。 $ docker run --privileged -it -v `pwd`:`pwd` -w `pwd` --rm norionomura/swift:pr-22714 swift Welcome to Swift version 5.0-dev (LLVM 771292f12a, Swift 474d293b05). Type :help for assistance. 1> print( 2. "hello" 3. "world" 4. ) hello world
Avatar
omochimetaru 4/15/2019 1:50 AM
A pitch to make some ABI annotations used in the standard library available to all Swift users. Proposal PR here Introduction One of Swift's goals is to be a good language for libraries with binary compatibility concerns, such as those shipped as part of Apple's OSs. This i...
1:51 AM
アプリをリビルドせずにライブラリのバイナリをアップデートできるようになるLibrary evolutionのピッチ
1:52 AM
すでに標準ライブラリで実現されていることを、ユーザに解放する。 コンパイル時にevolutionモードでビルドする選択肢が与えられることと、内部オプションだったflozenが公式になる。
Avatar
これはswiftだけの問題なのかな?appstoreのポリシーもあるのでは (edited)
Avatar
omochimetaru 4/15/2019 1:53 AM
iOSアプリの場合、開発時点での第三者ライブラリを配布できるだけで
1:54 AM
AppStoreから配信されたアプリの内部のライブラリをアップデートすることはないんじゃないかな。
1:54 AM
たとえば、今はCarthageではみんなが手元でコンパイルしてるけど、最初からビルドしておいたバイナリを配布するようにするとか。 (edited)
1:57 AM
他の言語と比べると、値型のフィールドを追加できるのが面白いと思った。 スタックにメモリ確保するときにメタタイプからサイズを取ってくるのでそこが動的になってる。
1:58 AM
その方法なら値型のデータ自体はスタックに置き続けることができる。
Avatar
inlinableってジェネリクスのspecializeもやってくれると思ってたんですがやってくれないんでしょうか? https://github.com/t-ae/inlinable-performance/blob/master/Sources/inlinable-performance/inlinable_performance.swift public func matmul_base<T: Numeric>(lhs: [T], rhs: [T], m: Int, n: Int, p: Int) -> [T] { return matmul_internal(lhs: lhs, rhs: rhs, m: m, n: n, p: p) } @inlinable public func matmul_inlinable<T: Numeric>(lhs: [T], rhs: [T], m: Int, n: Int, p: Int) -> [T] { return matmul_internal(lhs: lhs, rhs: rhs, m: m, n: n, p: p) } public func matmul_specialize(lhs: [Double], rhs: [Double], m: Int, n: Int, p: Int) -> [Double] { return matmul_internal(lhs: lhs, rhs: rhs, m: m, n: n, p: p) } 以上のように内部実装は共通でインターフェースだけ違うのを計測してみると、 https://github.com/t-ae/inlinable-performance/blob/master/Tests/inlinable-performanceTests/inlinable_performanceTests.swift Test Case '-[inlinable_performanceTests.inlinable_performanceTests testBase]' passed (11.864 seconds). Test Case '-[inlinable_performanceTests.inlinable_performanceTests testInlinable]' passed (11.498 seconds). Test Case '-[inlinable_performanceTests.inlinable_performanceTests testSpecialize]' passed (0.340 seconds). と素のものとinlinableで同程度になっています。 インライン化と同時にじゃないとspecializeされないってのがありそうかなーと思っています。
Contribute to t-ae/inlinable-performance development by creating an account on GitHub.
Contribute to t-ae/inlinable-performance development by creating an account on GitHub.
Avatar
omochimetaru 4/16/2019 8:12 AM
速度で判別するよりIRを見たほうが良いと思います
Avatar
swift test -c release で計測してる?
Avatar
@koher もちろんです。
8:13 AM
@omochimetaru モジュール跨ぎはやったこと無いので調べながらやってみます……
Avatar
お、そんな便利なのが。>save-optimization-record (edited)
Avatar
omochimetaru 4/16/2019 8:18 AM
ちゃんと試してないけど -emit-module でモジュール作って、 -Iでインポート とかな気がする
Avatar
--- !Passed Pass: sil-generic-specializer Name: sil.Specialized DebugLoc: File: /Users/araki/Desktop/t-ae/inlinable-performance/Tests/inlinable-performanceTests/inlinable_performanceTests.swift Line: 30 Column: 26 Function: 'closure #1 in inlinable_performanceTests.testInlinable()' Args: - String: 'Specialized function ' - Function: '"inlinable_performance.matmul_inlinable<A>(lhs:rhs:m:n:p:)"' - String: ' with type ' - FuncType: '(@guaranteed Array<Double>, @guaranteed Array<Double>, Int, Int, Int) -> @owned Array<Double>' ... うーん?
Avatar
omochimetaru 4/16/2019 8:24 AM
<A> => [Double] でされてるね
Avatar
--- !Missed Pass: sil-generic-specializer Name: sil.NoDef DebugLoc: File: /Users/araki/Desktop/t-ae/inlinable-performance/Tests/inlinable-performanceTests/inlinable_performanceTests.swift Line: 31 Column: 13 Function: 'closure #1 in inlinable_performanceTests.testInlinable()' Args: - String: 'Unable to specialize generic function ' - Callee: '"XCTest.XCTAssertEqual<A>(_:_:_:file:line:)"' - String: ' since definition is not visible' ... 呼び出し側がミスしてる?
8:27 AM
いやこれはXCTAssertEqualのログだ
8:32 AM
// matmul_inlinable<A>(lhs:rhs:m:n:p:) sil [serialized] @$s21inlinable_performance07matmul_A03lhs3rhs1m1n1pSayxGAH_AHS3itSjRzlF : $@convention(thin) <τ_0_0 where τ_0_0 : Numeric> (@guaranteed Array<τ_0_0>, @guaranteed Array<τ_0_0>, Int, Int, Int) -> @owned Array<τ_0_0> // matmul_specialize(lhs:rhs:m:n:p:) sil @$s21inlinable_performance17matmul_specialize3lhs3rhs1m1n1pSaySdGAH_AHS3itF : $@convention(thin) (@guaranteed Array<Double>, @guaranteed Array<Double>, Int, Int, Int) -> @owned Array<Double> SIL的にはinlinableはジェネリックなままみえてそうですね
Avatar
omochimetaru 4/16/2019 8:50 AM
最適化されるとspecializeされたSILができる
8:50 AM
SIL生成直後はまだジェネリックしかない
Avatar
ああ、-Oつけわすれてました。 つけるとmatmul_inlinableが消える代わりにmatmul_internalがジェネリックなまま出てきますね。
8:58 AM
どうやら@usableFromInlineなジェネリックメソッドを@inlinableなメソッドでspecialize出来ていないぽい。
まさにこれに該当しそうです。
😂 1
Avatar
matmul_internalはusableFtomInlineが付いてるの?
Avatar
付いてますよ。ついてないとinlinableから呼べないです。
Avatar
usableFtomInlineは
12:58 AM
inlineableから呼ばれてても良い つまり実態としてはABI publicだけど APIとしては外から呼べない
12:59 AM
って用途だったから、展開されたinlineableの中からは、ただの呼び出しとして維持されるので、正しい気がする
12:59 AM
呼べるだけで中身はpublicじゃないから更なるインライン展開やスペシャライズはできない
1:00 AM
matmul_specializeの方は
1:00 AM
モジュールをビルドする時点で展開されるから
1:00 AM
動いてる
Avatar
matmul_specializeについてはそうでしょうね。 (edited)
Avatar
omochimetaru 4/17/2019 1:02 AM
inlineable を指定するとSILコードが外に晒されるから最適化できる
1:02 AM
usableFromInlineは関数ヘッダーが見えるだけだと思う
Avatar
あれ?internalもinlinableにできるんでしたっけ……
1:03 AM
そもそも認識が間違っていた可能性が
Avatar
omochimetaru 4/17/2019 1:03 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
@usableFromInlineから@inlinableにしたらたしかにインライン化されました。
Avatar
omochimetaru 4/17/2019 1:05 AM
The attribute can only be applied to declarations with public or internal visibility.
Avatar
inlinable privateだと '@inlinable' attribute can only be applied to public declarations, but 'matmul_internal' is private なるメッセージが出るのでpublic onlyと誤解した可能性が高そうです。
Avatar
omochimetaru 4/17/2019 1:06 AM
internalでもinlinableにできんのか。
1:06 AM
それは知らなかった。
1:08 AM
たしかにそのエラーメッセージはわかりにくい
1:08 AM
bugsにチケット出したら?すでにありそうな気もする
Avatar
エラーメッセージ修正だけならPR出してコントリビューターになるチャンスも (edited)
1:10 AM
https://bugs.swift.org/browse/SR-8212 すでにありました。
Avatar
omochimetaru 4/17/2019 1:12 AM
パッチ作るの簡単そう
Avatar
むしろメッセージの内容のほうが難しそうですね
1:12 AM
コメントでその件で話してるみたいです。
Avatar
omochimetaru 4/17/2019 1:14 AM
メッセージ内容というか
1:15 AM
メソッドがinternal + inlineableでもクラスがinternal + usableFromInlineじゃないと
1:15 AM
いけないから
1:15 AM
「inlineableはpublic or internalにしかつけられません」は偽って事だよね
Avatar
クラスがusableFromInlineじゃなくてもコンパイルは通るみたいです。 でインライン化はされないんだと思います。
Avatar
omochimetaru 4/17/2019 1:17 AM
Slavaのサンプルコードが間違ってる?
Avatar
class C { @inlinable func f() {} // error } ここでerrorって言ってるのは少なくともコンパイルエラーのことではなさそう
Avatar
omochimetaru 4/17/2019 1:17 AM
もしコンパイルが通るとすれば
1:17 AM
それはそれでかなりわかりにくい、なぜかインライン化されない現象が
1:17 AM
生じる事になるが・・・
Avatar
@inlinable public func x() { let c = C() c.f() } Class 'C' is internal and cannot be referenced from an '@inlinable' function 結局CがusableFromInlineじゃないと他のところでコンパイルが通らないですね。
1:19 AM
それを指してerrorと書いてるのか
Avatar
omochimetaru 4/17/2019 1:19 AM
それはメソッドfが無関係じゃない?
Avatar
まぁそうなんですが
Avatar
omochimetaru 4/17/2019 1:20 AM
「inlineableにならない」ではないか?
1:20 AM
「通常inlineableはusableFromInlineも暗黙に与えるが、それはouter scopeがusableFromInlineの場合に限る」 (edited)
1:21 AM
だから、 「C.fが、inlineableではあるが、usableFromInlineではない」状態が発生するんじゃない?
Avatar
inlinableだけどusabeFromInlineじゃない状態をerrorと呼んでるというのが合ってそうですかね。inlinableだけど決してインライン化されないという実装者の意図に反した状態で。
Avatar
omochimetaru 4/17/2019 1:32 AM
かなあ。「決して」が確証がない、なんかやりようがあるんかな。
1:32 AM
あと、「実装者の意図」が、モジュール外だった場合にってことだよね。 (edited)
Avatar
モジュール内でinlinableないとインライン化されないケースってなんかあります?
Avatar
omochimetaru 4/17/2019 1:33 AM
[omochi@omochi-iMac-PC43 mdi]$ swiftc -emit-module m.swift [omochi@omochi-iMac-PC43 mdi]$ swiftc -silgen -I . a.swift ↑これでコンパイルできたけど、実行ができない。
Avatar
僕の方はFrameworkつくって-Fで与えました。
Avatar
omochimetaru 4/17/2019 1:34 AM
モジュール内は常に全部inlineableか?
1:34 AM
inlineableは外向けの影響しかないか。
1:34 AM
内向けでヒントしたりするのは @inline(always) とかか。
Avatar
ですね。
Avatar
omochimetaru 4/17/2019 1:35 AM
僕の方はFrameworkつくって
どうやるの?
Avatar
上に貼ったプロジェクトがSPMなんでxcodeprojからビルドした生成物を使いました。
Avatar
omochimetaru 4/17/2019 1:35 AM
ああ、なるほど・・・
1:41 AM
少し進んだ
1:42 AM
inlineableだけどusableFromInlineじゃない状態って意義あるのかな
1:42 AM
ないんだとすれば、その時点でエラーにしてやったほうがよさそうだ
Avatar
ちょっと思いつかないですよね。
Avatar
omochimetaru 4/17/2019 1:43 AM
で、「メソッドをinlineableにするにはクラス本体をusableFromInlineにしてください」って
1:43 AM
エラーメッセージを出す仕組みが別途あればいい?
Avatar
それがベストだと思います。
Avatar
omochimetaru 4/17/2019 1:44 AM
このスレッドで聞いてみるか
Avatar
mark outer scope as @usableFromInline or make outer scope publicですかね
Avatar
omochimetaru 4/17/2019 1:44 AM
俺でもいいけど書き込む?
Avatar
特にこだわりないんでお願いします。
Avatar
omochimetaru 4/17/2019 1:44 AM
OK
Avatar
omochimetaru 4/17/2019 1:53 AM
かきこんどいた
🙏 1
1:57 AM
コンパイルできたけどlibSwiftCoreが無いって言われてしまう
1:57 AM
LC_RPATHが指定できれば良さそう
2:00 AM
お、できた
2:04 AM
$ swiftc -parse-as-library -emit-object m.swift $ swiftc -emit-module m.swift $ swiftc -I . a.swift m.o -Xlinker -rpath -Xlinker /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx $ ./main
Avatar
norio_nomura 4/17/2019 2:28 AM
呼べるだけで中身はpublicじゃないから更なるインライン展開やスペシャライズはできない
なるほど、そういう事か。
Avatar
omochimetaru 4/17/2019 2:28 AM
これもできた $ swiftc -emit-library m.swift $ swiftc -L . -lm -I . a.swift -Xlinker -rpath -Xlinker /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx $ ./a
2:29 AM
@norio_nomura usableFromInlineはそうやって本体のバイナリ公開を抑制することで後のバイナリアップデートに備えるための指定子っぽいですね。
Avatar
norio_nomura 4/17/2019 2:32 AM
A pitch to make some ABI annotations used in the standard library available to all Swift users. Proposal PR here Introduction One of Swift's goals is to be a good language for libraries with binary compatibility concerns, such as those shipped as part of Apple's OSs. This i...
Avatar
omochimetaru 4/17/2019 2:32 AM
はい。SE0192のproposalの時点でmotivationに > Implementing support for library evolution ...
2:32 AM
って記述があるのにさっき気がついた。
2:33 AM
ABI長期計画ちゃんとつながっててえらい
Avatar
norio_nomura 4/17/2019 2:37 AM
ジェネリックメソッドを@inlinableにした場合、内部で使っているジェネリックメソッドも@inlinableにしておかないと、@_specializeを使わない限り完全にはspecializeされないって事だよね。これは悩ましいな。 (edited)
Avatar
omochimetaru 4/17/2019 2:39 AM
内部のメソッドを @inlinable internal にするのがやりたいことではないです? (edited)
Avatar
norio_nomura 4/17/2019 2:43 AM
@inlinable internalなメソッドを変更した場合、ABIが変わるって事だよね。
Avatar
omochimetaru 4/17/2019 2:43 AM
そうですね。バイナリ互換性は保てない。
2:44 AM
インライン化してほしい=利用側にコードを埋め込みたい、ということだから、このジレンマはどうしようもない。
2:45 AM
バイナリだけアップデートしたとき、すでに埋め込まれたコードは差し替わらないので。
Avatar
norio_nomura 4/17/2019 2:46 AM
じゃあ、ABIを維持するためにジェネリックメソッドを@usableFromInline internalにすると、今度はそれを@inlinableから使った場合に遅くなってしまう。
2:47 AM
結果、何も考えずに@inlinableを付けただけだと遅くなる場合がある。
Avatar
omochimetaru 4/17/2019 2:48 AM
inlinableな関数gが非ジェネリックで、内部の関数fがジェネリックなとき、そうなりますね。
2:49 AM
inlinableな関数gもジェネリックパラメータを持っていて、それをfに転送しているだけの場合は、inlienableをつけなかったとしても結果は同じだけど、
2:49 AM
gが非ジェネリックな場合は、gの中から呼び出すfが専用に最適化されるから、inline化しないほうが良いって事に。
2:50 AM
あ、でも、そういうケースは
2:50 AM
fの @_specialize(T = Int) の使いどころか?
2:51 AM
fのスペシャライズ版が生成され、かつ、存在が明示的になるから、gからf<Int> が呼ばれるようになって、 その特殊化版を呼ぶgが、利用側でインライン化されるなら
2:51 AM
遅くならない。 そこまで理解してないと遅くなっちゃう可能性があるのはそうですね。
Avatar
norio_nomura 4/17/2019 2:53 AM
んー、以前試した時は、gがジェネリックな場合はfとgの両方に@_specialize を付けないとダメだった気がする。
Avatar
omochimetaru 4/17/2019 2:54 AM
gがジェネリックな場合はそうなると思います。
2:55 AM
func gGeneric<T>(_ x: T) { f(x) } func gInt(x: Int){ f(x) } func f<T>(_ x: T) { ... }
Avatar
norio_nomura 4/17/2019 2:57 AM
@_specializeがもっと書きやすければいいのだけど。 ジェネリックパラメータが多いと大変。 extension StringProtocol { @usableFromInline @_specialize(where Self == String, S == String, T == String) @_specialize(where Self == String, S == String, T == Substring) @_specialize(where Self == String, S == Substring, T == String) @_specialize(where Self == String, S == Substring, T == Substring) @_specialize(where Self == Substring, S == String, T == String) @_specialize(where Self == Substring, S == String, T == Substring) @_specialize(where Self == Substring, S == Substring, T == String) @_specialize(where Self == Substring, S == Substring, T == Substring) … (edited)
Avatar
omochimetaru 4/17/2019 2:57 AM
gGeneric = inlinable : ジェネリックなfを呼び出すgGeneric が展開されるだけ、遅い gInt そのまま : gInt 内部に 特殊化された f の呼び出しが展開される、早い gInt = inlineable : ジェネリックなfを呼び出す gInt が展開されるだけ、遅い gInt = inleinable + f specialized(Int): Intに特殊化された f を呼び出すgInt が展開される、早い ( このパターンが僕の仮説)
2:58 AM
gGeneric = inlineable + f specialized(Int) : Intに特殊化されたfは生成されるけど、gGenericから呼び出すf はジェネリックT な fにすぎないので、遅い
2:59 AM
gGeneric specialized(Int) : Int に特殊化されたgが生成されて、その中で f が特殊化されるので早い gGeneric specialized(Int) + inlineable : Int に特殊化されたgが生成されるけど f はジェネリックなので ジェネリックな f の呼び出しが展開されるだけで遅い
3:00 AM
gGeneric specialized(Int) inlinable + f specialized (Int) : Int に特殊化されたgとIntに特殊化されたfがあるので展開されて早い
3:00 AM
String / Substring x Self / S / T で 2^3 = 8 通りあるんですか・・・
3:01 AM
Specializeに組み合わせ表記があったら嬉しいですね
3:01 AM
@_specialize(where Self == String x Substring, S == String x Substring , T == String x Substring) (edited)
3:01 AM
↑これで8通りを書き並べたのと同じになる
Avatar
norio_nomura 4/17/2019 3:06 AM
gInt = inleinable + f specialized(Int): Intに特殊化された f を呼び出すgInt が展開される、早い ( このパターンが僕の仮説)
これはこの通りだった気がする。
Avatar
omochimetaru 4/17/2019 3:09 AM
なるほど。そこで f に specialized を付けないと遅くなっちゃうってのは たしかに↓のとおりですね >何も考えずに@inlinableを付けただけだと遅くなる場合がある。
Avatar
norio_nomura 4/17/2019 3:26 AM
また@inlinable周りは検証し直さないといけないな。 (edited)
Avatar
omochimetaru 4/17/2019 3:36 AM
SwiftPMのビルドを調べてるけど、SwiftPMは一発でswiftmoduleとobject(*.swift.o)を生成してるっぽいんだけど、コマンドを真似しても再現できない・・・
Avatar
omochimetaru 4/17/2019 3:55 AM
ああああ・・・・ (edited)
3:56 AM
フルパスで与えないとoutput-file-mapとマッチングしねえのか・・・
Avatar
omochimetaru 4/17/2019 4:07 AM
{ "": { }, "/Users/omochi/temp/mdi/m.swift": { "object": "/Users/omochi/temp/mdi/b/m.swift.o" } } #!/usr/bin/env ruby require "shellwords" cmd = [ "swiftc", "-emit-dependencies", "-emit-module", "-emit-module-path", "b/m.swiftmodule", "-output-file-map", "map.json", "-parse-as-library", "-emit-object", "/Users/omochi/temp/mdi/m.swift" ] system(cmd.shelljoin) (edited)
4:08 AM
これで .o と .swiftmodule を一発で作れた。
Avatar
Joe_Groff I have (belatedly) generated a new toolchain with the latest implementation of the feature, which also supports the ABI resilience aspects of the proposal, and uses the proposed some P syntax:
https://forums.swift.org/t/se-0244-opaque-result-types-reopened/22942/52
I have (belatedly) generated a new toolchain with the latest implementation of the feature, which also supports the ABI resilience aspects of the proposal, and uses the proposed some P syntax:
4:39 AM
早くない?
4:39 AM
いつもレビュー期間終わって結構長い間そのままなのに。
Avatar
omochimetaru 4/18/2019 4:39 AM
はやっ
4:40 AM
しかもコメントがなにもない
4:40 AM
SE-0244 has been accepted.
4:40 AM
いや、レビュースレッドの末尾に書いてあるのか
4:41 AM
Several reviewers felt that being able to name opaque types is an important feature for many use cases. This is clearly a useful feature and would be a good next step, but the core team thinks that the feature as proposed consists of a reasonable "minimum viable product" to land now, and then can be added to through subsequent proposals.
Avatar
昨日までレビュー期間で西海岸時間だから、 Core Team の間で結論すでに出ててレビュー期間終わって即 accept されたのかな?
Avatar
omochimetaru 4/18/2019 4:42 AM
いくらかのレビュワーがOpaqueTypeに名前をつける機能(ReverseGenericsとかでしょうね)を大事って言ってるけど、minimum viable productを出すのが良いと結論した、みたいな。
Avatar
レビュースレッドに Chris Lattner が現れなかったのは、予め話して納得したのかな??
Avatar
omochimetaru 4/18/2019 4:42 AM
たしかに。
4:42 AM
opaque typealiasで議論になってたのに
4:43 AM
こっちにはこなかったですね。たしか将来的な方向についてまとまってなさすぎるってラトナも指摘してたから
4:43 AM
「 Generics UI Improvements overview」をまとめるときに一緒に話してそう
Avatar
これが accept されたってことは、 existential に any がつくとこまで既定路線なのかな?
Avatar
omochimetaru 4/18/2019 4:45 AM
基本的にはそうでしょうね、今後プロポーザルが出てきそう
Avatar
March 18, 2019 (final branching): The swift-5.1-branch will have changes merged from master one last time. After the final branch date there will be a “bake” period in which only select, critical fixes will go into the release (via pull requests).
https://swift.org/blog/5-1-release-process/ これ 5.1 に間に合わなかったかな?それとも重要機能で取り入れられる?
(edited)
This post describes the goals, release process, and estimated schedule for Swift 5.1.
Avatar
omochimetaru 4/18/2019 4:46 AM
Generics Manifestoでも長いこと進まなかったやつとかもあるから、Generics Improvementsのどれがどの順番でどんくらいのペースで進むのかは結構ブレそうだけど
4:47 AM
間に合って無さそうですね
4:47 AM
でもこれまでも滑り込みで機能追加することあった気がする
Avatar
Result とか滑り込みだったっけ?
4:53 AM
Result よりは重要そうだけど、実装も大変そうだから余裕ももって 5.1 は回避されるかもしれないなぁ。
4:53 AM
標準ライブラリの変更とかも考えるときついかな。
Avatar
omochimetaru 4/18/2019 4:54 AM
いずれにしても、標準ライブラリの型をsomeに書き換える作業が間に合わ無さそう
Avatar
標準ライブラリの型をsomeに書き換える
って、プロポーザルに含まれてます?
Avatar
omochimetaru 4/18/2019 4:55 AM
このプロポーザルには含まれてないですね、そういえばGenerics Improvementsにも書いてないな
Avatar
含まれてないなら別プロポーザル必要な気がする。
Avatar
omochimetaru 4/18/2019 4:55 AM
最初のプロポーザルのMotivationには書いてあったと思うけど
4:56 AM
プロポーザルの内容それ自体に出てきたことは無いです
Avatar
omochimetaru 4/25/2019 7:40 AM
@swift-5.1.5 swiftc -emit-sil -O func main() -> Int { let hoge: Int? = 1 let fuga = hoge .map { $0 * 2 } .map { $0 + 3 } .map { $0 * 4 } return fuga ?? 99 } main() (edited)
Avatar
exit status: 2 with stderr:error: unable to invoke subcommand: /usr/bin/swift-swiftc (No such file or directory) (edited)
Avatar
omochimetaru 4/25/2019 7:40 AM
@swift-5.1.5 -help (edited)
Avatar
OVERVIEW: Swift compiler USAGE: swift OPTIONS: -assert-config <value> Specify the assert_configuration replacement. Possible values are Debug, Release, Unchecked, DisableReplacement. -continue-building-after-errors Continue building, even after errors are encountered -debug-info-format=<value> Specify the debug info format type to either 'dwarf' or 'codeview' -debug-info-store-invocation Emit the compiler invocation in the debug info. -debug-prefix-map <value> Remap source paths in debug info -D <value> Marks a conditional compilation flag as true -enable-library-evolution Build the module to allow binary-compatible library evolution -enforce-exclusivity=<enforcement> Enforce law of exclusivity -framework <value> Specifies a framework which should be linked against -Fsystem <value> Add directory to system framework search path -F <value> Add directory to framework search path -gdwarf-types Emit full DWARF type info. -gline-tables-only Emit minimal debug info for backtraces only -gnone Don't emit debug info -g Emit debug info. This is the preferred setting for debugging with LLDB. -help Display available options -index-store-path <path> Store indexing data to <path> -I <value> Add directory to the import search path -j <n> Number of commands to execute in parallel -L <value> Add directory to library link search path -l<value> Specifies a library which should be linked against -module-cache-path <value> Specifies the Clang module cache path -module-link-name <value> Library to link against when using this module -modul (edited)
Avatar
omochimetaru 4/25/2019 7:41 AM
@swift-5.1.5 -Xfrontend -emit-sil -Xfrontend -parse-as-library -O func main() -> Int { let hoge: Int? = 1 let fuga = hoge .map { $0 * 2 } .map { $0 + 3 } .map { $0 * 4 } return fuga ?? 99 } (edited)
Avatar
sil_stage canonical import Builtin import Swift import SwiftShims func main() -> Int (edited)
Avatar
プロトコル準拠って、デフォルトパラメータの有無も含むのか。 @swift-5.0.3 protocol X { func say(sentence: String) func say() } struct A: X { // error: Type 'A' does not conform to protocol 'X' func say(sentence: String = "I'm fine, you ?") { print("A : \(sentence)") } } (edited)
Avatar
exit status: 1 with stderr:<stdin>:6:8: error: type 'A' does not conform to protocol 'X' struct A: X { ^ <stdin>:3:8: note: protocol requires function 'say()' with type '() -> ()'; do you want to add a stub? func say() ^ (edited)
Avatar
あいや、違うか。
12:12 AM
デフォルトパラメータを使うと、コンクリートタイプの実装よりプロトコルエクステンションが優先されるらしい。 https://forums.swift.org/t/different-behavior-using-default-values-with-extension-and-struct/23675/1 (edited)
👋 Introduction Method defined on Extension seems to override the default method when default values are used. ⬇ Example import Foundation protocol X { func say(sentence: String) } extension X { func say(sentence: String = "Hello Jessy") { print("X :...
Avatar
プロトコル定義にはデフォルトパラメータの有無とか無いから、パラメータを渡さず呼び出した時にプロトコルが求めるメソッドと見なされないのか。
Avatar
デフォルトパラメーターの話でいうと、プロトコル関係ないところで、引数なしのメソッドがあったところに、次のバージョンで引数ありの同名メソッド(デフォルトパラメーターあり)を追加・置き換えすると、一見ソース互換あるように思うけど、メソッド参照として使っていたところはソース互換なくなるし、シンボルとしても引数なし版が存在しなくなるのでバイナリ互換もなくなったりしますね (edited)
Avatar
norio_nomura 4/26/2019 1:03 AM
なるほど。ABI維持を考えると、パラメータ無しオーバーロードとか必要になるのか。
Avatar
↓みたいなややこしさもあるし、デフォルトパラメータとオーバーロードの一元化をしてほしい気持ちになります。 @swift-5.0.3 func foo() -> Int { return 42 } func foo(_ x: Int = -1) -> Int { return x } print(foo())
Avatar
42
Avatar
デフォルトパラメーターはあくまでコールサイトでの展開なんですよねー
Avatar
せめてデフォルトパラメータとオーバーロードのコールサイトでの見た目が異なればいいんですけどねー。
2:46 AM
デフォルト引数を明示化する構文とかだといいのかな。
2:47 AM
↑の二つの foo に対して↓とか。 foo() foo(_)
2:48 AM
Obj-C のライブラリでもよく明示的に nil を渡してたりしたし、明示的に省略するのは良さそうな気が。
Avatar
public enum RGB: CaseIterable { case r, g, b } public let count = 100_000_000 @inlinable public func testB() -> Int { var result = 0 for _ in 0..<count { for c in RGB.allCases { switch c { case .r: result += 1 default: break } } } return result } このようなtestBを別モジュールから呼んだ場合RGB.allCasesで毎回Array生成しているらしくかなりコストが大きくなってしまう…… 自動実装のallCasesがinlinableじゃないってことなんでしょうけど盲点になりそう。 (edited)
12:48 AM
RGB.allCasesをforの外で呼んだ場合のtestAとの比較
12:48 AM
12:55 AM
あれ?↑間違ってたかもしれないです。 同モジュール内でも遅いので単に最適化で展開されていないのか……
Avatar
調べてみたところ別のところに問題があるようで、 public enum RGB: Int, CaseIterable { case r, g, b } public let count = 100_000_000 public func testNormal() -> Int { var result = 0 for _ in 0..<count { for c in RGB.allCases { result += c.rawValue } } return result } @inlinable public func testInlinable() -> Int { var result = 0 for _ in 0..<count { for c in RGB.allCases { result += c.rawValue } } return result } inlinableなはずのtestInlinableのほうがArray生成されてtestNormalより遅くなるという結果に。
Avatar
omochimetaru 5/13/2019 1:10 AM
normalの方はallCasesがインライン化されてるの?
1:11 AM
速度差だけからは、それは自明ではないと思うけど。
Avatar
time profilerで見るかぎりではtestInlinableのほうだけRGB.allCases.getterでallocateUninitializedBuffer云々出てます。
Avatar
omochimetaru 5/13/2019 1:12 AM
なるほど
Avatar
これモジュールまたがなくて同一モジュール内でもinlinableついてるかどうかで変わってる気が……
Avatar
omochimetaru 5/13/2019 1:13 AM
インライン化するかどうかは自明ではないからね
1:13 AM
inlineableはインライン化可能であることを示すだけで
1:13 AM
そもそもインライン化は速度低下することもあるから
Avatar
単一モジュール内でもinlinableって影響あるんですかね?
Avatar
omochimetaru 5/13/2019 1:14 AM
同一モジュールの場合はついててもついてなくても
1:14 AM
インライン化されたりされなかったりする という認識です
1:15 AM
そのアトリビュートはコードを公開するって意味で、
1:15 AM
同一モジュール内からコードはそもそも見えてるから変化無い
Avatar
ですよね
Avatar
omochimetaru 5/13/2019 1:17 AM
自動生成されるallCasesにinlinableがついててもいいんじゃないかな
Avatar
常に一定のはずですしそうですよね。 bugsのほう経由で出してみます。
Avatar
omochimetaru 5/13/2019 1:20 AM
常に一定というか、議論としては
1:20 AM
enumのcase定義が
1:20 AM
frozenかどうかと同じになると思う
1:20 AM
frozenなenumならcaseが固定なのでオーケー
Avatar
むしろfrozenでない場合を考えて、常に大丈夫な現状の形になってるってこともあるかもですね。
Avatar
omochimetaru 5/13/2019 1:30 AM
とりあえず保守的に作って、深く検討されてないというのはありそう
1:30 AM
パフォーマンス上ボトルネックになる使い方がそうそう思いつかんし。
Avatar
omochimetaru 5/13/2019 6:55 AM
On reflection, I have to say that I like this solution best. It is very similar in flavor to maybeNilObject?.someMethod() I might even argue that it should only be used for Void return types, just like that method call becomes essentially void if the object is nil. Kurt...
6:55 AM
doIt { [guard weak self] in //... code }
6:55 AM
↑この記法のアイデア初めて見たけどかなり良くない?
Avatar
おお!??めっちゃいい
10:07 AM
んですが、返り値Voidのみ動きそう (edited)
Avatar
だいたいVoidだしVoidじゃないときは普通に書けばいいんじゃないか
Avatar
mapとかあるんすよ
Avatar
mapでselfがnilのとき、結果はどうすればいいの?
Avatar
二進も三進もいかないときに発生しがち
10:08 AM
返り値Optionalです
10:08 AM
最後に束ねて捨てる
Avatar
nilでいいってこと?
Avatar
それはそう
10:09 AM
だからー返り値Optionalなら使えるみたいな
Avatar
それならこの記法でもサポートできるね
Avatar
特別扱いが結構入ってきて辛そうだなと思った
Avatar
omochimetaru 5/17/2019 4:09 PM
The core team discussed staticallyCall and other variants that incorporated the word "static". The problem is that this can exist as protocol requirements and on classes, which are dynamically dispatched (through existentials and subclasses). We'd prefer to avoid the oppor...
4:10 PM
プロポーザル通ったあとに不満言って「もう決まったことだよ」って流れよくあるけど、callFunctionのスレは不満多め
Avatar
omochimetaru 5/24/2019 1:15 AM
The Core Team discussed this and has decided to further revise the proposal to name the operator function func callAsFunction(). We are comfortable with enabling this functionality purely based on nothing more than the name of a function, and we are not persuaded that init and subscript (which both have substantially different semantic and syntactic rules and are not simply functions) provide important precedents here requiring a new declaration introducer.
Thank you all for the discussion. John McCall Bikeshed Manager
1:15 AM
callAsFunction に決まったみたい
Avatar
omochimetaru 5/24/2019 1:25 AM
Bikeshed Managerちょっと皮肉っぽく聞こえるw
😅 1
Avatar
allSatisfy 加えるなら someSatisfy 的なのもほしくないですか? and と or 的に。 https://github.com/apple/swift-evolution/blob/master/proposals/0207-containsOnly.md
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 5/30/2019 5:51 AM
containsでは対がわかりにくいってことですか?
Avatar
ああそうか。 contains か。
Avatar
omochimetaru 5/30/2019 5:51 AM
はい。
5:51 AM
そもそもSE0207はcontainsOnlyのプロポーザルでした
Avatar
Bool コレクションに対する andor ベースで考えてたから
Avatar
Alternatives consideredあたりに書かれてますね。
Avatar
omochimetaru 5/30/2019 5:52 AM
containsとcontainsOnlyで対でわかりやすいぜって意見もあったけどallSatisfyになった。
Avatar
なるほど。
5:52 AM
あとは、 Sequence where Element == Bool に対する API がほしいかも。
Avatar
// x.allFalse() x.allSatisfy(!) !x.contains(true) たしかに現状使えるのだと前者のほうが短いのでこう書きたくなる(ならない)
Avatar
omochimetaru 5/30/2019 6:04 AM
むむっ
6:05 AM
array.allSatisfy(\.self)
6:05 AM
これの出番か?
6:05 AM
@swift-main [true, true, true].allSatisfy(\.self)
Avatar
swiftNightly BOT 5/30/2019 6:05 AM
exit status: 1 with stderr:<stdin>:1:31: error: cannot convert value of type 'WritableKeyPath<_, _>' to expected argument type '(Bool) throws -> Bool' [true, true, true].allSatisfy(\.self) ^~~~~~
Avatar
omochimetaru 5/30/2019 6:05 AM
未実装か
Avatar
x.allSatisfy(Bool.init(_:)) いまつかえるのだとこれですね。
6:08 AM
グローバルに恒等関数があったら便利かもしれない
Avatar
omochimetaru 5/30/2019 6:08 AM
\.selfがほぼidだよ
Avatar
そうですね。Swiftの場合はこの道が正しそう。 (edited)
Avatar
omochimetaru 5/30/2019 6:09 AM
一応関数型への暗黙変換であってそれ自体はKeyPath型だから
6:10 AM
KeyPathと関数の両方でオーバーロードされたりすると、ちゃんとしたidとは振る舞い変わっちゃうど。 (edited)
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 5/30/2019 6:13 AM
うん。
Avatar
x.allSatisfy(!) ww
6:40 AM
and とか or が使いやすそう。 [true, true, false].and() [true, true, false].or()
Avatar
omochimetaru 5/30/2019 6:41 AM
.all.any (edited)
Avatar
allSatisfy との対では all がわかりやすい
Avatar
問題は今のSwiftのサジェスト機能がバグってて、extension Sequence where Element == Bool で実装したメソッドは全ての Sequence のサジェストに出てきちゃうんですよね…w (edited)
8:36 AM
ワークアラウンドとして protocol LogicalOperatable 作って static func &&static func || 宣言して、extension Bool: LogicalOperatable 適合して extension Sequence where Element: LogicalOperatableand()or() もしくは all()any() 作れば問題ない
Avatar
omochimetaru 5/30/2019 8:37 AM
["a"].だとjoinedの候補でるけど、[1].だと出てこないから、
8:37 AM
extension Array where Self.Element == String はうまく動いてそう
8:38 AM
あれ? joined ってSequenceに生えてるわけじゃないのか?
Avatar
サジェストで思い出しましたが、 Apple の Swift のドキュメントに出てくる
Available when Element conforms to Sequence.
とかって前から出てましたっけ?最近出てくるようになったような気がしてるんですが・・・。↓の joined() とか。 https://developer.apple.com/documentation/swift/array
Avatar
あれ?それSequenceでバグってましたか?Arrayにextension生やすと全部に生えるのは把握してましたが
9:18 AM
Optionalだとバグるので対策にprotocol作った記憶がある
9:25 AM
記憶が混濁してそう
Avatar
あ、今試してみたらSequenceなら大丈夫でした、Arrayはだめですね
👍 1
5:16 AM
5:16 AM
Avatar
omochimetaru 5/31/2019 5:17 AM
joinedはArray<String>に対して書かれているのでますます謎だ
Avatar
その辺のrequirement付きで適用できない候補がコード補完に出てきてしまう問題は次のバージョンで治ってるはずです。
Avatar
omochimetaru 5/31/2019 5:23 AM
Avatar
We used to return decls from extension with non-matching same type requirements. e.g. struct S&lt;T&gt; { } extension S where T == String { func foo() {} } S&lt;Int&gt;().#HERE# /...
🎉 2
Avatar
norio_nomura 6/4/2019 1:45 AM
Function Builder、draftに書かれたHTMLBuilderをXcode 11 betaで動かそうとしてるけど、いまいちうまくいかないな。 https://forums.swift.org/t/pitch-function-builders/25167
It's always been a goal of Swift to support declarative programming, and the language can be quite good for it, but some kinds of "declaration" fit better into the current language than others. In particular, heterogeneous trees with a lot of hard-coded structure — such as...
Avatar
omochimetaru 6/4/2019 5:01 AM
関数の型に対してアノテーションつけといて、記法がすり替わるのか
5:03 AM
あ、型じゃなくてラベルについてるのか
Avatar
norio_nomura 6/4/2019 5:46 AM
今の実装はvariadic parameterなbuildBlockをサポートしてるのかな?
Avatar
omochimetaru 6/4/2019 5:47 AM
ViewBuilderのリファレンス見ると引数10個?までオーバーロードされてるから、variadicじゃ無さそうに見えます
5:49 AM
That’s needed only because (1) SwiftUI wants to propagate sub-view types into the return type to enable some optimizations and (2) Swift doesn’t have variadic generics yet. It’s not a long-term problem, and most other libraries can just use variadic arguments.
Avatar
norio_nomura 6/4/2019 6:11 AM
ぬぬ。あとdraftで使われてるbuildExpressionとかも無さげ。
6:14 AM
@_functionBuilderViewBuilderに最低限必要な機能だけ実装されてるぽい。
Avatar
omochimetaru 6/4/2019 6:15 AM
なるほど
Avatar
norio_nomura 6/5/2019 1:17 AM
動作するサンプルが載ってた。 https://github.com/apple/swift-evolution/pull/1047
This is an example of how to use the function builder feature to make a DSL for HTML in Swift. It builds off of the example in the function builders proposal here: #1046 This should not be merged, ...
Avatar
このサンプルコードはコンパイル通らない https://developer.apple.com/documentation/swiftui/staticmember
9:16 AM
これ見た限りだとStaticMember<Base>のBaseがcolorStyleのシグネチャに使われてないのに推論されてて、型推論が強化されたのかと思ったけど、実際は func colorStyle<S : ColorStyle>(_ style: S.Member) -> Self.Modified<ColorStyleModifier<S>> みたいな感じでラップされて伝播してた (edited)
9:18 AM
このテクは今までも使えたけど型パラがどんどん膨れ上がっていくので辛いことになってたけど、ORTのおかげで使いやすくなった。
Avatar
omochimetaru 6/5/2019 9:19 AM
これどうなってんだ?
Avatar
ORTあるとかなり型消去考えずに済むの良いですね
Avatar
omochimetaru 6/5/2019 9:20 AM
RedStyleは struct RedStyle : ColorStyle
Avatar
そうです
Avatar
omochimetaru 6/5/2019 9:21 AM
てことは、 RedStyle.Member.blue とかも生えてる?
Avatar
いや、それが生えてる必要はないはずです
Avatar
omochimetaru 6/5/2019 9:22 AM
必要は無いけど、 extension StaticMember where Base : ColorStyle これのせいで生えてそう
9:23 AM
で、そうすると、 MyView().colorStyle(.red) ↑これはなんで解決できるんだ? func colorStyleSは何が推論されてるの?
Avatar
SwiftUIの型見た感じだとStaticMemberのconstionalなメンバとして生えてるだけですね
9:24 AM
あれ、たしかに。
Avatar
omochimetaru 6/5/2019 9:24 AM
型パラがどんどん膨れ上がっていく
このパターンのジェネリクスに名前がほしいのでとりあえず「雪だるまジェネリクス」と呼んでみたい
Avatar
あ、いや
Avatar
マトリョシカって呼んでたw
Avatar
omochimetaru 6/5/2019 9:25 AM
constional
この言葉はじめてみた
Avatar
redの型がStaticMember<RedColor>だからBaseが推論できてるはず
9:26 AM
タイポ…
Avatar
omochimetaru 6/5/2019 9:27 AM
conditionalか
Avatar
ですです
Avatar
omochimetaru 6/5/2019 9:27 AM
んん〜?
Avatar
StaticMember.redはStaticMember<Red>になるじゃないですか?
Avatar
omochimetaru 6/5/2019 9:29 AM
StaticMember.red はおかしくない?
9:29 AM
StaticMember<Base>.redBase を何かで埋めないと。
9:30 AM
あ、見てる場所が違うのか。 俺が気にしてるのは .colorStyle(.red) の推論ね。
9:30 AM
{ return .init(.init()) } の方じゃない。
9:31 AM
@swift-5.1.5 struct StaticMember<Base> { init(_ base: Base) {} } protocol ColorStyle { typealias Member = StaticMember<Self> } struct RedStyle : ColorStyle {} struct BlueStyle : ColorStyle {} extension StaticMember where Base : ColorStyle { static var red: RedStyle.Member { return .init(.init()) } static var blue: BlueStyle.Member { return .init(.init()) } } protocol View {} extension View { func colorStyle<S : ColorStyle>(_ style: S.Member) { } } struct MyView : View {} MyView().colorStyle(.red) MyView().colorStyle(.blue)
Avatar
swift51 BOT 6/5/2019 9:31 AM
no output
Avatar
omochimetaru 6/5/2019 9:34 AM
<S> StaticMember<S>.red って許されてるのか
Avatar
Baseが埋まってるからいけるんじゃないかなと思った
Avatar
omochimetaru 6/5/2019 9:36 AM
@swift-5.1.5 struct StaticMember<Base> { init(_ base: Base) {} } protocol ColorStyle { typealias Member = StaticMember<Self> } struct RedStyle : ColorStyle {} struct BlueStyle : ColorStyle {} extension StaticMember where Base : ColorStyle { static var red: RedStyle.Member { return .init(.init()) } static var blue: BlueStyle.Member { return .init(.init()) } } protocol View {} extension View { func colorStyle<S : ColorStyle>(_ style: S.Member) { } } struct MyView : View {} MyView().colorStyle(RedStyle.Member.red) MyView().colorStyle(BlueStyle.Member.red) (edited)
Avatar
swift51 BOT 6/5/2019 9:37 AM
no output
Avatar
@swift-5.1.5 @swift-4.1.3 struct Static<Base> {} extension Static { static var foo: Static<Int> { return .init() } } func useMember<T>(member: Static<T>) {} useMember(member: .foo) (edited)
Avatar
swift51 BOT 6/5/2019 9:37 AM
no output (edited)
Avatar
omochimetaru 6/5/2019 9:37 AM
MyView().colorStyle(RedStyle.Member.red) MyView().colorStyle(BlueStyle.Member.red) ↑これのどっちも通るわけですよ
9:37 AM
RedStyle.MemberStaticMember<RedStyle>BlueStyle.MemberStaticMember<BlueStyle> だから
9:37 AM
Baseがなんなのか確定しない
Avatar
swift41 BOT 6/5/2019 9:38 AM
no output
Avatar
omochimetaru 6/5/2019 9:40 AM
だから、Baseは不確定だけど Base = <S> S where S : ColorStyle な状態を解決としてるように思える (edited)
9:40 AM
MyView().colorStyle(RedStyle.Member.red) MyView().colorStyle(BlueStyle.Member.red) MyView().colorStyle(.red) // これは↑のどちらでもない
Avatar
まあambiguousになるパターンはありますね
Avatar
omochimetaru 6/5/2019 9:42 AM
ドット記法はただの推論じゃなくて、「書き下せないパターン」に落ちてる場合があるって事じゃないか
9:43 AM
むむ
9:43 AM
@swift-5.1.5 struct StaticMember<Base> { init(_ base: Base) {} } protocol ColorStyle { typealias Member = StaticMember<Self> } struct RedStyle : ColorStyle {} struct BlueStyle : ColorStyle {} extension StaticMember where Base : ColorStyle { static var red: RedStyle.Member { print(self) return .init(.init()) } } protocol View {} extension View { func colorStyle<S : ColorStyle>(_ style: S.Member) {} } struct MyView : View {} MyView().colorStyle(.red) MyView().colorStyle(RedStyle.Member.red) MyView().colorStyle(BlueStyle.Member.red)
Avatar
swift51 BOT 6/5/2019 9:43 AM
StaticMember<RedStyle> StaticMember<RedStyle> StaticMember<BlueStyle>
Avatar
omochimetaru 6/5/2019 9:44 AM
.redStaticMember<RedStyle>.red らしい。
Avatar
あー、わかった
Avatar
omochimetaru 6/5/2019 9:45 AM
あ〜、.staticProp は その返り値の型と受ける型が同一って制約があるのか?
Avatar
ですね
Avatar
omochimetaru 6/5/2019 9:47 AM
.redに対してStaticMember<S: ColorStyle> の状態で static var red をconditionalに見つけて、redの返り値が StaticMember<RedStyle> だから、.redStaticMember<RedStyle>.red の扱いになるのか
9:49 AM
@swift-5.1.5 struct StaticMember<Base> { init(_ base: Base) {} } protocol ColorStyle { typealias Member = StaticMember<Self> } struct RedStyle : ColorStyle {} struct BlueStyle : ColorStyle {} extension StaticMember where Base : ColorStyle { static var red: RedStyle.Member { print(self) return .init(.init()) } } protocol View {} extension View { func colorStyle<S : ColorStyle>(_ style: S.Member) {} func anyStyle<S>(_ style: StaticMember<S>) {} } struct MyView : View {} MyView().colorStyle(.red) MyView().anyStyle(.red)
Avatar
swift51 BOT 6/5/2019 9:49 AM
StaticMember<RedStyle> StaticMember<RedStyle>
Avatar
omochimetaru 6/5/2019 9:49 AM
conditionalでない時点で発見して試みるのか。
9:50 AM
@swift-5.1.5 struct StaticMember<Base> { init(_ base: Base) {} } protocol ColorStyle { typealias Member = StaticMember<Self> } protocol FontStyle { typealias Member = StaticMember<Self> } struct RedStyle : ColorStyle {} struct BlueStyle : ColorStyle {} struct RedFontStyle : FontStyle {} extension StaticMember where Base : ColorStyle { static var red: RedStyle.Member { print(self) return .init(.init()) } } extension StaticMember where Base : FontStyle { static var red: RedFontStyle.Member { print(self) return .init(.init()) } } protocol View {} extension View { func colorStyle<S : ColorStyle>(_ style: S.Member) {} func fontStyle<S: FontStyle>(_ style: S.Member) {} func anyStyle<S>(_ style: StaticMember<S>) {} } struct MyView : View {} MyView().colorStyle(.red) MyView().fontStyle(.red) MyView().anyStyle(.red)
Avatar
swift51 BOT 6/5/2019 9:50 AM
exit status: 1 with stderr:<stdin>:41:20: error: ambiguous use of 'red' MyView().anyStyle(.red) ^ <stdin>:16:16: note: found this candidate static var red: RedStyle.Member { ^ <stdin>:23:16: note: found this candidate static var red: RedFontStyle.Member { ^
Avatar
omochimetaru 6/5/2019 9:51 AM
同じものをもう一組用意すると、曖昧な場合はちゃんとエラーだ
9:58 AM
あ、このStaticMemberって
9:58 AM
これをやるためのヘルパージェネリクスなのかw
9:59 AM
え、じゃあこれ自体に StaticMember<S> で引数を受けてる意味はなくて
9:59 AM
中ではすぐに style.base<S> を取り出すだけ?
Avatar
そのはず
Avatar
omochimetaru 6/5/2019 10:01 AM
func background<Background>(Background, alignment: Alignment) -> Self.Modified<_BackgroundModifier<Background>> func background<S>(S.Member) -> Self.Modified<_BackgroundModifier<Rectangle.Filled<S>>> func background<S>(S.Member, cornerRadius: Length) -> Self.Modified<_BackgroundModifier<RoundedRectangle.Filled<S>>> func background<S>(S, cornerRadius: Length) -> Self.Modified<_BackgroundModifier<RoundedRectangle.Filled<S>>>
10:01 AM
そういうことか
10:02 AM
func background<S>(_ content: S.Member, cornerRadius: Length) -> Self.Modified<_BackgroundModifier<RoundedRectangle.Filled<S>>> where S : ShapeStyle func background<S>(_ content: S, cornerRadius: Length) -> Self.Modified<_BackgroundModifier<RoundedRectangle.Filled<S>>> where S : ShapeStyle (edited)
10:04 AM
↑この2つは ただドット記法させるためだけのオーバーロードと、本質的なインターフェースだ
10:06 AM
これはSwiftならではのデザインパターンだなあ
Avatar
どっちも用意してあるのか
Avatar
omochimetaru 6/5/2019 10:11 AM
そうじゃないと、普通に ShapeStyle の値をもってるときに
10:11 AM
無意味に StaticMember(style) って書かないといけなくなる
Avatar
ambiguousになるパターンもこれがないと詰みそう
10:14 AM
いや、大丈夫か
Avatar
omochimetaru 6/5/2019 10:19 AM
StaticMember<StaticMember<ColorStyle>> とかやると曖昧になるかもしれんけど
10:19 AM
目的外利用だね
Avatar
omochimetaru 6/21/2019 9:09 AM
protocol CopyInitializable {} extension CopyInitializable { init(copy: Self) { self = copy } } class Animal : CopyInitializable { init() {} convenience init(a: Int) { let copy = Animal() // `Self`にforce castしたいがここに`Self`が書けないので // self.init(copy: copy as! Self) // type(of: self)でSelf型を作って、 // それをジェネリクスに渡すことで`as!`を実行できる self.init(copy: forceCast(copy, to: type(of: self))) } } func forceCast<X, T>(_ x: X, to type: T.Type) -> T { return x as! T }
9:09 AM
↑トリッキー
Avatar
🤔 @swift-5.0.3 import Foundation let gregorian = Calendar(identifier: .gregorian) let utc = TimeZone(identifier: "UTC")! let components = gregorian.dateComponents(in: utc, from: Date()) func date(from components: DateComponents, with nanosecond: Int) -> Date { var components = components components.nanosecond = nanosecond return components.date! } print(date(from: components, with: 999499976).description) print(date(from: components, with: 999499977).description)
Avatar
2019-06-25 10:39:38 +0000 2019-06-25 10:39:39 +0000
Avatar
精度限界関係かしら
Avatar
なるほど。 @swift-5.0.3 import Foundation let iso8601WithFractionalSecondFormatter: DateFormatter = { let formatter = DateFormatter() formatter.locale = Locale(identifier: "en_US_POSIX") formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSSSS" formatter.timeZone = TimeZone(secondsFromGMT: 0) return formatter }() let gregorian = Calendar(identifier: .gregorian) let utc = TimeZone(identifier: "UTC")! let components = gregorian.dateComponents(in: utc, from: Date()) func date(from components: DateComponents, with nanosecond: Int) -> Date { var components = components components.nanosecond = nanosecond return components.date! } let date1 = date(from: components, with: 999499976) print(iso8601WithFractionalSecondFormatter.string(from: date1)) print(gregorian.dateComponents(in: utc, from: date1).nanosecond!) let date2 = date(from: components, with: 999499977) print(iso8601WithFractionalSecondFormatter.string(from: date2)) print(gregorian.dateComponents(in: utc, from: date2).nanosecond!)
Avatar
2019-06-25T11:26:43.999000 999499917 2019-06-25T11:26:44.000000 999500036
Avatar
Macでは結果が違ったりするのかな
Avatar
同じです。
Avatar
ほ~
Avatar
YamsのYAMLEncoderで、10000回に5回くらいしか起きないバグの原因になってる。 (edited)
Avatar
norio_nomura 6/26/2019 7:26 AM
昨日のDateFormatter、ドキュメントによるとdateFormat文字列には Unicode Technical Standard #35 を使うと書かれてるけど、S Fractional Secondの扱いが Unicode Technical Standard #35 と違ってるんだ。 https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW13 (edited)
Explains how to use Cocoa formatters to create and validate text in text fields and other cells.
7:27 AM
Unicode Technical Standard #35 によると Fractional Second - truncates (like other time fields) to the count of letters. となってるけど、実際の挙動はtruncateではなくroundになってる。 http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns (edited)
Avatar
omochimetaru 6/26/2019 7:32 AM
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
7:33 AM
public struct Date : ReferenceConvertible, Comparable, Equatable { fileprivate var _time: TimeInterval }
7:35 AM
Doubleの精度はおよそ15桁だから、 1970から50年で 1,576,800,000秒で10桁使うから
7:36 AM
ミリ秒3桁までは13桁でいけそうだけど
7:36 AM
マイクロ秒6桁になるとギリギリアウトぐらいか
Avatar
norio_nomura 6/26/2019 7:38 AM
なるほど。確かに手元の検証は6~7桁でおかしくなる。
Avatar
omochimetaru 6/26/2019 7:39 AM
原点が1970年か2000年かちょっとわからんけど、原点周辺なら精度が出そう。
Avatar
norio_nomura 6/26/2019 7:40 AM
あ、TimeIntervalReferenceDateは2001年1月1日0:00だ。 @swift-5.0.3 import Foundation print(Date(timeIntervalSinceReferenceDate: 0)) print(Date().timeIntervalSinceReferenceDate) (edited)
Avatar
2001-01-01 00:00:00 +0000 583227738.026557 (edited)
Avatar
omochimetaru 6/26/2019 7:47 AM
@swift-5.1.5 import Foundation let iso8601WithFractionalSecondFormatter: DateFormatter = { let formatter = DateFormatter() formatter.locale = Locale(identifier: "en_US_POSIX") formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSSSS" formatter.timeZone = TimeZone(secondsFromGMT: 0) return formatter }() var d = Date(timeIntervalSinceReferenceDate: 0) for _ in 0..<10 { print(iso8601WithFractionalSecondFormatter.string(from: d)) d += 0.0001 }
Avatar
2001-01-01T00:00:00.000000 2001-01-01T00:00:00.000000 2001-01-01T00:00:00.000000 2001-01-01T00:00:00.000000 2001-01-01T00:00:00.000000 2001-01-01T00:00:00.001000 2001-01-01T00:00:00.001000 2001-01-01T00:00:00.001000 2001-01-01T00:00:00.001000 2001-01-01T00:00:00.001000
Avatar
norio_nomura 6/26/2019 7:50 AM
そう、今は3桁で四捨五入した結果しか返してくれない。
Avatar
omochimetaru 6/26/2019 7:50 AM
Formatterのほうはそうなんですね。
7:50 AM
@swift-5.1.5 import Foundation let iso8601WithFractionalSecondFormatter: DateFormatter = { let formatter = DateFormatter() formatter.locale = Locale(identifier: "en_US_POSIX") formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSSSS" formatter.timeZone = TimeZone(secondsFromGMT: 0) return formatter }() let gregorian = Calendar(identifier: .gregorian) let utc = TimeZone(identifier: "UTC")! let components = gregorian.dateComponents(in: utc, from: Date()) var d = Date(timeIntervalSinceReferenceDate: 0) // 2001年 for _ in 0..<10 { print(gregorian.dateComponents(in: utc, from: d).nanosecond!) d += 0.000001 } d = Date(timeIntervalSinceReferenceDate: 86400 * 365 * 20) // 2021年 for _ in 0..<10 { print(gregorian.dateComponents(in: utc, from: d).nanosecond!) d += 0.000001 }
Avatar
0 1000 2000 3000 4000 5000 5999 6999 8000 9000 0 953 1907 2861 3814 4768 5722 6675 7629 8583
Avatar
omochimetaru 6/26/2019 7:50 AM
↑原点から遠ざかるほどガバガバになる
😞 1
Avatar
norio_nomura 6/26/2019 7:53 AM
JSONEncoderは標準機能だと、任意のDateのインスタンスを元の値を維持したままDateFormatter使ってエンコード/デコード出来ないから、Date()のround tripテストだけ特別なことしてる。 https://github.com/apple/swift/blob/master/test/stdlib/TestJSONEncoder.swift#L255-L257 (edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 6/26/2019 7:54 AM
ひえ〜
7:54 AM
この辺信用ならんから、API設計ではJSON文字列で扱うようにして、パーサも自作してる。
Avatar
norio_nomura 6/26/2019 7:55 AM
あ、DateFormatter使ったエンコード/デコードだ。
7:56 AM
標準は Doubleにするから大丈夫だったはず。 (edited)
7:56 AM
あいや、これDoubleだ。
7:58 AM
あ、JSONSerializationDoubleの精度を落としちゃうからダメって書かれてる…
8:00 AM
🤔 あれ?公式のリポジトリ内では、JSONEncoderは任意のDateインスタンスのエンコード/デコードを標準の手法でテストされてない?
8:04 AM
ISO8601DateFormatterも精度が足りないし。
Avatar
norio_nomura 6/30/2019 5:08 AM
DateFormatterがsub-millisecondで四捨五入する挙動はドキュメントと一致していない、というissueを登録した。 https://bugs.swift.org/browse/SR-11049
Avatar
omochimetaru 7/1/2019 1:21 AM
えらい
Avatar
omochimetaru 7/4/2019 12:50 AM
Hey all, As per the GSoC announcement, @jansvoboda11 is working on Integration of libSyntax with the compiler pipeline with @rintaro as his mentor. I'd like to provide more details on what the project entails and what changes you should expect to see coming to the Swift repo...
12:50 AM
りんたろープロジェクトの詳細なアナウンスが出た
12:52 AM
パーサーの処理をlibSyntaxに一本化して、libSyntax->旧libASTに変換する、パイプラインに書き換えると。
😀 1
12:59 AM
そこまではできそうだけど、その後のステージでASTの型掴んでるところを段階的移行するのが難しそうなんだよなあ
2:02 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
2:02 AM
レビューの決着ちゃんとアナウンスされてないけど、とりあえずフォーマッターの実装がappleのリポジトリに爆誕した
2:03 AM
25000行のコミットウケる
Avatar
ついに! Descriptionもないw
Avatar
omochimetaru 7/11/2019 4:37 AM
固定って何のことですか?
Avatar
norio_nomura 7/11/2019 4:38 AM
Package.swiftdependencies.package(url: "https://github.com/apple/swift-syntax", .revision("swift-DEVELOPMENT-SNAPSHOT-2019-07-10-m")), に書き換えてswift-5.1-DEVELOPMENT-SNAPSHOT-2019-07-09-aを使うと動いた。 (edited)
Avatar
omochimetaru 7/11/2019 4:39 AM
.package(url: "https://github.com/apple/swift-syntax", .revision("xcode11-beta1")),
4:39 AM
これか
4:40 AM
そっか、SwiftPMで実行ターゲットとしてビルドできるんですね
Avatar
norio_nomura 7/11/2019 4:41 AM
TOOLCHAIN (SwiftSyntax)のバージョンを合わせないと、 Unable to format ../../SwiftLint/Package.swift: SwiftSyntax parser library isn't compatible とか言われて動かない。
Avatar
omochimetaru 7/11/2019 4:42 AM
SwiftSyntaxのバージョン合わせややこしいですね
4:42 AM
SwiftSyntax自体がコンパイラバイナリに依存してるからしょうがないのか
4:43 AM
でもSwiftPMの思想的にはそれは良くない状態に感じる
Avatar
norio_nomura 7/11/2019 4:46 AM
ここでlibSyntaxが使う型情報のハッシュを計算しておいて、実行時にこれを照合して互換性があるライブラリかチェックしてるぽい。 https://github.com/apple/swift/blob/master/utils/gyb_syntax_support/__init__.py#L164-L170 (edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 7/11/2019 4:47 AM
バージョン番号とかじゃなくて定義そのものなのか。
Avatar
norio_nomura 7/11/2019 4:48 AM
gybに食わせるPythonで記述された型情報ぽい。
4:51 AM
SwiftSyntaxに依存すると、TOOLCHAINにバンドルしないとほぼ成り立たないツールになってしまう様に見える。 (edited)
Avatar
omochimetaru 7/11/2019 5:20 AM
SwiftSyntaxがそうだから、連鎖的にそうなっちゃいますよねえ
Avatar
omochimetaru 7/23/2019 4:14 AM
The review of SE-0262: Demangle Function begins now and runs through July 29, 2019. The proposal is written by @Alejandro. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep y...
4:14 AM
demangle関数のstdlib入りレビュー (edited)
4:18 AM
人間読む用の文字列にデマングルするだけじゃなくて、定義のツリー構造が取り出せる的な指摘がされてるな、そのとおりだ
Avatar
@swift-5.0.3 struct Foo { var value: Int func a() -> Int { return value } mutating func b() -> Int { value += 1; return value } } print(type(of: Foo.a))
Avatar
(Foo) -> () -> Int
Avatar
@swift-5.0.3 struct Foo { var value: Int func a() -> Int { return value } mutating func b() -> Int { value += 1; return value } } print(type(of: Foo.b))
Avatar
exit status: 1 with stderr:<stdin>:7:20: error: partial application of 'mutating' method is not allowed print(type(of: Foo.b)) ^
Avatar
↑これって (inout Foo) -> () -> Int じゃダメですか?
3:45 PM
ダメか
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
4:23 PM
3 年前に Accept されたまま実装されてないのか。 https://bugs.swift.org/browse/SR-1051
Avatar
omochimetaru 7/30/2019 1:20 AM
そういえばこれのAccept見たな
1:21 AM
selfについてカリー化しないで第ゼロ引数に押し込めば、mutatingのinoutも問題ないのか。
1:21 AM
まあ、メソッド呼び出しのときがそうだからそれはそうか。
Avatar
Accept されたのに長期間放置もあるんだね。
Avatar
omochimetaru 7/30/2019 8:13 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
8:13 AM
↑これも、最近入ったけどAcceptはずっと前だったと思う
Avatar
昔は実装なしで提案できたからってのもあるのかな。
Avatar
omochimetaru 7/30/2019 8:14 AM
昔はというか今もそれはそうだと思ってました
Avatar
norio_nomura 7/30/2019 8:18 AM
正式な提案には実装が必要になったのでは。
Avatar
omochimetaru 7/30/2019 8:25 AM
Develop the proposal: expand the rough sketch into a complete proposal, using the proposal template, and continue to refine the proposal on the forums. Prototyping an implementation and its uses along with the proposal is required because it helps ensure both technical feasibility of the proposal as well as validating that the proposal solves the problems it is meant to solve.
8:26 AM
ほんとだ。Prototyping is required だ。
8:28 AM
2017-09に is encouraged から is *required* に変わってたのか。
Avatar
class existential container https://github.com/apple/swift/blob/master/docs/ABI/TypeLayout.rst#class-existential-containers が witness table へのポインタを保持しないといけない理由って何でしょう?クラスの場合、オブジェクトが vtable を参照しているのでそちらから必要なメソッドを引けないですか?複数プロトコルに適合しているときの扱いをシンプルにするため?
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 8/1/2019 9:54 AM
引けるか引けないかでいうと引けるはずですね 実行時のconditional conformanceがあるぐらいなので
9:55 AM
事前に紐付けられたテーブルと実行時に探索した結果が異なる場合がありえるかどうかは思いつかないですが
9:55 AM
少なくともパフォーマンス上かなりロスがありそう
9:57 AM
ただ昔のSwiftはランタイムリフレクションが今ほど無かったんで昔は引けなかった気も?
10:00 AM
あ、あとメソッドを引くというかテーブルを引くだと思います
Avatar
norio_nomura 8/2/2019 1:41 AM
クラスのメタデータには、そのクラスのプロトコルwitness tableって含まれていないのでは。
Avatar
omochimetaru 8/2/2019 1:47 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
1:48 AM
↑このランタイム関数で、(クラスに限らず)メタタイプとProtocolからWitnessTableを引っ張れます
1:49 AM
実装詳細は追ってないけど、メタデータとしてそれが入ってないとできないと思う。
Avatar
norio_nomura 8/2/2019 1:52 AM
生成されたアセンブラを読むと、メタデータ内の情報は使わず、そのクラスのwitness tableを返すシンボルが存在する前提でそれを呼び出すコードが生成されているのですよね。 (edited)
Avatar
norio_nomura 8/2/2019 2:06 AM
swiftc -emit-assembly ClassExistencial.swift|swift demangle>ClassExistencial.asm - ClassExistencial.asm
2:13 AM
上記gistで、class C1のメタデータはこの辺り。witness tableに関する情報は含まれてないように見える。 https://gist.github.com/norio-nomura/5cf4615b4334eeb7d4b5081aeb7e1536#file-classexistencial-asm-L579-L600
2:16 AM
witness tableを取り出すところはここ。直接シンボルを参照してる。 https://gist.github.com/norio-nomura/5cf4615b4334eeb7d4b5081aeb7e1536#file-classexistencial-asm-L25 (edited)
Avatar
omochimetaru 8/2/2019 2:18 AM
静的にわかるケースだとそうなると思います ランタイム関数のconformsToProtocolが使われるケースがわかったら共有します
Avatar
norio_nomura 8/2/2019 2:21 AM
そうか、動的チェックのコードを見ないといけないのか。
Avatar
実装上こうなってるからできないという理由とは独立して、なぜそのような設計にしたのかという話があると思います。 Java 等ではインタフェース型変数はアドレスを格納するだけで vtable からメソッドの実体を引くので、変数は( 64 ビット環境なら) 8 バイトで済みますよね? Swift の Class Existential Container だと Witness Table へのポインタを含むために↓では 16 バイトになってしまうわけですが、そのような設計にした理由は何だと考えられますか? @swift-5.0.3 protocol Animal: AnyObject { func foo() -> Int } class Cat: Animal { func foo() -> Int { return 42 } } let cat = Cat() let animal: Animal = cat print(MemoryLayout.size(ofValue: cat)) print(MemoryLayout.size(ofValue: animal))
Avatar
swift50 BOT 8/2/2019 2:25 AM
8 16
Avatar
norio_nomura 8/2/2019 2:26 AM
vtableだけではプロトコルメソッドを探せないからでは。
Avatar
それは実装上の都合ではないですか?
Avatar
omochimetaru 8/2/2019 2:27 AM
Java 等ではインタフェース型変数はアドレスを格納するだけで vtable からメソッドの実体を引くので
ここはちょっと実際と違うと思います
Avatar
norio_nomura 8/2/2019 2:28 AM
classメタデータをObjective-Cと互換にするという制約で実現できないのでは。
Avatar
@omochimetaru Java 等のインタフェース型変数は 8 バイトでアドレスを格納してるわけではないということ?
Avatar
omochimetaru 8/2/2019 2:32 AM
インターフェースが要求するメソッドを並べたインターフェーステーブルがあって、
2:32 AM
クラスのインターフェースの充足は事前に静的にわかるので
2:32 AM
そのテーブルは生成されていて
2:33 AM
インターフェースにアップキャストしたオブジェクトっていうのはそれで扱われてるはずです
2:33 AM
この辺の詳細はJVMバイトコードとは独立してJVMランタイム固有の部分みたいだけど
2:33 AM
以前IBMのスライドで見た。
2:33 AM
C++のインターフェースアップキャストも同じような構造でコンパイルされます。
2:33 AM
そうしないと、対応するメソッドの検索がO(1)にできないからです
2:34 AM
こうしておくとインターフェースとメソッド番号(index)でテーブルから一発で引ける。
2:34 AM
で、それが8バイトポインタから間接で引いてるのか、 インターフェースキャストしたthisとインターフェーステーブルのペアの16バイトなのか、 そもそもペアで扱うのかとかは知らない。
2:35 AM
そのような設計にした理由
これに関しては、こうしておいたほうが「witnessテーブルを引く」実行コストが少ないからだと思います。
2:36 AM
ある型Tがany Pコンテナに格納される部分のコードでは、witness table of T for P はコンパイル時に静的に引けるので
2:36 AM
any Pコンテナへのアップキャストのところで静的にテーブルを格納できて、 any P をopenする側ではもうそこにテーブルがあるので取り出せば呼び出せる。
Avatar
具象クラスの継承と違うのは、 interface/protocol は多重に implement/conform できるから?
Avatar
omochimetaru 8/2/2019 2:37 AM
そうですね。 親が一個だけの継承に関しては、親子のつながりでvtableを上から埋めていけば、
2:37 AM
アップキャスト用のテーブルを用意しなくても、子のテーブル is 親のテーブルのABI互換性が得られます。
2:38 AM
C++の場合そのへん賢くて、 親が1系統である限りテーブルのオフセットは発生しないけど、 親が2ついたりすると、片方の親へのアップキャスト(static_cast)は、thisのアドレスがズレたりしますよ。 (edited)
2:40 AM
Rustのtrait implも、同じような感じでthisとimpl tableのペアだよって公式文書に書いてあったと思う。
Avatar
うーん、 Java ではインタフェース型だとしても変数側でペアで持ってないと思うんだけど(これに関しては別途確認するとして)、それが正しいとすると Swift と Java は別の方式を選択してるわけで、何の違いが別の選択をさせてるんだろう?
Avatar
omochimetaru 8/2/2019 2:44 AM
変数側でペアで持ってない
インターフェース型の変数のサイズはペアの可能性はありますね
2:45 AM
何の違いが別の選択をさせてる
少なくとも、Javaではポリモーフィズムを考えるところでは全部参照型だけ考えればいいけど
(edited)
Avatar
Class Existential Container は参照型だけ考えればいいんじゃない? (edited)
Avatar
omochimetaru 8/2/2019 2:45 AM
Swiftは値型を値的性質のままで、protocolの多重継承とany protocol型へのアップキャストをやってるので
2:46 AM
ああ、あくまでClass ECの話か。
Avatar
うん、 Opaque Existential Container は別として、 Class Existential Container が Witness Table を保持するのはなぜかって疑問。
Avatar
omochimetaru 8/2/2019 2:46 AM
そのほうが速いからじゃないですかねえ
Avatar
じゃあ Java がペアで持ってないならなぜ速い方法を選ばなかったのか。まずペアで持ってないところを確認した方が良さそうだけど。
2:47 AM
なにかの言語仕様の違いがそうさせてるのか、
2:47 AM
それとも後発だからより良い方法が見つかったのか、
2:48 AM
ユースケースの違いで 16 バイトの領域を使ってもパフォーマンスをとった方が良いということなのか、
Avatar
omochimetaru 8/2/2019 2:50 AM
Swiftのほうが後発だから単純に思いつかなかったとか パフォーマンスを捨ててるとしたら、ありえそうなのは実装をシンプルにしたかったとか? thisポインタ一個のまま扱って、ランタイムリフレクションでメソッドを探すだけであれば、例えばGC実装とかでそのデータ構造の考慮はいらないですね (edited)
Avatar
2.6.1. Local Variables A single local variable can hold a value of type boolean, byte, char, short, int, float, reference, or returnAddress. A pair of local variables can hold a value of type long or double.
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-2.html#jvms-2.6.1
Avatar
omochimetaru 8/2/2019 2:51 AM
でもインターフェースアクセスのたびにメソッドの探索をしてたら重すぎるから、アップキャストテーブルとのペアはもってそうだけどなあ
Avatar
メソッド探索まではしてないんじゃない?
Avatar
omochimetaru 8/2/2019 2:51 AM
インターフェース対応テーブルリストからのテーブル検索かな。
Avatar
各インタフェース用の vtable を持ってたら、 i 番目のテーブルをとってくるところは
2:52 AM
1 ステップ余計に必要だけど、 O(1) には変わらないだろうし。
Avatar
omochimetaru 8/2/2019 2:52 AM
え、1にはできないのでは
2:53 AM
i番目がいくつかがわからないから
2:53 AM
検索が必要です
Avatar
えっと、そこを線形探索してても、 implement されたインタフェースの数はメソッドの数と比べて小さく定数とみなせると思うし、
Avatar
omochimetaru 8/2/2019 2:54 AM
メソッドの数と比べる意味がわからんです
2:55 AM
だいたいのコードで、 // A はinterface void foo(a A) { a.hoge(); a.fuga(); a.piyo(); }
Avatar
ああ、メソッドを線形探索する話をしてるわけじゃないのか。
Avatar
omochimetaru 8/2/2019 2:55 AM
↑こうなってたら、hoge,fuga,piyoの呼び出しのたびにその検索が生じる。
Avatar
あとは、効率が良いかどうかは別として、辞書的に今求めてるインタフェースに対応した vtable を O(1) で引くこともできるんじゃない?
Avatar
omochimetaru 8/2/2019 2:55 AM
hogeとかの内容によっては、メソッド本体よりテーブル検索のほうが重い。
2:56 AM
まあ辞書にはできますね。
2:56 AM
計算量という意味ではそうだけど、それも処理本体に比べたらオーバーヘッドでかすぎると思いますけど・・・
Avatar
でも実装してるインタフェースなんて大した個数なさそうだから線形探索した方が速そうな気が。実質的に 1, 2 ステップ増える程度じゃないのかな? (edited)
Avatar
omochimetaru 8/2/2019 2:58 AM
ArrayListでも すべての実装されたインタフェース: Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess このくらいですね
Avatar
Iterable > Collection > List あたりの継承関係にあるのはまとめられそう
Avatar
omochimetaru 8/2/2019 2:59 AM
僕の感覚だと6ステップぐらいはかかっちゃう気がします。
2:59 AM
Swiftはそこを理論上最速になるつくりで実装してると思う。 (edited)
Avatar
norio_nomura 8/2/2019 3:03 AM
そうか、動的チェックのコードを見ないといけないのか。
動的チェックは_swift_dynamicCastが担ってて、実装はこれ。 https://github.com/apple/swift/blob/master/stdlib/public/runtime/Casting.cpp#L2271
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 8/2/2019 3:05 AM
少なくとも case MetadataKind::Existential: return _dynamicCastToExistential(dest, src, srcType, cast<ExistentialTypeMetadata>(targetType), flags);
3:05 AM
このフローの内部で、Protocol Witness Tableの取り出しをやるはずですね。
3:05 AM
Existential Containerの中にPWTを格納しないといけないので。
Avatar
- invokevirtual invokes an instance method of an object, dispatching on the (virtual) type of the object. This is the normal method dispatch in the Java programming language. - invokeinterface invokes an interface method, searching the methods implemented by the particular run-time object to find the appropriate method.
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-2.html#jvms-2.11.8
Avatar
omochimetaru 8/2/2019 3:07 AM
searching the methods とは書いてあるけど、そのへんは、JVM規格側なんで、
3:07 AM
実際の今のモダンなVMがどうなってるかとは、わからなそう。
3:07 AM
Javaは特にバイトコード規格と実装の分離を歴史的にがんばってるから、なおさら。 (edited)
Avatar
さっきの
A single local variable can hold a value of type boolean, byte, char, short, int, float, reference, or returnAddress.
からは、ペアになってなさそうな感じがする。
(edited)
Avatar
omochimetaru 8/2/2019 3:09 AM
その「reference」が、常に一通りのポインタ1個でなければならないとは、言ってないんじゃないですかね?
Avatar
まあそうだけど、クラス型とインタフェース型変数で区別されてたらそこに列挙されてそうじゃない?
Avatar
omochimetaru 8/2/2019 3:10 AM
う〜ん。まあそうですが、証拠にはならないと思います。
3:11 AM
どこまでの議論をして何を断じたいのかにはよりますが、OpenJDKプロジェクトとかならオープンソースだし、 OracleもOpenJDKに乗っかったから、
3:11 AM
そこを読みに行くのが一番正しい情報が得られると思います。
Avatar
うん、これだけで確証は得られないから「なさそうな感じ」。
3:12 AM
仕様じゃなくて実装としてしか存在しなさそうかぁ。
3:12 AM
ちょっと落ちます。
Avatar
reference 型の値はオブジェクトへのポインタって書いてあるから、やっぱ単にポインタ一つを保持してるだけじゃないかな?
The Java Virtual Machine contains explicit support for objects. An object is either a dynamically allocated class instance or an array. A reference to an object is considered to have Java Virtual Machine type reference. Values of type reference can be thought of as pointers to objects. More than one reference to an object may exist. Objects are always operated on, passed, and tested via values of type reference.
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-2.html#jvms-2.2
Avatar
omochimetaru 8/2/2019 4:17 AM
フーム・・・
Avatar
こっちでは reference 型を三つに分けてるけど interface のときの中身には詳しく触れられてないなぁ。
2.4. Reference Types and Values There are three kinds of reference types: class types, array types, and interface types. Their values are references to dynamically created class instances, arrays, or class instances or arrays that implement interfaces, respectively. An array type consists of a component type with a single dimension (whose length is not given by the type). The component type of an array type may itself be an array type. If, starting from any array type, one considers its component type, and then (if that is also an array type) the component type of that type, and so on, eventually one must reach a component type that is not an array type; this is called the element type of the array type. The element type of an array type is necessarily either a primitive type, or a class type, or an interface type. A reference value may also be the special null reference, a reference to no object, which will be denoted here by null. The null reference initially has no run-time type, but may be cast to any type. The default value of a reference type is null. This specification does not mandate a concrete value encoding null.
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-2.html#jvms-2.4
(edited)
4:20 AM
参照だとは書かれてるか。
4:22 AM
reference 型の値は reference だってトートロジーっぽいな・・・。さっきの文と合わせて考えるとこの reference は単一のポインタと考えて良さそうだけどいまいち確信が持てない・・・。
4:22 AM
#other-lang でやった方がいい気がしてきた。
Avatar
omochimetaru 8/2/2019 4:26 AM
改めて. 言語処理系好きのためのslackを作りました.すでに初学者から強い方まで色々な人が参加してます: https://t.co/MDWx2TTOgy
Retweets
145
Likes
379
4:26 AM
↑ここで聞けば知ってる人が居るかも。 (edited)
🙏 1
Avatar
norio_nomura 8/2/2019 5:24 AM
  • __TEXT,__swift5_protoセクションにprotocol conformance descriptorへのポインタが列挙されてる。
  • protocol conformance descriptorには以下 が含まれる。
    • protocol descriptorプロトコル
    • nominal type descriptorそのプロトコルに準拠する型。メタデータとは別
    • witness tableその型がプロトコル準拠するに必要なwitness一覧
  • nominal type descriptorにはメタデータへのポインタが含まれる。
これらのデータを元に、swift_conformsToSwiftProtocolは渡されたメタデータが準拠するプロトコル情報を探してきてくれる。実装はこちら。 https://github.com/apple/swift/blob/swift-5.1-branch/stdlib/public/runtime/ProtocolConformance.cpp#L544-L608
(edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
5:28 AM
* frame #0: 0x00000001012f3d13 libswiftCore.dylib`swift_conformsToSwiftProtocolImpl(… frame #1: 0x00000001012f3a56 libswiftCore.dylib`swift_conformsToProtocol [inlined]… frame #2: 0x00000001012f3a11 libswiftCore.dylib`swift_conformsToProtocol [inlined]… frame #3: 0x00000001012f3a11 libswiftCore.dylib`swift_conformsToProtocol… frame #4: 0x00000001012c4efa libswiftCore.dylib`swift::_conformsToProtocol… frame #5: 0x00000001012c8e07 libswiftCore.dylib`_conformsToProtocols… frame #6: 0x00000001012c849e libswiftCore.dylib`_dynamicCastToExistential(… (edited)
5:29 AM
これならば、witness tableへのポインタ持ちたくもなる。
Avatar
omochimetaru 8/2/2019 5:31 AM
「これならば」ってのは、データ構造を手繰るステップ数がかかるから、高速化のためにって意味ですよね?
Avatar
norio_nomura 8/2/2019 5:32 AM
そう。
🙂 1
Avatar
norio_nomura 8/2/2019 6:21 AM
otool -l /usr/lib/swift/libswiftCore.dylibで見る__TEXT,__swift5_protoのサイズは0x1288バイトで、含まれるprotocol conformance descriptorの数は 4744/8=593 Section sectname __swift5_proto segname __TEXT addr 0x0000000000379758 size 0x0000000000001288 offset 3643224 align 2^2 (4) reloff 0 nreloc 0 flags 0x00000000 reserved1 0 reserved2 0 (edited)
Avatar
omochimetaru 8/2/2019 6:25 AM
型の数がわかれば、一つの型の平均のプロトコル数がわかりますね
Avatar
norio_nomura 8/2/2019 6:28 AM
YamsのテストYamsPackageTestsだとサイズ0x5a4でprotocol conformance descriptorの数は180
Avatar
norio_nomura 8/2/2019 8:45 AM
型の一覧は__swift5_typesですね。 Section sectname __swift5_types segname __TEXT addr 0x000000000037a9e0 size 0x000000000000065c offset 3647968 align 2^2 (4) reloff 0 nreloc 0 flags 0x00000000 reserved1 0 reserved2 0
Avatar
omochimetaru 8/2/2019 8:46 AM
Avatar
norio_nomura 8/2/2019 8:46 AM
0x65c / 8 = 203個 (edited)
8:47 AM
どこのセクションに何があるかはここ (Mach-Oバイナリの場合) https://github.com/apple/swift/blob/master/stdlib/public/runtime/ImageInspectionMachO.cpp#L32-L45 (edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 8/2/2019 8:54 AM
この辺、バイナリのセクション名になってるの面白い
8:54 AM
実行ファイルのそのへんのデータ構造を普通に言語機能のために使ってしまうの驚いた
Avatar
norio_nomura 8/3/2019 4:07 AM
Class Existential Container が Witness Table を保持するのはなぜかって疑問。
これ、今更だけど、 https://github.com/apple/swift/blob/master/docs/ABI/TypeLayout.rst#class-existential-containers
Note that if no witness tables are needed, such as for the "any class" type protocol<class> or an Objective-C protocol type, then the only element of the layout is the heap object pointer.
って注意書きがあるね。プロトコル制約がある時だけwitness tablesを持つ。
(edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
4:08 AM
指定してるプロトコル制約が、指定したクラスが準拠してるプロトコル全てと同一でない場合は、別途witness tableを持つしかない、という当然の帰結になるのでは。
4:08 AM
速度とか関係なく。 (edited)
Avatar
今の Swift の実装でメタデータからメソッドにアクセスできるかどうかと、そのような実装をすることができるかは別問題ですよね?後者を採用しなかった理由としてパフォーマンスというのはあり得るんじゃないでしょうか。
Avatar
norio_nomura 8/3/2019 5:18 AM
「Class Existential Containerがプロトコル制約を持つ」を、witness tableを持たせる以外で表現してメンバを使う際にはメタデータからwitness tableを検索する様にしなかった理由、って事ですか?
Avatar
そうですね。昨日の会話では確証は得られませんでしたが、 Java 等ではそうなってるんじゃないかと思ってます。
Avatar
norio_nomura 8/3/2019 5:37 AM
なるほど、そういう実装との比較ならば、今の実装を選択したのはパフォーマンスが理由だと思います。
Avatar
そこの選択が分かれた理由が言語仕様による特性の違い(たとえば Swift は多数のプロトコルを conform させる傾向があり、よりパフォーマンス上のデメリットが大きい)とかがあるとおもしろそうだと考えてました。
Avatar
Generalized Existential が導入されて、一部の associated type だけ指定された場合、指定されなかった associated type は、戻り値で使われた場合は Any 、引数で使われた場合は Never になるんでしょうか? protocol Animal { associatedtype Foo associatedtype Bar func foo() -> Foo func bar(_ x: Bar) -> Bar } struct Cat: Animal { func foo() -> Int { ... } func bar(_ x: Bool) -> Bool { ... } } struct Dog: Animal { func foo() -> Int { ... } func bar(_ x: String) -> String { ... } } let animal: any Animal<Foo == Int> = Bool.random() ? Cat() : Dog() print(type(of: animal.foo)) // () -> Int print(type(of: animal.bar)) // これは (Never) -> Any になる?
Avatar
set getなvarとかどうなるんでしょ?アクセスできなくなる気もする
Avatar
omochimetaru 8/7/2019 3:56 AM
それが絡んだメンバはアクセスできないか、
3:56 AM
AnyCollectionのIndexと同じで、それもまたAnyになって、
3:56 AM
書き込みアクセスの時に、実態のassociatedtypeにダウンキャスト、型が違ったらクラッシュ
3:57 AM
とかが考えられますね
3:57 AM
protocol Animal { associatedtype Foo } なら Any で、 protocol Animal { associatedtype Foo : P } なら any P
3:59 AM
型安全(実行時クラッシュ無し)にするなら、CovarianceポジションはAny, ContravarianceポジションはNeverにするしかない。(associatedtypeにプロトコルついてるなら境界になる
Avatar
set getなvarとかどうなるんでしょ?アクセスできなくなる気もする
setget で型がずれちゃいますよね。ただ、ある引数が Never ってアクセスできないことを意味しているとも考えられて、 setNever == readonly と解釈すればおかしくないかも。
Avatar
omochimetaru 8/8/2019 1:31 AM
setが潰れると、any PがPを満たせなくなっちゃいますね
1:32 AM
まあ今も、Ext. PはPを満たさないので、そっちに寄せるのもありですが
1:33 AM
実行時エラーを許容してでもPを満たさせる方が、 既存のAnyCollectionなどには近い設計になるのでどっちの路線もありだと思います
1:34 AM
あ、てか、例の新マニフェストによると
1:34 AM
デフォルトでは違反になるものは生成されなくて
1:35 AM
自分でextension any P : P としてやって、違反してたやつを無理やり自分で実装するとself conformが得られる
1:35 AM
ってスタイルが提案されてたな
1:35 AM
それだとユーザーの意思で選択できて良さそう (edited)
Avatar
any Pset がつぶれることと any PP を満たすことは両立できるんじゃないかな?たとえば↓のコードで、 getSetValuefoo を渡すときに existential container を分解して特殊化されてない版を実行させることに問題はなくない? protocol Foo { associatedtype Value var value: Value { get set } } struct Bar: Foo { var value: Int } func getSetValue<F: Foo>(of foo: F) -> F { var foo: F = foo let value: F.Value = foo.value // get foo.value = value // set return foo } var foo: any Foo = Bar(value: 42) let value: Any = foo.value // foo.value = value // NG foo = getSetValue(of: foo)
Avatar
omochimetaru 8/9/2019 1:11 AM
たしかに。それは正しいですね。 そうか、existentialのassociated typeは、アイデンティティがextのインスタンスに紐付いたopaque typeになりますね。 ORTはアイデンティティが関数宣言に紐付いているけど、これは値一つに対して固定される型だ。
Avatar
omochimetaru 9/4/2019 1:10 AM
For a bit of background this stems from a bug I (and a number of other people) have reported on bugs.swift.org, the original being here: https://bugs.swift.org/browse/SR-103. The Current Situation For context let's start by looking at basic class inheritance, something we al...
1:11 AM
protocolのデフォルト実装が親クラスのvtableにエントリを作らない問題のスレ
1:12 AM
スレの中で過去スレが3つリンクされてるほどの根深いテーマ
Avatar
お、伸びてる
1:13 AM
classとprotocolの両方の挙動に深い理解を以って初めてわかる動きだからなぁ
Avatar
omochimetaru 9/4/2019 1:13 AM
レス14で提示されてるexistentialにアップキャストするパターンは初めて見たけどこれ見ると何が起きてるかわかりやすい
1:16 AM
親クラスに対するプロトコルPの後付けと、サブクラスBの定義を別モジュールから行った場合には、どうしてもクラスAのvtableは書き換えられないから
1:17 AM
どうにもならない気がする
1:19 AM
実装できないから解決しなくて、でもハマる人が出てくるから話題が繰り返してるんだと思うけど
1:20 AM
なんか良い落としどころはないんかなあ
Avatar
protocol extensionを含んだprotocolを「classの宣言時に定義」した場合にprotocol extensionをvtableに載せる、だと
1:21 AM
framework問題も解決しつつ整合性が取れそうに思える
Avatar
omochimetaru 9/4/2019 1:21 AM
それは1つの答えだけど、先付けと後付けで動きが変わるっていう新しい問題が新たに発生しちゃう
Avatar
それはそれでいいんじゃないか
Avatar
omochimetaru 9/4/2019 1:22 AM
余計難しくなってるようにも思える
Avatar
classはextensionに書いたメソッドをoverrideできない(objc除き)という規則もあるので
1:23 AM
受け入れやすいと思うよ
1:23 AM
一貫してると思う
1:23 AM
ただ、現状のprotocol extensionは上記extensionの括りに含みます、というのも
1:23 AM
それはそれで一貫してはいる
Avatar
omochimetaru 9/4/2019 1:24 AM
クラスのextensionがオーバーライドされない現象は、 サブクラス側でoverride修飾子が付かない事でハッキリしてて
1:25 AM
それが受け入れられるなら、今のプロトコルの挙動も受け入れられるような気がする。
Avatar
まあなんかoverride非表示じゃなくて
1:25 AM
コンパイルエラーにした方が良いとは思うけどw
1:25 AM
今のルールにするにしても
Avatar
omochimetaru 9/4/2019 1:26 AM
検出できる限りはエラーで止めるのは良さそう
1:26 AM
検出できないけどこの現象が起きる穴が気になるけど、、、
Avatar
framework超えで違反起きた場合も一律エラーで良さそう
Avatar
omochimetaru 9/4/2019 1:29 AM
例えば、AとPとBがそれぞれ別のフレームワークの場合は?
Avatar
最後にimportしてるフレームワークで破綻検知できるからそこで落ちれば良さそう
Avatar
omochimetaru 9/4/2019 1:31 AM
Bがfuncを定義しようとしたとき、同じ名前のメソッドが親クラスのprotocolでデフォルト実装がついていたら禁止するってことね
Avatar
後付けで破綻が起きてもエラー
Avatar
omochimetaru 9/4/2019 1:31 AM
じゃあ、 AKit <- BKit <- PKit の順番でimportが依存してる場合は?
1:31 AM
Bの時点だとAはPによる問題を抱えていないから見えない。
Avatar
Pを入れるところで発覚するはず
Avatar
omochimetaru 9/4/2019 1:32 AM
なるほど・・・そうだよね、で、最後が
1:32 AM
AKit <- BKit と AKit <- PKit というBkitとPKitが独立に実装されていて、 Appが BKit <- App, PKit <- App って
1:32 AM
両方取り込む場合は?
Avatar
importがエラーになればオケ
Avatar
omochimetaru 9/4/2019 1:33 AM
マジ?
1:33 AM
BKitもPKitも独立でビルドできているのに
1:33 AM
まとめて取り込もうとするとそれが拒否されるって現象は
1:33 AM
いいのかな・・・
Avatar
そういう挙動は許されるべきだと思う
Avatar
omochimetaru 9/4/2019 1:34 AM
「同時に取り込む互換性の無い2つのモジュール」って概念が爆誕するのか
Avatar
protocol extensionで同名のfuncを別々のframeworkに生やして二つimportしたら破綻する
1:34 AM
今でもそうじゃないの
Avatar
omochimetaru 9/4/2019 1:34 AM
お、そうだっけ
1:34 AM
今どうなるんだ?
Avatar
記憶が正しければその概念は既に存在したと思う、一回そのエラーを引いた記憶がある
Avatar
omochimetaru 9/4/2019 1:35 AM
やってみるか
1:35 AM
えーっと
Avatar
これコンパイルエラーにする時の問題は計算量が爆発しないかぐらいだと考えてるよ
Avatar
omochimetaru 9/4/2019 1:35 AM
PKit に Pの素体が入ってて、 PXKit に Pのdefault impl x、 PYKitにPのdefault impl y が入ってて
1:35 AM
AppからPXKitとPYKitを取り込むって形?
Avatar
そうだね
Avatar
omochimetaru 9/4/2019 1:36 AM
計算量は爆発しないと思うよ
1:36 AM
新たに取り込むモジュールのDeclの数nに対してO(n)のスキャンをするだけだから。
1:37 AM
すでに取り込んだDeclはテーブルに入ってればO(1)で突合チェックできる。
Avatar
where句とかもあるけど大丈夫かね
1:37 AM
まあ大丈夫か
Avatar
omochimetaru 9/4/2019 1:37 AM
whereの場合はそもそもvtableとか無理よね?
Avatar
同じ問題は発生するよ
Avatar
omochimetaru 9/4/2019 1:37 AM
あー、default implがwhereの場合か
1:38 AM
あれ?それって実装分けられるんだっけ
1:38 AM
できるか。
1:38 AM
conditional conformanceが1つしかできないだけか。
Avatar
そう
Avatar
omochimetaru 9/4/2019 1:39 AM
じゃあ今チェックしてるサブクラスが、親クラスの持ってるprotocol default implとの突合を見る時に、
1:39 AM
そのdefault implがwhere付きならそれが有効化するのかどうかを見ないといけんのか。
1:39 AM
まあ保守的に殺しても良い気がする・・・
1:39 AM
それこそ混乱しそうな状況だし。
Avatar
omochimetaru 9/4/2019 1:50 AM
Contribute to omochi/ProtoExConflictExp development by creating an account on GitHub.
1:50 AM
できた
1:51 AM
ちょっと思ったのと違う挙動だった
1:51 AM
AppからPXKitとPYKitをimportした瞬間に
1:51 AM
どちらのdefault implも消滅して
1:51 AM
App.S の S : P が conformされてないよってエラーになった。
Avatar
なるほど
Avatar
omochimetaru 9/4/2019 1:52 AM
片方だけimportすると、そっちがちゃんと入る。
1:52 AM
このほうが被害が最小限でいいね
1:52 AM
「対消滅が起きたこと」はなんらメッセージされないのがちょっと良くないと思ったけど。
1:53 AM
同じ発想でピンポイントブロックするのは難しそうだなあ
1:53 AM
PKitのdefault実装はすでにPKitの中のA conform Pで取り込まれちゃってるから
1:54 AM
Appで何かを無効にすることで止められるものでもない
1:54 AM
ま〜でも、う〜ん、import失敗するのが良いような気もするな
1:54 AM
そしたらこのスレの連鎖を止められる
Avatar
omochimetaru 9/18/2019 3:22 AM
var a = [1, 2, 3] func f(_ index: Int) { let b = Array(a[index...]) + Array(a[..<index]) print(b) } f(0) // [1, 2, 3] f(1) // [2, 3, 1] f(2) // [3, 1, 2]
3:22 AM
↑関数fの実装に関して、簡潔に書いたらこうなったんですがパフォーマンスが悪そう どういうのがいいかな
Avatar
Array(a[index...] + a[..<index])にすると少しだけ良くなりそう
Avatar
omochimetaru 9/18/2019 7:56 AM
あ、ArraySliceのまま結合できるのか。
Avatar
こういうプログラミング言語の特性も踏まえたパフォーマンスの話は面白いですね
9:41 AM
.first(where:)をメソッドチェーンの末尾に使う場合はメソッドチェーンの開始に.lazyを入れると早くなる、とか (edited)
Avatar
そういうの、Haskellみたいな遅延評価だと強いですよねー。
5:59 PM
循環については、 ArraySlice みたいな型を作ってラップして返すのが良さそう。
6:00 PM
で、 Array になってほしい時だけ選択的にコストを払って変換。
6:02 PM
CollectionSubSequence みたいに associatedtype 持っててもおもしろそう。循環コレクションから循環コレクションとっても循環コレクションのままでいいので二重にラップされないみたいな。
6:03 PM
RangeSubSequenceRange 自身なように。
6:04 PM
もう一つはlazy 方式かなぁ。
Avatar
omochimetaru 9/18/2019 6:15 PM
一番動作効率がいいのはCollectionをラップする型を作る方法ですねー
Avatar
ShiftedArray<Element> とかより Shifted<Base: Collection> とかの方がいいかな?名前は別として。
10:52 PM
IndexInt の縛りがないと難しいかな。
Avatar
omochimetaru 9/19/2019 3:19 AM
startIndex, endIndex, advanceがあれば、ラップした結果をSequenceにすることはできそう。 (edited)
3:20 AM
CollectionならoffsetbyがあるからCollectionにもできるかな?計算量要件を満たすかわからん
Avatar
そこが O(1) にできるなら StringIndexInt でいいんじゃない?
Avatar
omochimetaru 9/19/2019 6:05 AM
あ、負荷がかかるのは最初にShiftedArrayを生成するときだけだから
6:05 AM
普通にCollectionにできそう。
6:05 AM
Indexをadvanceするところは、同じように内部Indexを1つadvanceするだけだし、
6:05 AM
巡回してstartIndexに戻るところは内部collectionから取得できるので。
6:06 AM
というか、「どこから始めるか」をShiftedArrayのinitで受け取るだろうから、
6:06 AM
すでに最初のオフセット負荷は完了しているな。
Avatar
Shifted を生成する部分を O(1) にしたいのではなく?
Avatar
omochimetaru 9/20/2019 1:47 AM
例えばStringの場合、 Shifted(str, str.index(str.startIndex, offsetBy: 4)) とか書かざるを得ないと思うので
1:48 AM
Shifted自体は渡されたCollectionとIndexを受け取って生成するだけじゃないすかね
1:49 AM
Shifted(str, 4) として 内部で同じことをすることはできるけど、まあその場合もこれ以上早い方法は無いし。
Avatar
たとえば Shifted<String> があったとして、その subscript のインデックスはずらして循環させた String と同じものである必要があるよね?そのインデックスを生成する手間を考えたら、そのシフトされた String を生成した方が速くない?なので、 インデックスが Int 以外のときは Shifted が不要な気がする。より正確に言えば、 Int64 とか O(1) で計算できるやつはできるけど、そこはサポートしなくてよいかと。
Avatar
omochimetaru 9/20/2019 3:58 AM
その subscript のインデックスはずらして循環させた String と同じものである必要があるよね
そこはそうとは限らないような? Elementは同じものを期待してるけど、Shifted.Indexで良い
そのシフトされた String を生成した方が
「方が」が指してる2つはそれぞれどういう方式ですか?
インデックスが Int 以外のときは Shifted が不要な気がする
"abcd" から "cdab" を得るために必要です
(edited)
Avatar
シフトする API は必要として、 String で事前に O(N) 支払うならその API が返す型は String でよくない?
Avatar
Collectionassociatedtype ShiftedCollection: Collection where ShiftedCollection.Element == Self.Element, ShiftedCollection.Index == Self.Index を付けて func shifted(by: Int) -> ShiftedCollection として、 ArrayShifted<Array<Element>>StringString を返すのがいいかなぁ。 shifted が O(1) か O(N) かが型によって変化するのが微妙かな。
Avatar
omochimetaru 9/25/2019 5:11 AM
ああ、Shited型を作るんじゃなくてassociatedtypeにするとStringから直接Stringが得られるって事か。
5:11 AM
でもStringを再構成よりインデックスだけずらしてるラッパーの方が動作は軽そう。
5:13 AM
ShitedがCollectionだと思うんで、 String(Shifted(str, ...)) で明示的に再構成すれば良い気もします。
Avatar
たしかに計算量のオーダーは変わらなくてもラッパーならバッファは一つで済むし計算も軽そうだね。
6:21 AM
associatedtypeなら、Shiftedをさらにshiftしたときにネストしなくて良い(ArraySliceがネストしないのと同じ)というのはありそう。
Avatar
Swiftのrethrowsに条件をつけられるようになったら良さそう。 https://t.co/ir6fOzVoU0
2:56 AM
protocol Iterator { associatedtype Element associatedtype Failure: Error func _next() throws -> Element? } extension Iterator { func next() throws -> Element? { try _next() } } // 例外飛ばない版 // 本体の定義が`_next`なのは、もし`next`だとここで自己再起しちゃうから。。 extension Iterator where Failure == Never { func next() -> Element? { try! _next() } } // こういう仕組みが必要なのかもしれない // iterator.nextの呼び出しから例外が飛ばないことがXの型からわかるとき、 // dropCからも例外を飛ばないということを宣言したい // rethrows句自体はすでにあるけど、クロージャを渡した場合に限られた機能なので、 // これを拡張する。 func dropC<X: Iterator>(iterator: X, n: Int) rethrows(from iterator.next) { for _ in 0..<n { _ = try iterator.next() } }
3:00 AM
↑これどうかしら
Avatar
クロージャーを渡すのはダメなの?
3:07 AM
こういう時は値ではなくクロージャーを渡すようにしてる。結局本質的に欲しいのは値ではなかったりするので
3:08 AM
例えば他の例ではinitできることを保証するprotocolも便利だけど場合によってはinit関数それ自体を渡したほうがいいケースが結構ある (edited)
Avatar
Iteratorだとメソッドがシンプルすぎるからアレだけど、前提として、Errorを型にもつジェネリックな型を扱う場合において、それを使うライブラリを書く時にwhere Neverなオーバーロードを避けたくなるよね、という話です
3:30 AM
実例でいうとCombineのStreamとか。あ、でもあれは非同期だからthrowsが絡んでこないな。 (edited)
3:30 AM
Swiftc合宿 2019/09/28. Contribute to omochi/SwiftTypeInferenceHandsOn development by creating an account on GitHub.
3:30 AM
↑最近感じた実例をもう一つあげると、このTypeWalker.findは
3:30 AM
渡してるpreWalkが例外を投げないから、walk自体も例外を投げないんだけど、
Avatar
どちらかというとthrowsの側にwhereがあれば十分なのかな (edited)
Avatar
一度throwsのついてるvisitメソッドの呼び出しを経由するからrethrowsで表明できなくて
3:31 AM
ああ、throwsになる理由をwhereで示すってことよね?
3:31 AM
rethrows(from)のアイデアはまさにそれです。
Avatar
protocolとしてthrows funcを定義する時に条件付きにできれば
Avatar
あ、そっちか。
Avatar
rethrows側も解釈できるようになるはず
3:32 AM
ただまあなんかGenericだとthrowsに倒れざるを得ないのはわかる、というのと
3:33 AM
dropBみるとわかると思うんだけど、
Avatar
実は無理やり朋友関係を見出してそれをGenericsに無理に展開しようとした段階で理論破綻してるのでは?という気もしている
Avatar
多分そっちがわだとできないんだよね
3:33 AM
やりたいのはdropB自体がthrowsかどうかってことなので
3:33 AM
その本文のnext()がthrowsかどうかから伝搬させようとしたら
3:33 AM
「そもそもthrowsに合わせて中でtryをする」っていう縛りが
3:34 AM
壊れちゃう気がする
3:34 AM
うーん、関数型も(A) -> RってようはFunction<A, R>って型のfunc call()を呼んでるだけだからなあ。
3:34 AM
関数型だけ特別なんじゃなくて、rethrowsが関数型に特化してるので、それを汎用的なジェネリクス型に拡張すべきってアイデア。
Avatar
結論から言うとそういうときはResult使おうぜ、になるのでは
3:35 AM
そうでもない?
Avatar
Result型で返してErrorの型をResultの中に入れていけばいいのはそうだね。
3:35 AM
CombineでProviderモナドチェーンで書くのと同じ事になって
3:36 AM
ResultモナドでのflatMapスタイルで書けば解決はする。
Avatar
最終的にResultから値を取り出すタイミングでerrorがthrowされるかNeverで無視されるか、と言うことになる
Avatar
でもflatMapスタイルを通常の制御スタイルでかけるのがthrowsの魅力なので、throwsの適用範囲を広げたいじゃん。
3:36 AM
そうだね、あってる。>最終的に取り出すところ
Avatar
つまりErrorをassocに入れてthrow funcを書いたら protocol extensionにResult wrapperを書けばこの問題は本質的にクリアできる
Avatar
現状ならdropBみたいに2つ書くよりResultモナドに閉じ込めて書くほうがマシっちゃマシね
3:37 AM
でも.next()がResultで返ってきたら萎えるでしょw
Avatar
流石にthrow-rethrowにこれを展開するのは無理筋な気もしていて、これは餅は餅屋で良いのではないでしょうか (edited)
Avatar
うーむ。
Avatar
いやだから、nextそれ自体はthrow funcで書かれていて
3:38 AM
そのラッパーが用意されていれば、rethrows展開したいときはResultを使うことができるようになる、という感じ
Avatar
ああ、なるほど。
3:39 AM
直接使う用にthrowsとwhere Neverなno throwがあって、
Avatar
そうそうそう
Avatar
ジェネリックなライブラリを実装するようにResultのインターフェースもあるのね。
Avatar
カンのペキな気がする〜
Avatar
現状のベストプラクティスではあるね。
Avatar
話がそれちゃうけど、この例のFailureがNeverのときの具体的な型って、next()はthrows付きとthrowsなしの2つがオーバーロードされた感じになってるんですか?それともなしのほうだけになってる?
Avatar
2つのオーバーロードですね
3:44 AM
それで、where付きのほうがジェネリックシグネチャが厳しいので、両方いけるときはそっちが選ばれる
3:44 AM
呼び出し側でtryをつけてるかどうかはオーバーロードの結果選択に影響しない気がする。
Avatar
ということは、dropCはXの型によって、実際に呼び出す先が変わる?
3:46 AM
あ、 rethrows from ができたとしての話。
Avatar
あー、たしかに、このままだとdropCのなかで呼ぶnextが固定されちゃいますね
3:46 AM
tarunonのいうとおり、protocol側にも条件が必要そうだ。
Avatar
なるほど
Avatar
func next() throws(when Failure!=Never) -> Element?
3:47 AM
みたいにnextもオーバーロードするんじゃなくて、throws自体が変化するっていうスタイルでひとまとめにかかないとな。
3:48 AM
あ、ちがう、そこは func next() throws(Failure) -> Element? こうかければいいんだ。
3:48 AM
typed throwsですね。
Avatar
Resultある今それは難しそうだw
Avatar
じゃあdropCも同じだ。これでいいじゃん。 func dropC<X: Iterator>(iterator: X, n: Int) throws(X.Failure) (edited)
Avatar
なるほど
Avatar
そうか、Javaのtyped throwsは
3:50 AM
throws句にジェネリックパラメータタイプを書けないからダメだったんだな
3:50 AM
具体的なExcepition型を列挙しないといけない
3:50 AM
そこをジェネリクス対応させればスッキリじゃん
Avatar
本質的にそれResultですよね…
3:51 AM
多分だけどResultに糖衣用意してあげるほうが筋が良い気はしています
Avatar
それはそう。ていうか、throwsっていう文法機能が、エラーモナドの構文変換だから。
Avatar
do構文なんだよね、それが先に来て後からResult来たのはちょっとおもろい
Avatar
だからResult型の導入の時にErrorパラメータを付けるか議論が盛り上がったのだし。
3:52 AM
むしろResultでErrorパラメータを付けてくれた今こそ
3:52 AM
typed throwsの流れに期待はできる
Avatar
うーん私は
Avatar
ResultにErrorが無かったらCombineにもErrorが無くてそもそものストーリーが始まらなさそう
Avatar
Resultある環境ならそれに幾つかの糖衣を用意した方が筋はいい気はするのだよなぁ
Avatar
糖衣であると思っても差し支えなくない?
3:54 AM
throws(Failure) を用意するのとどう違うん
Avatar
単純に実装の実現性と今の仕様からの差分の少なさの話で
Avatar
差分は少ないと思うよ これまでのthrowsthrows(Swift.Error)と同じ意味として互換性が得られる
Avatar
フーム
Avatar
まあ本当に糖衣になるのなら、throws 付き関数を try なしで呼んで結果を Result で受け取れてもいいように思いますが。
Avatar
私のイメージはそんな感じでした。逆も然りで、Result返り値でそれが出来るのもアリかなと
4:01 AM
サブタイピングだと闇が発生するので、アサインのみ変換して許可とかになるかとは思いますが (edited)
Avatar
今は let a = Result { try f() } で包む必要があるね
4:01 AM
暗黙変換じゃなくて明示的変換
4:02 AM
糖衣であるっていうのがthrowsとResultの変換が暗黙である、って話になるなら、ちょっとまた別の論点そう
Avatar
Result が戻り値の関数を try 付きで呼ぶのも。
Avatar
あ、そうですね。現状だと try f().get() になるやつ。
Avatar
明示変換の方が良いのはそれはそう、なので
4:04 AM
書き味がもう少し良くなれば良いかな
Avatar
うーん、そのへんはやっぱりいらない気がするなあ。
Avatar
throwsとResultが実質的に等価であるというのはそうなんですが、糖衣構文という話になると、糖を剥がした書き方もできるのが当然という気がするんですよね。
Avatar
Resultは非同期とかで値をキープしたいためのものであって、
4:04 AM
エラーハンドリングを含むロジックを書くところで使うものではないような
Avatar
typed throwが無い今はそれの代替も含んでしまう
Avatar
typed throwsでdo-tryで書いて、最後にResultに明示的にしまえばいい。
4:05 AM
はい、今はびみょ〜な状態。
Avatar
で、そうなってしまった以上、typed throwをそこに提案するのは難しいんじゃ無いかなと思うわけです
4:05 AM
これは本質的にどちらが良いと言うよりは、人間がどのようにものを考えてしまうかと言う話で
4:06 AM
議論を運ぶのは難しそうだなと言う肌感がある (edited)
Avatar
そこは大丈夫、フォーラムの議論とか意味ないから
4:06 AM
コアチームがわかってればいい
Avatar
まあそれならいいんじゃがw
Avatar
あれの実態はコアチームが見落としがないように意見を集める場であって
4:07 AM
議論の流れの雰囲気と結論はわりと独立しがち
4:07 AM
これまで見てて良い意味で信頼してる
4:08 AM
僕が提案するとしてそもそもの説得力のある文章がかけるかという問題はあるけど。
Avatar
Resultを使った今のベストプラクティスを踏まえた上でtyped throwの優位性を説ければ、良い提案になりそうな気がする
Avatar
@omochimetaru
そうか、Javaのtyped throwsは throws句にジェネリックパラメータタイプを書けないからダメだったんだな
Javaのthrowsは型パラメータ書けなかったっけ?問題はbottom typeがないことと、throwsにbottom type書いたら検査が起こらないようにする機能がないことじゃないかな?あと、単一の型パラメータでは複数の例外クラスのthrowsに対応できないからUnionもいる。
Avatar
func f() throws(BError) -> T let r = Result<T, AError> { try f() }
3:09 AM
で、「あかんで」って言ってもらえるの便利だと思うけど
3:10 AM
逆に
3:11 AM
func f() throws(BError) -> T let r = Result { try f() } // 型パラメータ不要
3:11 AM
もできる
Avatar
Kishikawa Katsumi 10/21/2019 3:52 AM
そういえばJavaの例外がすごく嫌われて(その影響でなんとなくtry/catchが嫌われるのは)Javaは標準APIの例外の使い方が良くなかったからですね。 機能は今の言語と比べたら不足はしてるけどちゃんと設計されてたからAPIの例外がマトモだったらここまで嫌われることはなかった、はず。
Avatar
使い方が良くなかった
そう思います。 でもSwiftでいうところのtry!相当は欲しいですね。
3:54 AM
ある文だけをRuntimeExceptionにするときに5行か6行かかる
3:54 AM
あ、あと、throwsな関数の本文でどこから飛んでるかわからなくなるから、あんまり安心感が無いというのも。
3:54 AM
例外型システムはよくできてるけど ・標準ライブラリの準拠の仕方が悪い ・構文サポートが弱い(markedでないのが良くない, REへの昇格が煩雑) の2つ欠点があると思います (edited)
Avatar
RuntimeException周りが一番キツイ印象
3:56 AM
@koher@omochimetaru か忘れましたけど言及していたと思っていて、RuntimeExceptionがExceptionのサブタイプになってしまってる、っていうのと、その周辺の言語仕様との組み合わせでかなり辛い感じに仕上がってる気はするんですよね (edited)
Avatar
RuntimeExceptionがExceptionのサブタイプ
そこ自体は俺は正しいんじゃないかと思ってる
3:57 AM
検査が不要な式 < 検査が必要な式 のはずだから。 Swiftの関数型も () -> Void is () throws -> Void でしょ。
Avatar
えっとね
Avatar
Kishikawa Katsumi 10/21/2019 3:59 AM
その辺はJavaの時代はしょうがなかったし、そんなに問題はなかったと思う。
4:00 AM
java.sqlパッケージとかそのへんがもうちょっとなんとかなってれば。。。という。 (edited)
Avatar
まあたしかに、他の言語の書き心地もそこまで良くなかったですね。
4:00 AM
Rubyとかが書き心地に関しては切り開いたと思う。
Avatar
後思いつくのはRuntimeExceptionがNullPointerExceptionも含んでいるので、これが頻発する、とかかな
Avatar
NullPointerExceptionが検査例外じゃないとあまり意味ないのはそう
Avatar
Kishikawa Katsumi 10/21/2019 4:01 AM
あと、Javaの例外はコールスタックを保存するので遅いから、通常のケースで使うべきじゃないんだけど、そういうのが標準APIにあったとか。 (edited)
Avatar
でもそのためにはnull safetyが入ってないと実装できないからどうしようもないw
Avatar
Kishikawa Katsumi 10/21/2019 4:02 AM
そう ^JavaでNullPointerExceptionを検査例外にはできない。
4:02 AM
すべての行がtryになる。
Avatar
もしやったとしても、いくらやってもunwrapできない(not null型がない)から
4:02 AM
無限にtrycatchがひつようw
Avatar
Kishikawa Katsumi 10/21/2019 4:02 AM
いや、NullPointerExceptionはSIGABORTと思えばいいんですよ。
Avatar
その当たりの辛さが重なった結果、検査例外は辛いとして認識されているのだと思う
Avatar
Kishikawa Katsumi 10/21/2019 4:03 AM
JavaでNullPointerExceptionはキャッチしないわけだから、それはあまり関係ないんじゃないかな。
Avatar
検査例外は辛いと言ってる人の中には、Null safeじゃないのは辛いを意味している人も結構いるんじゃないかな
Avatar
たとえJavaの検査例外が良くできていたとしても、ヌルポで壊れちゃうのだと、結局安全な言語だと思えないから
4:03 AM
検査例外のおかげで安全になった、って認識できない気がします
Avatar
Kishikawa Katsumi 10/21/2019 4:04 AM
今の視点でいうとそう。
Avatar
正確には、検査例外で扱う範囲では安全、という状況は目指せたはずではあるけど
4:04 AM
「ヌルポはまあ別枠でしょうがないよね」って気持ちのもとで
4:04 AM
検査例外自体はいいものだよね、って思えた可能性はあるのかも。
4:05 AM
僕はJava頑張ってたとき、ちょっとはそう思った気がする。
Avatar
Kishikawa Katsumi 10/21/2019 4:05 AM
Javaが言ってた安全はポインタの演算がない、っていうので、 そのあと何年かして、イミュータブルとかNull安全とか、って感じじゃない? <=別の言語ね。 (edited)
Avatar
ああ、そうですね、Javaが掲げた安全は、未定義動作が生じないという意味の安全がでかくて
4:06 AM
どんなにバグらせてもメモリからコード注入とかできなくて、ちゃんとマネージドな例外になっている、という意味での安全。
4:07 AM
アプリが落ちるより、アプリのバグからクラックされる方がより怖いので、 そういう意味では、悪い状況のボトムラインはだいぶ上がったはず
Avatar
Kishikawa Katsumi 10/21/2019 4:08 AM
でまあサーバで使うぶんにはNullPointerException起こっても500になるだけだから、、、ってのはありますね。
4:08 AM
直すのは大変だけど。
Avatar
たしかに。RuntimeExceptionだろうがcatchできるのは良いところですね。
Avatar
@tarunon 僕も言ってますが @omochimetaru も↓で言ってますね。
検査例外すべてを補足しようとして、Exceptionのcatch節を書いてしまうと、それではRuntimeExceptionも捕捉してしまいます。
https://qiita.com/omochimetaru/items/c30f7a021fb9b8f0fa92#検査例外だけ捕捉するのが困難 >> RuntimeExceptionがExceptionのサブタイプ
そこ自体は俺は正しいんじゃないかと思ってる
これは意見が変わったの?
Swiftのエラーハンドリングは他のメジャーなプログラミング言語のどれとも異なる新しい仕様を持っています。特に、検査例外を持っているのですが、これはJavaで採用された以降はほとんどの言語で採用さ...
Avatar
「検査例外全てを補足したい」というニーズはあるけどそれができなくてRuntimeExceptionを巻き込む という問題意識は継続してます
6:33 AM
「サブタイピングが間違っている」ってかいてましたっけ?
Avatar
というのも、Exceptionは検査例外ですが、そのサブクラスであるRuntimeExceptionは非検査例外だからです。
Avatar
それ自体は、キャッチしちゃう理由だから、嘘は言ってないんだよな・・・
6:35 AM
どうするのがいいんだろうな Exception > CheckedException Exception > RuntimeException こうしておいたらよかったんじゃないか。
Avatar
うん、それだったらいいと思う。
Avatar
その上で、自分は、CheckedExceptionでまとめてキャッチを普段は使いたい
Avatar
でも、根っこにThrowableがあるし、Exceptionとは?ってならないかな?
Avatar
Exception is Throwableはおかしい気がしますね
6:37 AM
Throwableなら検査は不要なのに
6:37 AM
Exceptionを投げる関数はThrowableを投げる関数とみなせるはずなのに
6:38 AM
そうみなした瞬間にExceptionのcatch強制する性質が消える
Avatar
throwsの後ろに書けるという性質と、throwできるという性質を分けて考えないといけなさそう。
Avatar
Throwableは書けない?
Avatar
Javaではその二つが両方Throwableで表してるけど。というか、検査例外と非検査例外が同じthrows/throwで表されてるのが良くないのかな。
6:45 AM
throws Error とthrows Never 的サブタイピングを考えるとThrowableでまとめるのに無理がありそうって意味。
6:46 AM
そうすると検査例外が親じゃないといけないけど、そしたら↑の非検査例外巻き込みが起こるから、別系統にして構文も変えるのが良さそう。
6:49 AM
Swiftが非検査例外(Logic Failure)の構文をthrows/tryから分離したのは正しそうだなぁ。あとは、↓とかで非検査例外のハンドリングがサポートされれば…。 https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782#part-3-reliability-through-fault-isolation
Swift Concurrency Manifesto. GitHub Gist: instantly share code, notes, and snippets.
6:52 AM
@Kishikawa Katsumi JavaのAPIの例外の使い方が良くないというのは僕もそうじゃないかと思ってましたが、 parseInt の NumberFormatException が非検査例外なのが飛び抜けてヤバいのに印象が引っぱられてて、他はそうでもないと思うようになりました。
Avatar
それで岸川さんが出した例がjava.sqlパッケージの話なのかと思いました
Avatar
https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html このあたりの使い分けも Swift とあまり変わらなさそう。
This Java tutorial describes exceptions, basic input/output, concurrency, regular expressions, and the platform environment
6:54 AM
java.sql は全部 SQLException なのはヤバいけど、検査例外なこと自体はおかしくないんじゃないかなぁ。
Avatar
他はそうでもないと思うようになりました。
6:56 AM
List.addから飛んでくるunmodifiableは?
Avatar
あと、 null-safety がなくて NullPointerException で台無しってのと、 try! がないってのはその通りで、そのあたりの相乗効果で使いづらい。
6:57 AM
イミュータブル関連は、例外の使い方というより型ヒエラルキーの設計の問題かと。
Avatar
他になんかなかったっけなあ
7:02 AM
まあでもutilとかだとそもそも論理的なエラーになりえる場面がそんなにないか。
7:05 AM
class MyE extends Exception{}; class A<E extends Exception> { void f() throws E {} } public class Main { public static void main(String[] args) throws Exception { try { new A<MyE>().f(); } catch (MyE e) {} } }
7:05 AM
たしかに書けますね
7:06 AM
パラメータ型のthrowsはできるから、Never型があったらよかったなあ。 (edited)
Avatar
でもJavaはthrowsの後ろに複数の例外を書けるから、それを一つの型パラメータで表現するには、それがUnionで表されるようにならないといけないんよね。
Avatar
ん?どういうことですか?
Avatar
catchするのは(7か8から)Union的に書けるようになってる。
Avatar
一つの型パラメータで複数は表せなくてもよいのでは
Avatar
throws FooException, BarExceptionを
7:12 AM
throws Eで実現できない。
Avatar
Result<Integer, FooException | BarException>こういうことがしたくなりうるという話?
Avatar
たとえば、FunctionにEとthrows付けても、Neverがあっても
Avatar
うーんまあそうなるのか、普段から複数例外を並べているなら
Avatar
すべてのthrowsを表現できない。
Avatar
非同期APIとかもそうしたくなるはずか。
Avatar
なので、mapとrethrowsとかもできない。
Avatar
じゃあそれもいりますね、もしくはパラメータ化したいときは1個だけで我慢
Avatar
複数書ける仕様も良くない気がしてて、そのせいで雑に上の階層に投げなおされたりする。まあ、それはtyped throwsがなあ今のSwiftも同じかな。
Avatar
そのせいで
そのせいなのかどうかは微妙な気がしますけどね
7:19 AM
Eclipseの提示するAuto Fixが「throws Exceptionにまとめる」が1番だったら
7:19 AM
みんなthrows Exceptionにまとめていたような気もするし。
Avatar
null safety、try!、検査例外だけcatch、検査例外のparseInt、単一throwsが実現された世界なら検査例外素晴らしいってなるかもしれないけど、そりゃイメージできないよね。それだけ距離があると。
Avatar
まあそうですねw
7:40 AM
Swiftコアチームはすごい。
Avatar
ほんとに。
Avatar
ある程度使ってやっと納得できた
Avatar
結果的に多くの言語が非検査例外に傾いちゃったのが残念だね。特にKotlinはきついなー。必要なものはほとんど揃ってそうなのに。
Avatar
Kishikawa Katsumi 10/21/2019 10:09 AM
Javaのthrowsは全部列挙しなきゃいけなかったんだっけ。それは大変だな。だいぶ忘れてる。。。
Avatar
ヴァルボーグ@toyosuke 10/21/2019 10:12 AM
IDE任せにしてたけどJavaは確かにそうなんだよな… 3つくらいのExceptionを関連メソッドに実装していった覚えがある
Avatar
SwiftはTyped Throwsが導入されてもthrowsに書けるのは一つのエラー型だけってChris LattnerかJoe Groffあたりが言ってたはず。
Avatar
それは言語がenumを持ってるから簡単にユニオン的な事ができるからってのもあるでしょうね
10:15 AM
ユニオンよりもタグが付けられるから、同じエラー型でも複数経路ある場合区別できるし。
Avatar
そうすると下層のエラーが複数種類ある場合に雑にそのまま投げなおすことができないから、Errorとしてまとめるか、そのAPIに適したエラーに包みなおして適切な粒度でcaseを分けることになる。
10:16 AM
Javaにtagged unionがないのもきついよね。
10:17 AM
まあ、untagged unionがあればある程度なんとかなるのかな?
Avatar
throws句はuntagged unionを毎回書き下してるとも言えますね
10:18 AM
typealiasでそのペアに名前が与えられたらまだ良かったかも。
Avatar
#swift ユーザーにアンケート 言語機能の検査例外(do,try,throw,throws)は
10:36 AM
↑思ったよりは嫌い票が多い。
Avatar
throws句はuntagged unionを毎回書き下してるとも言えますね
うん。なので、先の型パラの話は、untagged unionがあれば解決するんよね。 throws A, B, Cをthrows A|B|Cのシュガーにする。
Avatar
untagged unionの直接記法がある状況と
11:28 AM
それのtypealiasが命名できる状況にはもう一手、使い心地の違いがあると思って。
11:28 AM
Javaにはtypealias無いですよね。
Avatar
catchについては、今のJavaでも catch(A|B|C e) { ができる。
11:30 AM
typealiasはないね。 (edited)
Avatar
そこでtypealiasがないと、
11:30 AM
カプセル化できてないから微妙な気がします
Avatar
typealiasはカプセル化はしなくない?
Avatar
例えば
11:31 AM
class A { typealias Error = NumberFormatException | IOException; void f() throws Error { } }
11:31 AM
こういう状況で、f()を呼び出して、そのままthrowsする関数をAのユーザーが作ったときに
11:31 AM
A.Errorで再throwsを書ければ
11:32 AM
将来A.Errorの右辺が変更したときも
11:32 AM
「Aのエラーをそのまま再throws」っていう意味の記述が維持できるけど
11:32 AM
typealiasが無いと、再throwsする関数のシグネチャも直さないといけない
11:33 AM
そういう意味でAのユーザーにとってA.Errorの実体を無視することを許すのでカプセル化?かなと
Avatar
エイリアスの指すものは隠蔽されないし、rethrowで足りないものはコンパイルエラーで浮かび上がるから良いのでは?
Avatar
安全性は壊れないけど書き直すのは面倒じゃないですか。
Avatar
SwiftでErrorのenumでcaseを足したときと同じじゃないかなぁ。
11:34 AM
違うか
Avatar
SwiftのErrorでcaseを足したときも、
11:34 AM
そのまま投げる場合はそのままでいいですよね。
11:35 AM
switchしてるところは追記しないといけないだけで。
Avatar
catch側だけ分岐しなおせばいいか。
Avatar
はい
Avatar
まあ、ただ、そのままrethrow自体が良いことじゃないから
11:35 AM
そのための機能をサポートするのは微妙な気がする。
Avatar
引数のオーバーロードをちょっと足すだけみたいな状況なら
11:36 AM
そのままrethrowするのが正しいコードだと思います
Avatar
オーバーロードでrethrowってどういうケース? Swiftでrethrows使ってるようなケースはまさにrethrowが良いと思うけど。
11:38 AM
それはでも型パラがエイリアス代わりになる。
Avatar
ライブラリにA.f(float x) throws Error みたいな関数があったときに、 アプリモジュールで追加してる Angleみたいな型があったとして、a.f(angle)ってそのまま渡せるように A.f(Angle angle) throws Error を追加するみたいなケース。 実装としては、angle.valueを元のfに転送するだけ。
Avatar
そういうケースは素通しさせたいかもだけど、それって戻り値も同じ話にならない?throwされるエラー値って戻り値の一種だし。Resultで考えてみたらエラー型だけ素通ししたいってのは変な要求では? (edited)
Avatar
同様に、戻り値にunion typeを使うなら、将来増えそうなのでtypealiasしておいてほしいですね
11:58 AM
Swiftでenumを使うときに
11:58 AM
返り値の型のところで毎回caseを書き並べていたら不便でしょう。
Avatar
うーん、unionの要素(?)が増えるってpublicなAPIの変更なわけで、unionの変更に限らず戻り値の型の変更とかと同じで、それなりに大ごとだしコンパイラが検出できるならいいんじゃないかな?typealiasが助けになる面はあるとしても、あまり本質的なことじゃない気が。 (edited)
Avatar
Swiftでenumのcaseが増えるときは、その値をswitchで開いて使うところでしか変更が生じないのと同じじゃないですか?
12:05 PM
enumの型名を変数名、引数、返り値の型に使ってるところは、そのままです。
12:05 PM
caseが増えたときに、そうした箇所全てを直すのは、大変すぎるし特に意味がないと思う。
12:07 PM
なので、untagged union typeが導入される場合、そのunionの組に対して名前をつける機能はセットじゃないと
12:07 PM
つかいづらいとおもう
Avatar
でもそれって、untagged unionを使うAPIの設計者がtypealiasを付けてくれないとダメじゃない?それを強制したいならtagged unionが必要なのでは?
Avatar
付けれたら付けてくれると思います 強制はできないですね Swiftでもラベル付きタプルを返り値の型に直接書くか、typealiasしておくか、みたいな時は似たような状況になる。
Avatar
タプルにエイリアスみたいなときはたいていstructが正解じゃないかなぁ。
Avatar
同じ話だと思います。
2:32 PM
タプルはフィールドの積で、untagged unionはフィールドの和だから。
Avatar
うん。non-nominalのエイリアスって微妙なケースが多くて、それだったらnominalにした方が良いという感覚だから、untagged unionにエイリアスってピンと来なくて、それはtagged unionが必要なんじゃないかと。 (edited)
Avatar
むむ、それは論点がずれてると思います
2:34 PM
untagged unionかtagged unionかの違いは
2:34 PM
データ構造として、unionでマージしてる個別の要素を、型だけで区別するか、名前をつけて区別するかであって
2:34 PM
そのまとめた全体に名前をつけられるかどうか、は直交する話だと思います。
2:34 PM
つまり・・・
2:37 PM
untagged union: (FileIOError | NetworkError) ↓名前を付けたuntagged union DownloadError = (FileIOError | NetworkError) tagged union: (cacheFileIOError: FileIOError | downloadFileIOError: FileIOError | network: NetworkError) ↑taggedは、ケースにtagがついているので、FileIOErrorを2つ区別して保持できる tagged unionに名前が付けられる: ↓これの左辺の事 DownloadError = (cacheFileIOError: FileIOError | downloadFileIOError: FileIOError | network: NetworkError) (edited)
2:37 PM
Swiftのenumに関して言えば、 enum DownloadError // ←ここに名前がつくかどうかじゃなくて { case cacheFile(FileIOError) // ←このケースと case downloadFileIOError(FileIOError) // このケースが区別できるのがtag case network(NetworkError) } (edited)
2:38 PM
で、Swiftのタプルは、taggedな値の積なんじゃないかなと
2:43 PM
実際他の言語の例だとTypeScriptは名前が付けられるuntagged unionです https://github.com/ReactiveX/rxjs/blob/5.5.12/src/Observable.ts#L19 (edited)
A reactive programming library for JavaScript. Contribute to ReactiveX/rxjs development by creating an account on GitHub.
2:44 PM
(最新のmasterでその部分の設計が変わっていたので5系のリンクですが・・・) (edited)
2:45 PM
A reactive programming library for JavaScript. Contribute to ReactiveX/rxjs development by creating an account on GitHub.
Avatar
そのまとめた全体に名前をつけられるかどうか、は直交する話だと思います。
たしかにそれはそうだなぁ。
3:13 PM
そうすると論点は↓で
caseが増えたときに、そうした箇所全てを直すのは、大変すぎるし特に意味がないと思う。
これはたまたまenumではそうだけど、戻り値の型が変わったら素通しで投げ返してる箇所全部変更するわけだし、エイリアスで解決できるのは一部のケースだけだし、その一部がエイリアスを導入することを正当化できるのかかなぁ。
3:14 PM
現にJavaのthrowsはすでに同じ問題を抱えてるはずだけど、エイリアスなしでやってきてるわけだし。
3:15 PM
エイリアスは役に立つかもしれないけど、それは複数例外のthrowsをunionで書けるようにする話とは独立なんじゃないかな?
Avatar
そこもまた別ですね。
Avatar
関係ないけど、たまたま今Java界隈が検査例外で盛り上がってるみたいだね。
Avatar
現にJavaのthrowsはすでに同じ問題を抱えてるはずだけど、エイリアスなしでやってきてるわけだし。
ここがやってこれなかった理由じゃないかなあと思っていて、ここまでの僕の意見の流れがあります。
3:16 PM
根っこで1種類増えると素通し系全部throwsのところ直さなきゃいけなくて、やってられ〜んと思って、後続の言語がやめちゃった。
3:17 PM
ですね、朝なぎせさんがツイートしてた
3:17 PM
チェック例外の議論してるのに、パッと見、Swiftの言及がないのはなんなんだぜ? https://t.co/aiYxUmBzPt
Avatar
↓これどういうケースだろ? https://twitter.com/gakuzzzz/status/1185168047838879744?s=21
ただ、やっぱりEitherと比較すると関数合成で特定のパターン(f . g で fがエラーを返しgがエラーをリカバリーするようなパターン)を実現できないので、柔軟性という意味ではEitherの方がまだ利がありそう...
3:19 PM
あ、前のツイートからの続きでSwiftのtyped throwsの話してる。
Avatar
がくぞさんにもrethrowsの仕様伝わってるのか、良かった
Avatar
ここがやってこれなかった理由じゃないかなあと思っていて、ここまでの僕の意見の流れがあります。
なるほどー。それなら筋の通る話ではあるね。ただ、本来素通しはそんなに起こらないと思ってて、苦しんでるほとんどのケースは雑な素通しが原因だと思うんよね。
Avatar
がくぞさんの言ってるのは、 g() -> Either<A, E> と f() -> Either<A, E> に対して、 gとfを合成して述べてるような関数を作る高階関数hを構成できることを言ってるのかな?
Avatar
違うか。包み直すのが理想的なのはそうとして、実際問題ほとんどはエラーかどうかがわかればいいから、現実的に雑な素通しが横行することになって、そこでthrows Exceptionができればよかったんだけど、RuntimeException巻き込み問題があるからそれもできないと。
Avatar
本来素通しはそんなに起こらないと思ってて、苦しんでるほとんどのケースは雑な素通しが原因
そこはやってみたことがないからなんとも言えないんですけど、雑な素通しで良いケースが結構多い気はしている
3:26 PM
あ、そうですね、Javaの場合はそこでRE巻き込み問題が絡んでくる。
3:26 PM
Combineにはエラーの型がついたから、試しに取り組むならCombine上でちゃんとやるのがいいでしょうね (edited)
Avatar
なんか細かいやらかしがたくさん積み重なりすぎて詰んでるよね😅
Avatar
いなみさんとかはReactiveSwiftでエラーの型ちゃんと合成してんのかな〜
Avatar
Swiftに最初からtyped throws入れなかったの、Core Team賢すぎるな。
Avatar
まあJavaはそうですね>積み重なり
3:28 PM
Kotlinが刷新してくれたらよかったがそうはならなかったので
3:28 PM
次のAltJavaに期待
Avatar
Kotlinに検査例外ないのほんと辛いよね。
Avatar
まあinline funからのreturnができるんで、Eitherで頑張る手もある
Avatar
null safeだけとerror unsafeになっちゃったという…。
Avatar
あーでもそれだと自分でtryの振る舞いを書き下してるだけか
Avatar
今さらKotlinとScalaを超えるAltJavaが出てきて覇権をとるイメージがわかないなぁ。10年は無理では。
Avatar
do記法のあるscalaはその点は結構いいですね
3:31 PM
scala3は結構期待できるのかも
3:31 PM
最近仕様?が出始めたらしくて、結構変わっている
3:31 PM
らしい
Avatar
scalaのdo記法ってforのこと?
Avatar
あ、forでした
3:37 PM
でもあれはifとかとシームレスではないか。
Avatar
throws/tryやasync/awaitのいいところって、制御構文と柔軟に組み合わせられるとこだと思うけど
3:38 PM
って同じことを言おうとしてるかな?
Avatar
あ、はい
3:39 PM
その絡みでいうと
3:39 PM
『0から知った気になるAlgebraic Effects』で発表しました。 ご清聴ありがとうございました。 スライドはこちらです。 https://t.co/1qC5hONvLS #FunFunFunctional
Avatar
モナド、そのあたりが辛いけど、Haskellとかうまくやれんのかな?パズルになりそうな印象なんだけど。
Avatar
↑この資料と出会って、ついにEff読めるようになりました
Avatar
おお
3:40 PM
これでJoe Groffの言ってることがわかる?
Avatar
わかった
Avatar
見てみよう
Avatar
I've thought about this some. It might not have to be a keyword, if this were a generalized language feature. Anything that interrupts control flow and optionally resumes it later, such as 'throws', 'yields', and potentially also 'async', could be implemented as instances of ...
3:43 PM
これは要するにEffのAlgebraic effectsをSwiftな構文で組み込むならこんな感じにできそーって話
👍 1
3:44 PM
読んでみてください
Avatar
Swift5.1 on UbuntuでDateComponents.dateがmacと比べてめちゃくちゃ遅いっぽい…… ubuntuはDocker上でしかためしてないんでオーバーヘッドはあると思いますが流石にこの差はなにかありますよね? mac: $ cat main.swift import Foundation var comps = DateComponents( calendar: Calendar(identifier: .gregorian), timeZone: TimeZone(secondsFromGMT: 0)! ) comps.year = 2019 comps.month = 11 comps.day = 10 comps.hour = 10 comps.minute = 10 comps.second = 10 comps.nanosecond = 10 let start = Date() var total: TimeInterval = 0 for _ in 0..<10_000 { total += comps.date?.timeIntervalSinceNow ?? 0 } print("time: \(Date().timeIntervalSince(start))sec, \(total)") $ swiftc -O main.swift $ ./main time: 0.011227965354919434sec, 14087090925.878277 ubuntu on dokcer on mac: root@15ebe51be255:/var/vapor-app# swiftc -O main.swift root@15ebe51be255:/var/vapor-app# ./main time: 1.0126609802246094sec, 14088576437.363556
2:55 AM
VaporのMySQLからDateデコード処理がこれで、しかも関連する型がinternalなので自前実装に変えるのが面倒そう (edited)
Avatar
100倍は遅すぎるとは思うけど流石にdocker on macは仮想環境なのでそこは実Linuxで見ないとなんとも。
Avatar
スペック違うので単純比較できないですけどとりあえずやってみます。 (edited)
Avatar
(まあクラウドも仮想環境ですけど
Avatar
(現在クラウドにデプロイを試みているという文脈
Avatar
Kishikawa Katsumi 10/25/2019 3:00 AM
Swiftbotでやってみたけど同じくらいですねえ。あれもDockerだけど。
Avatar
Azure VM B2Sインスタンスにて $ swiftc -O main.swift $ ./main time: 0.4973900318145752sec, 14075794190.737843
3:15 AM
クラウドはCPU性能がよく分からないので比較には向いてなさそうですね…… 自宅のubuntuマシンで確認して三環境分まとめてbugsに報告が良いか。
Avatar
最終的にはICUに渡して日付計算を行なっているみたいで、そのために(?)いろいろ変換とかしてるようなので、その分時間がかかっているのかも、しれない、と思いました。
3:24 AM
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
Avatar
4.x -> 5.xで2倍くらい遅くなってるぽい。 $ pbpaste|docker-swift41 -O - time: 0.272868990898132sec, 14066769520.098 $ pbpaste|docker-swift42 -O - time: 0.32283997535705566sec, 14066729445.257643 $ pbpaste|docker-swift50 -O - time: 0.5901000499725342sec, 14066676853.962284 $ pbpaste|docker-swift51 -O - time: 0.5475540161132812sec, 14066619176.887285 $ pbpaste|docker-swiftnightly -O - time: 0.779636025428772sec, 14066542714.192633 $ pbpaste|swift42 -O - time: 0.013067960739135742sec, 14066457781.279984 $ pbpaste|swift50 -O - time: 0.01632702350616455sec, 14066407578.90026 $ pbpaste|swift51 -O - time: 0.014343976974487305sec, 14066365250.005945 (edited)
Avatar
文字列に変換してDateFormatterで変換したほうが3倍くらい速い # cat main2.swift import Foundation let df = DateFormatter() df.dateFormat = "yyyy/MM/dd HH:mm:ss.SSSSSSS" let start = Date() var total: TimeInterval = 0 for _ in 0..<10_000 { let year = 2019 let month = 11 let day = 10 let hour = 10 let minute = 10 let second = 10 let microsecond = 101010 let date = df.date(from: "\(year)/\(month)/\(day) \(hour):\(minute):\(second).\(microsecond)") total += date?.timeIntervalSinceNow ?? 0 } print("time: \(Date().timeIntervalSince(start))sec, \(total)")root@15ebe51be255:/var/vapor-app# swiftc -O main2.swift root@15ebe51be255:/var/vapor-app# ./main2 time: 0.32200801372528076sec, 14063930163.143023
😅 1
3:32 AM
5系でなにか変更あったんですかね。
Avatar
icuがtoolchainに同梱される様になったのが5.0からじゃなかったかな?
Avatar
文字列経由の方が早いのは笑うw
3:44 AM
パースが要らない分compsのほうが早いはずなのに、、
Avatar
さっきの変換自体は昔からあるみたいなので関係なさそう。
Avatar
昔の段階でmacOS上と比べて遅いかどうかは依然気になるところではありますね。
Avatar
そうか。昔もmacOSに比べると遅かった可能性は十分ありますね。
Avatar
4.2でも遅い。 $ pbpaste|docker-swift42 -O - time: 0.27475202083587646sec, 14051535205.538399 $ pbpaste|swift42 -O - time: 0.012828946113586426sec, 14051471374.175034
Avatar
ああ、これdocker-ついてない方はmacなんですかね。 (edited)
Avatar
そそ。
Avatar
Swift 5というと、このへんで大きく変わってはいるみたい。大きく変わりすぎててコードの変化がよくわからない。 https://github.com/apple/swift-corelibs-foundation/pull/1755
In the Mojave timeframe, we have extensively overhauled the way CFCalendar (and consequently, NSCalendar and struct Calendar) work, and improved accuracy, stability and test coverage of several cla...
3:53 AM
CFCalendar.cの _CFCalendarComposeAbsoluteTimeV がICUを呼び出しているところだと思うんですが、 そこが大きく変わっているような (edited)
3:58 AM
いや、そんなに大きくは変わってないみたいでした
Avatar
DateFormatterと速度逆転する時点でおかしいしこれだけ提示して報告で良さそうですね。
Avatar
https://bugs.swift.org/browse/SR-11667 投稿しました。何か追記することがあったら書いてください。
Avatar
DateFormatter使った方はmacOSとそんなに変わらないのね。
Avatar
macのCPUが2.7GHzでubuntuのが2.3GHzなのでその差って感じですね。 (edited)
Avatar
ぬ、CPU specに差があるなら それを一応書いておくべきでは。
Avatar
単純にDateFormatterと比較して遅いのはおかしい。ってつもりでしたが書いておきますね。
Avatar
perfでprofileしてみた。
Avatar
omochimetaru 11/2/2019 2:31 AM
コンパイラのバグとして報告されてる。めっちゃシンプルで草。ひどい。 https://t.co/hmXoZqBdok
2:33 AM
Swiftコンパイラ史のなかでもトップのヤラカシだと思った アプリのRxSwiftで踏んで様子見てたんですけど、もっと条件ゆるかった
Avatar
We found a workaround. Setting DEAD_CODE_STRIPPING = NO in our app’s target fixes the crash.
(edited)
Avatar
Short description of the issue: I&#39;m getting crashes when using merge() with Xcode 11.2. Same code with 11.1 works fine. What actually happens: EXC_BAD_ACCESS (code=1, address=0x0) frame #0:...
11:38 AM
こっちのスレだとそれでも直らない人も居るみたい
😢 2
11:39 AM
DCE(Dead code elimination)無効化で直るのは
11:39 AM
条件の組み合わせ的な話でroot issueではないんじゃないかなという気がする
11:39 AM
条件にSwiftPMによるビルドっていうのがあるので
11:39 AM
メタデータシンボルの可視性とかリンク時の解決が
11:40 AM
微妙にSwiftPMが組むビルドによって異なっているとかじゃなかろうか
Avatar
omochimetaru 11/5/2019 7:05 PM
This review ended on October 21st, but because of the LLVM conference, the Core Team didn't have an opportunity to discuss it until last week. Swift's indexing model is based on solid concepts that have held up well over the years, but the verbosity of expressing positions a...
7:06 PM
新しいオフセットインデックス記法のレビューが改善してやり直しになった
7:07 PM
もし必要ならスライスのためにコア言語機能の拡張もありうる、とかも書いてある
Avatar
これ通ったらちゃんと読もうと思ってたけどやり直しになったのか。
Avatar
omochimetaru 11/6/2019 8:00 AM
MichaelさんSwiftチーム入ってずっとStringAPIについて考えてるのに
8:00 AM
正規レビューの段階でコアチームからこのツッコミ入って差し戻しされるの
8:00 AM
ちょっとかわいそうだなって思った・・・
Avatar
I’m excited to announce a new open-source project for the Swift ecosystem, Swift Numerics! Swift Numerics will provide the building blocks of numerical computing in Swift, as a set of fine-grained modules bundled together into a single Swift package. My hope is that we can ...
Avatar
omochimetaru 11/8/2019 1:10 AM
おお!?
Avatar
numpyのswift版ですか?
Avatar
omochimetaru 11/8/2019 1:12 AM
いや
Avatar
内容的にはまだComplexとRealしか無いのでそこまではいってなさそう
Avatar
omochimetaru 11/8/2019 1:13 AM
実数プロトコルと複素数だね
Avatar
ふむ
Avatar
omochimetaru 11/8/2019 1:14 AM
続きでやりたいって言ってるShapedArrayが任意階数のテンサー?
Avatar
あ、ShapedArrayはまだ実在しないのか
Avatar
omochimetaru 11/8/2019 1:17 AM
A ShapedArray protocol and supporting types, capable of representing multidimensional homogeneous data. If you’ve worked with S4TF before, you’re already familiar with this concept; otherwise, you may have used NumPy arrays in Python, or Fortran, Matlab or Julia arrays.
1:18 AM
これがあるとないとじゃ全然別の粒度のライブラリに見えそうだな オペレータの数もめちゃくちゃ増えるだろうし
Avatar
https://github.com/apple/swift-numerics/blob/master/Package.swift targets: [ .target(name: "Complex", dependencies: ["Real"]), .target(name: "Numerics", dependencies: ["Complex", "Real"]), .target(name: "NumericsShims", dependencies: []), .target(name: "Real", dependencies: ["NumericsShims"]), ... ]
Numerical APIs for Swift. Contribute to apple/swift-numerics development by creating an account on GitHub.
Avatar
Deleted User 11/8/2019 7:04 AM
これsqrtでintermediate overflow/underflowがないと書いてあるように読めるのですが、どう実現するんでしょう (edited)
Avatar
hypot自体がもともとoverflowしないようになってたような。
7:07 AM
hypot, which computes sqrt(xx + yy) without intermediate overflow or underflow.
ここですよね?
Avatar
Deleted User 11/8/2019 7:08 AM
そこです
Avatar
Hypot is a mathematical function defined to calculate the length of the hypotenuse of a right-angle triangle. It was designed to avoid errors arising due to limited-precision calculations performed on computers.
Avatar
sqrt の前に x * x とかでオーバーフローしないって意味ですよね?
7:11 AM
シンプルに sqrt(x*x + y*y) として実装するとオーバーフローしちゃうかもしれないから (edited)
Avatar
omochimetaru 11/8/2019 7:12 AM
Numerical APIs for Swift. Contribute to apple/swift-numerics development by creating an account on GitHub.
7:13 AM
libmのhypotの実装に依存してそう
Avatar
Deleted User 11/8/2019 7:14 AM
このあたり意識したことないのですが、このdocs見る限りオーバーフローは起きることもあるのでは、、、と思いました(こなみ) http://www.cplusplus.com/reference/cmath/hypot/
Avatar
最終結果のoverflowと計算途中のoverflowは別で、計算途中のほうだけ(xx + yyによるところだけ)起こらないんじゃないでしょうか。
7:16 AM
https://cpprefjp.github.io/reference/cmath/hypot.html
算術型の平方和の平方根を求める。この際、余計なオーバーフロー、アンダーフローを起こさない。
>オーバーフローエラー、アンダーフローエラーが発生する可能性がある。
算術型の平方和の平方根を求める。この際、余計なオーバーフロー、アンダーフローを起こさない。hypot は hypotenuse((直角三角形の)斜辺)の略。
Avatar
omochimetaru 11/8/2019 7:17 AM
概要の「余計なオーバーフロー、アンダーフローを起こさない」とは、たとえ x2 が戻り値型の範囲を超えていても、結果が戻り値型の範囲に収まるのであればオーバーフローしないで正しい結果を返す、と言う事である。
Avatar
Finally, the multiplication by |x| cannot underflow, and overflows only when the result is too large to represent.
Avatar
そこを引くべきだった
Avatar
さっきの @t.ae の Wikipwdia にも書いてあった。
Avatar
例えばhypot(Float.max, 0)はオーバーフローしないけどhypot(Float.max, 100)とかはするってことですね。 (edited)
Avatar
float function hypot(float a, float b) { let [float x, float y] = [ // x ≥ y max(abs(a), abs(b)), min(abs(a), abs(b)) ]; if (x == 0) // x = y = 0 return 0; // avoid division by zero let float t = y / x; // 0 < t ≤ 1 return x * sqrt(1 + t * t); // > 0 }
Avatar
omochimetaru 11/8/2019 7:19 AM
あ〜
7:20 AM
sqrt ( x^x + y^y ) == x * sqrt ( (x^x + y^y) / x^2 ) == x * sqrt ( 1 + (y/x)^2 )
7:20 AM
こういうこと?
7:22 AM
実装が見たいけど__builtin_hypotとやらになっててその先がわからん、これどこから来るんだ
Avatar
GitHub is where people build software. More than 40 million people use GitHub to discover, fork, and contribute to over 100 million projects.
7:27 AM
These functions provide compatibility with GNU library header files. The functions are described in the GNU documentation.
Avatar
omochimetaru 11/8/2019 7:29 AM
これも計算の実態は書かれてない
Avatar
Deleted User 11/8/2019 7:32 AM
I have a MIPS program to compute the hypotenuse from two integers. However the program prints some weird number not the actual result, my best guess is there is something wrong with the square root
Avatar
↓やって遊ぼうとしたけど、 Complexsqrt がなさそう🙁 import Numerics let a: Complex<Double> = -1 let i: Complex<Double> = .sqrt(a) print(i) (edited)
Avatar
↓で遊べたけど誤差が・・・ import Numerics extension Complex { static func *(lhs: Self, rhs: RealType) -> Self { return Self(lhs.real * rhs, lhs.imaginary * rhs) } static func *(lhs: RealType, rhs: Self) -> Self { return Self(lhs * rhs.real, lhs * rhs.imaginary) } } extension Complex where RealType: ElementaryFunctions { static func sqrt(_ z: Self) -> Self { let length = z.length let phase = z.phase return .sqrt(length) * Self(.cos(phase / 2), .sin(phase / 2)) } } let a: Complex<Double> = -1 let i: Complex<Double> = .sqrt(a) print(i) (6.123233995736766e-17, 1.0)
8:17 AM
お、すでに提案されてる。 https://github.com/apple/swift-numerics/issues/2
All of the usual ElementaryFunctions operations should be defined for Complex types. Implementation details may be found in Kahan&#39;s &quot;Branch Cuts for Complex Elementary Functions; o...
8:19 AM
というか、初期の実装から外しただけか。
Avatar
Complex使ってるライブラリを置き換えようかと思ったんですがまだタグ一個も切られてないんですね。時期尚早か。
Avatar
https://github.com/apple/swift-numerics/blob/master/Sources/Complex/Arithmetic.swift ComplexSignedNumericじゃないんですね。 https://developer.apple.com/documentation/swift/signednumeric
The SignedNumeric protocol extends the operations defined by the Numeric protocol to include a value’s additive inverse.
定義的には適合しそうですがどうなんでしょう。
Numerical APIs for Swift. Contribute to apple/swift-numerics development by creating an account on GitHub.
Avatar
https://developer.apple.com/documentation/swift/signednumeric The SignedNumeric protocol extends the operations defined by the Numeric protocol to include a value’s additive inverse. AFAICS Compl...
Avatar
omochimetaru 11/9/2019 2:27 AM
無言だ・・・
Avatar
Hello Swift community, The review of SE-0271 “Package Manager Resources" begins now and runs through November 19, 2019. Reviews are an important part of the Swift evolution process. All reviews should be made in this thread on the Swift forums or, if you would like to kee...
12:11 AM
やっと#fileから取るのから脱却できる
Avatar
おお!正規レビュー入ったか!
Avatar
Hello Swift community, The review of SE-0272 “Package Manager Binary Dependencies" begins now and runs through November 20, 2019. Reviews are an important part of the Swift evolution process. All reviews should be made in this thread on the Swift forums or, if you would l...
3:25 AM
バイナリのほうも来ましたね
❤ 1
Avatar
おおっ、マジか! チェックしなきゃ!
Avatar
Software vendors who wish to provide easy integration with the package manager, but do not deliver source code, cannot integrate.
↑これはまあわかるし広告SDKに苦しむ各位が喜ぶと思うけど
4:16 AM
Someone wants to create a Swift package for generating LLVM code. However, LLVM's build process is far more complex than can be currently fit into SwiftPM's build model. This makes building an easy to use package difficult.
4:16 AM
↑この発想は無かった!w
Avatar
https://forums.swift.org/t/operator-member-syntax/31773/11 コンパイラ弱者なので分かってないのですがトップレベルのオペレータ関数とstaticなオペレータ関数でコンパイラ内部での扱いは違うんでしょうか? ユーザーが見る分には今の所同じですよね? (edited)
Good question. Operator member syntax is relevant only for operators declared as static methods of a particular type, not for operators declared as top-level functions. infix operator +++ // This operator is a top-level function, not a member of any type. func +++(_ x: Int,...
2:10 AM
提案されている内容はstaticなオペレータ関数はその型のメンバーとしてアクセスできるようにするってことですが、現状定義を見ないとstaticなのかトップレベルなのか分からないのでユーザーからすると不便な気がしています。 (今の所定義によって挙動が変わらないので二種類の定義方法があってもユーザーに不便はない) (edited)
Avatar
知らんけど同じだと思ってる
2:28 AM
別にこれは参照する方法を追加するだけで
2:28 AM
今より不便になる点は無いのでは?
Avatar
追加的な機能なので不便にはならないですが、この機能を使う人からすると不便じゃないかと思ってます。
2:30 AM
一般の関数の場合staticなのかトップレベルなのかはかんたんに見分けられますがオペレータ関数の場合定義もとに行かないと分からない
Avatar
一般の関数の場合見分けられるのは、返り値の型でわかるから?
Avatar
staticの場合外部からの呼び出しでは型名が要求されるからですね
Avatar
型名がない場合同士で比較しないと話が変では
Avatar
static関数からstatic関数を参照する場合は一応ありますね。 (edited)
Avatar
いや
2:32 AM
ドット記法
Avatar
あ、あー
2:32 AM
それは確かに
Avatar
SwiftPMとかだと使いまくるし普段も.some書くでしょ
2:33 AM
あれと同じ話だと思う。
2:34 AM
ドット記法は返り値の型が定義してる型同じ時だけ使えるけど
2:34 AM
もし複数の型に同じstatic funcがあるときは
2:34 AM
ドット記法だったら推論次第で呼び出しが変わるから
2:34 AM
オペレーターと同じだと思う
2:35 AM
オペレーターは名前が被りまくってるからわかりにくくなりやすいけど、 同じ分かり難さはすでにstatic funcにもある。
Avatar
@swiftbot func f(_ x: X) -> X { print("top-level") return x } struct X { static func f(_ x: X) -> X { print("static") return x } } let x = X() let _: X = .f(x) // static
🛠 1
Avatar
Author icon
t.ae
func f(_ x: X) -> X { print("top-level") return x } struct X { static func f(_ x: X) -> X { print("static") return x } } let x = X() let _: X = .f(x) // static
Version:
swift-5.1-RELEASE
Output:
static
Error:
Avatar
@swiftbot func f(_ x: X) -> X { print("top-level") return x } struct X { // static func f(_ x: X) -> X { // print("static") // return x // } } let x = X() let _: X = .f(x)
🛠 1
Avatar
Author icon
t.ae
func f(_ x: X) -> X { print("top-level") return x } struct X { // static func f(_ x: X) -> X { // print("static") // return x // } } let x = X() let _: X = .f(x)
Version:
swift-5.1-RELEASE
Output:
Error:
/usercode/main.swift:14:13: error: type 'X' has no member 'f' let _: X = .f(x) ~^~~~
Avatar
>ドット記法だったら推論次第で呼び出しが変わるからオペレーターと同じだと思う ドット記法って左辺型のstaticメンバが呼び出される仕様じゃなかったですっけ?
2:42 AM
@swiftbot struct X {} struct Y { static func f(_ x: X) -> X { print("Y") return x } } let x = X() let _: X = .f(x)
🛠 1
Avatar
Author icon
t.ae
struct X {} struct Y { static func f(_ x: X) -> X { print("Y") return x } } let x = X() let _: X = .f(x)
Version:
swift-5.1-RELEASE
Output:
Error:
/usercode/main.swift:11:13: error: type 'X' has no member 'f' let _: X = .f(x) ~^~~~
Avatar
ん、なんか文章読み間違ってますね。こんがらがってきた
Avatar
XとY の両方にstatic func fがあったら
2:50 AM
.fって式が曖昧になることはある
2:51 AM
で、それは、オペレーターが定義されてる型がわからないのと同じ。
Avatar
ありますか?_: X = .f(x)だったらXの方で解決されますよ
Avatar
例えば関数の引数だったら
2:51 AM
見てもわからない
2:52 AM
ん?解決できるかどうかじゃなくて
2:53 AM
人間が見てもわかりにくいって話を
2:53 AM
したいんだよね?
Avatar
そうですね。前提からこんがらがってきてます。
Avatar
static関数でドット記法の場合、受ける型さえわかればその場でどれを参照しているのかが分かる。 一方オペレータ関数の場合はそれがトップレベル/staticどちらで定義されているかのヒントは記述からは得られないため、定義元を見に行く必要がある。 というのが不便じゃないかというのが僕の言いたいことですね。
3:05 AM
でこれは結局オペレータ関数の記法に2つのオプションがあること、かつ(知ってる限りでは)どちらを使うのが好ましいというような指針もないことが問題な気がしてきました。
Avatar
というのが不便じゃないか
これはすでにある性質であって、今回の提案とは関係ない話じゃ?
(edited)
3:11 AM
今回の提案は、「わかってる場合に指定できる」というものであって。
3:11 AM
現状では、わかってても指定できない。
Avatar
そうですね。分からない場合に定義を見に行く必要があると書きましたがその手間を経て分かっている場合に指定できるという点は良いと思います。
Avatar
omochimetaru 1/14/2020 1:42 AM
Hello Everyone, I am the author of the thesis Swift for Embedded Systems mentioned in this thread. After a long time, I finally got back to working on it so I would like to share some progress with you 🙂 It is still in an early phase, but I am currently not aware of any...
1:43 AM
Swiftの組み込み対応してた人がソース公開した
1:44 AM
thumbv7mに対応してるらしい
1:45 AM
次はSTM32F439ZIをやるみたい
Avatar
やっぱりバイナリサイズがネックらしいですね
Avatar
omochimetaru 1/14/2020 2:19 AM
単純に小さい標準ライブラリを作るしか無いよねえ?
Avatar
メインプログラム側で使ってないstdlibの関数をストリップする方法があれば良いんじゃないですかね
Avatar
omochimetaru 1/14/2020 2:21 AM
う〜んそうか、それがきれいだね
Avatar
動的にキャストされる可能性をSwiftレベルで検証して、stdlib側のPWTを消し去る
Avatar
omochimetaru 1/14/2020 2:21 AM
動的な型情報経由のアクセスとかがあるから、
2:22 AM
リンカーレベルではできなくて
2:22 AM
Swiftコンパイラレベルで型の利用関係を抽出する必要がありそう
Avatar
モジュール内では必要な時だけメタデータを出力するような作りになってるっぽい
2:24 AM
@helje5 @compnerd Sorry, I misunderstood. The compiler only emits metadata records by need. In WMO, if nothing uses the class, then nothing should be triggering its emission to begin with
Avatar
omochimetaru 1/14/2020 2:32 AM
あ〜、それはそうだよね、LLVM-IRとか見てると。
2:32 AM
ああそうか、だから、仕組みとしては存在しているけど
2:32 AM
一つのモジュール(ソースファイル?)をビルドする単位での話で
2:33 AM
一度ビルドしちゃったモジュールをリンクする時にそういうのがないって話なのかな
Avatar
そうですねー
Avatar
omochimetaru 1/14/2020 3:04 AM
The compiler only emits metadata records by need.
↑ここの仕組みってLLVM側っぽい感じがしているけどどうなんかなあ
3:05 AM
あ〜いや、そんな事無いかも・・・
3:05 AM
IRGen::emitLazyXXXX系ってこのためにあるデザインかも
Avatar
あー、どうなんだろう… メタデータって大抵llvm irレベルでDCEしないでくれアトリビューションがついてる気がする (edited)
Avatar
omochimetaru 1/14/2020 3:06 AM
IRGenの中身ってとにかくひたすら getCachedResultOrEmit みたいなものを経由するようになってて
3:06 AM
その返り値が llvm::Value * なんだよね
Avatar
なるほどなるほど
Avatar
omochimetaru 1/14/2020 3:07 AM
出発点としてソースファイルのtop level functions/typesに対してループして
3:07 AM
コード生成時に細かいSILType とか出会うたびにそれが呼ばれるから
3:07 AM
そんときにその場でemitしたり、lazyEmit登録しておいたりして
3:07 AM
最後にlazy登録された奴らのemitが来る
3:08 AM
なんかそれで使うものだけ吐く形になる気がしてきた
Avatar
だから出力しないのとシンボル削除する機能は全く別の機構が必要なのか
Avatar
omochimetaru 1/14/2020 3:08 AM
あ、そうだね、今の話はリンクタイムは全く使えんな・・・
Avatar
たしか今年のLLVM MTGでSwiftのLTOの話があった気がする
Avatar
omochimetaru 1/14/2020 3:09 AM
マジ
3:10 AM
Link Time Optimization For Swift - Jin Lin [ Video ] [ Slides ]
3:10 AM
Those unused code and data cannot be eliminated easily by the compiler optimizations since they are recorded in llvm.used data structure
3:10 AM
We introduce a novel building pipeline that eliminates the protocol from swift class by leveraging the link time optimization in existing LLVM compiler
3:10 AM
ほんとだw
Avatar
まさにこれだ
Avatar
omochimetaru 1/14/2020 3:11 AM
The experiment shows that this novel approach reduces the code size of some commercial iOS app by 2%.
3:11 AM
後で見る
7:43 AM
↑急に来た感
7:44 AM
pitchはここか
Avatar
Enum cases as protocol witnesses Proposal: SE-XXXX Author: Suyash Srijan Review Manager: [TBD] Status: Awaiting Review Implementation: apple/swift#28916 Bug: SR-3170 Introduction Allow enum cases to satisfy static protocol requirements. Swift-evolution thread: Enum ca...
2:34 AM
pitch が来た😍
Avatar
omochimetaru 1/23/2020 2:15 PM
@koher
Swift 6 での Windows サポートあるんじゃないの?
Apple公式にWindows版の保守する可能性出てきましたね
Avatar
Apple というか、 Swift 公式じゃない?
2:16 PM
compnerd さんは Google の人っぽい。
2:16 PM
Chris Lattner も Google だし、 Core Team も Apple 一色じゃなくなってきた。
Avatar
omochimetaru 1/23/2020 2:17 PM
あれ、compnerdさんFacebookじゃなかったっけ
Avatar
2019 年から Google になってる。
Avatar
omochimetaru 1/23/2020 2:17 PM
そうだったのか
Avatar
お、先月からだ。
Avatar
omochimetaru 1/23/2020 2:17 PM
S4TFのWindowsサポートの話題もちょろっと見かけたし両方やってそうだな
Avatar
先月まで Facebook で、今月から Google
2:18 PM
Refine Swift’s implementation and capabilities to allow it to be used for low-level systems programming (or in constrained environments) and in important domains like services and machine learning
2:19 PM
S4TF も意識されてそう。
Avatar
omochimetaru 1/23/2020 2:20 PM
ほんとだ〜
2:20 PM
先月ってことはこの間のLLVM MTGで登壇したときはFacebookか
Avatar
Ownership, Concurrency, Variadic Generics, Windows サポートって実現したら Swift 6 すごすぎない?
2:21 PM
ABI 安定化も終わってようやく本当の Swift 1.0 って感じだね。
Avatar
omochimetaru 1/23/2020 2:21 PM
あと、Battery Included的なこともやりたいみたいですね
2:22 PM
最近StdLibのBeta Packageの話もしてるし。
Avatar
あー書いてあったね
Avatar
omochimetaru 1/23/2020 2:23 PM
うーんスゴイというか、最低限が揃うという感じ・・・
Avatar
Some examples of the latter include cultivating the critical ingredients needed for using Swift for developing services as well as libraries like Swift Numerics which are essential for a variety of use cases ranging from scientific computing to machine learning.
2:23 PM
いや、これまでの ABI 安定化中心でなかなか進まなかった色んなものが一気に進む感じ。
Avatar
omochimetaru 1/23/2020 2:23 PM
そうですね。1.0感はありますね。
Avatar
Concurrency って async/await だけじゃなく actor までいくかな?
2:24 PM
actor までいけば Logic Failure をハンドリングできるようになるかも。
Avatar
omochimetaru 1/23/2020 2:24 PM
うーん、async/awaitしばらく使ってみてから議論しようみたいになりそう
Avatar
あー個人的には Reverse Generics を進めてほしい。
Avatar
omochimetaru 1/23/2020 2:25 PM
スレッドの感じだと
2:25 PM
ニーズを提示しないと進みそうにないですね
2:25 PM
Adrian Meisterさんが
2:25 PM
Generics系いろいろ進めようぜ〜みたいに書き込んでるけど
2:26 PM
Joe Groffのレスみてると。
2:26 PM
VariadicGenericsだけ具体的に書かれてるのはSwiftUIのAPIがヤバい事になってるからだと思う。
2:26 PM
10個までしか並べられない。
Avatar
Opaque 型パラサポートもしないと Opaque Type も中途半端だけど、それできても Reverse Generics ないと↓とかできなくない?普通に機能足りてないと思うんだけど・・・。
Avatar
omochimetaru 1/23/2020 2:27 PM
Cristian Garcia This. Resorting to the Any* erasure types feels wrong. This should be fixed.
↑コレは本当にそうなので parameterized existentialは進んだらいいなあ。
Avatar
func makeAnimalPair() -> <A: Animal> (A, A) { ... }
Avatar
omochimetaru 1/23/2020 2:28 PM
できないのはそうで、それをやりたくなった具体的なシナリオで説得する必要がありそうな雰囲気を感じる。
Avatar
うーん。 Opaque 型パラはやる感じなのかな?そっちはイテレータ隠蔽にいるし。
2:30 PM
ああ違う
2:30 PM
Foo<some Animal>some Animal<.Foo == Bar> は別の話だった
Avatar
omochimetaru 1/23/2020 2:30 PM
Combineでerasure使うところ、assoctype対応したORTが欲しそうな気はする
Avatar
どっちもほしいけど、イテレータは後者だ。
2:32 PM
あと any も進めてほしいなぁ。 any はシンタックスだけの話だから対応は一番簡単だと思う。
Avatar
omochimetaru 1/23/2020 2:34 PM
実装するものは結構たくさんあると思いますよ
Avatar
Generalized Existential じゃなくて、 Existential に any 必須にするだけで?
Avatar
omochimetaru 1/23/2020 2:35 PM
ああ〜、そっちか。
Avatar
パーサだけの話じゃないの?コンバータもあるかもだけど。 (edited)
2:39 PM
Type Erasure 不毛すぎるからいいかげん Generalized Existential もほしい気もするけど、これから新しいプラットフォームに広げるならプロトコルのインタフェース化を防ぐためにしばらくなくてもいい気もする・・・。
2:40 PM
まあでも Self-conformance がないから、 Generalized Existential があってもインタフェース的には使えないか。
2:40 PM
any Sequence<.Element == Int> 型引数に any Sequence<.Element == Int> を渡せないし。 (edited)
Avatar
omochimetaru 1/23/2020 2:41 PM
あー
2:41 PM
いや、なので、そこは
Avatar
some Sequence<.Element == Int> なら渡せるのおもしろいな。
Avatar
omochimetaru 1/23/2020 2:42 PM
Generalizedを入れるタイミングで、Self-conformanceは
2:42 PM
ユーザ定義できるようにすべきですね
2:42 PM
extension any Equatable: Equatable { static func ==... }
Avatar
ユーザ定義はできるようにするとしても、標準ライブラリで any SequenceSequence 準拠するかな?
Avatar
omochimetaru 1/23/2020 2:43 PM
AnySequenceは今も is Sequenceですよね
2:43 PM
それにstatic memberが無いからself-coformanceの実装は自明だと思う (edited)
Avatar
うん、でも AnySequenceSubSequence も決まってるしなー。
2:43 PM
AnyCollection とか Index まで決まってるし。
Avatar
omochimetaru 1/23/2020 2:44 PM
それは、選べなきゃいけなくて
2:44 PM
any Sequence<Element = Int>any Sequence<Element = Int, SubSequence = Array<Int>>
2:44 PM
別の型だと思う。 (edited)
2:45 PM
あーでもプロトコル準拠するなら全部埋めなきゃいけないのか。
2:45 PM
あ、でも、AnySequenceはそうなってるか。
Avatar
あれ?
Avatar
omochimetaru 1/23/2020 2:45 PM
今のAnySequenceはSubSequenceもAnySequenceだから
Avatar
SubSequenceCollection
2:45 PM
この前も勘違いしたんだった
2:46 PM
SequenceIteratorElement しか持ってないんだった。
Avatar
omochimetaru 1/23/2020 2:46 PM
あれ、そうだっけ。それならまあそっちはOKだ。
2:46 PM
typealias AnySequence<E> = any Sequence<Element = T, SubSequence = any Sequence... // ←ここが再帰すると書けないな? (edited)
2:47 PM
この辺りとか SubSequence 出てこない。
2:47 PM
じゃあ Collection の話として
2:48 PM
let c: any Collection<.Element == Int> = [2, 3, 5] let sc = c[1...]
2:48 PM
このとき sc の型はどうなるの?
2:49 PM
any Collection<.Element == Int> (edited)
Avatar
omochimetaru 1/23/2020 2:49 PM
AnyCollection.SubSequenceAnyCollection だから
2:50 PM
えっとまず、僕の考えだと
2:50 PM
↑のコードについては、 scの型は SubSequenceを指定してないから、 Any になるか、コンパイルエラーのどっちか。
2:50 PM
いや、 some Collection かも。
2:51 PM
一番理論的に正しいのは some Collection じゃないかしら?
Avatar
some は無理じゃない?
2:51 PM
c の型が実行時にしか決まらないから
Avatar
omochimetaru 1/23/2020 2:51 PM
あ、何が入るかわからないか。
Avatar
うん
Avatar
omochimetaru 1/23/2020 2:51 PM
じゃあ正しいのはコンパイルエラーだけど
2:51 PM
現状のAnyCollectionに寄せるのであれば
2:51 PM
get操作はAnyとして取れるけど
2:51 PM
set操作をした場合は暗黙のダウンキャストが挿入されて
2:51 PM
型不一致ならクラッシュかな?
Avatar
associatedtype SubSequence : Collection = Slice<Self> where Self.Element == Self.SubSequence.Element, Self.SubSequence == Self.SubSequence.SubSequence
2:52 PM
Any まではいかなくて、↑にマッチする最も抽象的な型?
Avatar
omochimetaru 1/23/2020 2:52 PM
指定していない associatedtypeについては Never を指定したことにして呼び出せないっていうのが良いんじゃないか
2:52 PM
あ〜、そうですね、それにマッチするExistentialにできるかな?
2:53 PM
でもやっぱりsetしたときにダウンキャストが必要だなあ。内部では真の型があるのだから。
Avatar
あー
Avatar
omochimetaru 1/23/2020 2:53 PM
あれーやっぱりsomeにできませんかね?
Avatar
covariant position と contravariant position で
Avatar
omochimetaru 1/23/2020 2:53 PM
この場合、identityがlet c に束縛されたsomeです。
Avatar
どっち側に振れるかが逆になるのかな?
2:54 PM
contravariant position だと Never 側?
Avatar
omochimetaru 1/23/2020 2:55 PM
var c だったら、再代入のたびに identityが変わる。
Avatar
protocol Foo { associatedtupe X var x: X { get set } }
2:57 PM
var foo: any Foo = ... let x = foo.x foo.x = ...
2:57 PM
↑で考えると、コンパイル通るなら x の型は Any で、 set のときは Never じゃないといけないよね?
Avatar
omochimetaru 1/23/2020 2:58 PM
厳しくいくならそうだと思います、つまり代入できない。
Avatar
protocol Foo { associatedtupe X: Bar var x: X { get set } } var foo: any Foo = ... let x = foo.x これなら xany Bar でいける。
Avatar
omochimetaru 1/23/2020 2:59 PM
やっぱり x の型は 空の some  じゃないですかね?
3:00 PM
var foo に対しての some。
3:00 PM
get foo.xset foo.x は、同じ型 同じだけど具体的に見えないから some。
3:00 PM
var x に再代入があったら、そこから仕切り直し。
Avatar
そこを some にしようとすると x の型をコンパイル時に決定しないといけないんじゃない?
Avatar
omochimetaru 1/23/2020 3:00 PM
いいえ
3:00 PM
some は、コンテナに入ってますよ。
3:01 PM
真の型がわかるときは最適化して置換できるだけで
3:01 PM
実行表現としてのsomeは <T> とかと同じです。
Avatar
いや、やっぱおかしくて
Avatar
omochimetaru 1/23/2020 3:01 PM
そうでないと、ABI互換を保ちながらライブラリの返す真の型を後のバージョンで変えられない。
Avatar
var foo: any Foo = Foo1() let x = foo.x foo = Foo2() foo.x = x
3:02 PM
↑ができちゃだめだから
3:02 PM
setNever じゃないと。
Avatar
omochimetaru 1/23/2020 3:03 PM
いいえ、それはできないんです
Avatar
foosome なら get して set できていいけど、 any だからインスタンスから差し替えられる。
Avatar
omochimetaru 1/23/2020 3:03 PM
foo = Foo2() の行がある時点で
3:03 PM
その行より後ろの foo は別のidentityであることが静的に解析できるから。
Avatar
えー、同じ foo.x の型が変わっちゃだめじゃない?
Avatar
omochimetaru 1/23/2020 3:04 PM
var foo: any Foo = Foo1() let x = foo.x foo = Foo2() foo.x = x ↑これは↓のような解釈 let foo_1: any Foo = Foo1() let x = foo_1.x let foo_2 = Foo2() foo_2.x = x // foo_2.Xとfoo_1.Xは違う型だからコンパイルエラー
Avatar
それよりも setNever 扱いの方が自然だと思うけど。
3:05 PM
同じ var の型が変わるというのは変だと思う。
Avatar
omochimetaru 1/23/2020 3:06 PM
でも、そもそも existential が、
3:06 PM
型を値レベルで閉じ込める仕組みだから
3:06 PM
値単位で型が変わるのは理論的に正しいと思う
3:06 PM
仕様としてわかりにくいからやめとこうっていう意見はわかりますけど。
3:07 PM
ただその場合、現状のAnyCollectionで可能な var c: AnyCollection<Int> = foo() print(c[c.startIndex])
Avatar
値の型がわからなくてもうまく動くように型システムが働くのが自然だと思うけどなぁ。
Avatar
omochimetaru 1/23/2020 3:07 PM
↑これができるようになる理屈を用意しないといけないですね
3:07 PM
contravariant positionがNeverなのであれば subscript get ができなくなっちゃうから。 (edited)
3:08 PM
で、現状のAnyCollectionには問題があって
Avatar
上界・下界とも決められる仕組みが必要なのかな?
Avatar
omochimetaru 1/23/2020 3:08 PM
var c: AnyCollection<Int> = foo() let s = c.startIndex print(c[s]) // 絶対OK c = goo() print(c[s]) //クラッシュしうる (edited)
3:08 PM
↑こういう問題があるんです
3:09 PM
で、僕のさっきのアイデアだと、これを正しく、 絶対OKの方はコンパイルできて、クラッシュしうる方はコンパイルできない
3:09 PM
って型チェックができる。
Avatar
うーん、 Type Erasure はワークアラウンドだし、必ずしも Existential がそれを踏襲しなければいけないわけじゃないと思うけど。
3:11 PM
any Collection<.Element == Foo, .Index == Int> とかでもいいわけだし。
Avatar
omochimetaru 1/23/2020 3:13 PM
それはそれで、出来たほうが良いと思います
3:13 PM
そうじゃないと、もし↑のsomeの案だと、 たとえIndexが同じであっても、コンパイルエラーになっちゃうから、
3:13 PM
.Index == Int の指定があるなら、再代入の前後でIndexに型互換性があることをチェックできる。
3:14 PM
.Index == Hoge の指定を省略した時の挙動を考えてました。
Avatar
protocol Foo { associatedtype X: Bar where Baz: X var x: X { get set } }
3:14 PM
うん、で、省略したときは Index が contravariant position で Never になっちゃうのでいいんじゃない?ってこと。
Avatar
omochimetaru 1/23/2020 3:14 PM
あれ、そこにwhere付けられましたっけ。
Avatar
コンパイラクラッシュしたw
Avatar
omochimetaru 1/23/2020 3:15 PM
oh・・・
Avatar
↑が書ければ、 Never まで飛ばずに contravariant position を any Baz にとどめられる。
Avatar
omochimetaru 1/23/2020 3:15 PM
ちょっと、where無しで、書いてもらえますか、書きたかった意図が読み取れない (edited)
Avatar
Baz: X: Bar って関係ってこと
3:16 PM
Baz < X < Bar って書いた方がいいかな?
3:16 PM
Never < Baz < X < Bar < Any
3:17 PM
上界と下界を指定できて (edited)
Avatar
omochimetaru 1/23/2020 3:17 PM
うーん、それやっても、
3:17 PM
getで返ってくるのが any Bar で
3:17 PM
setで要求するのがany Bazだから
Avatar
うん
Avatar
omochimetaru 1/23/2020 3:17 PM
どっちにしろ、取ったものを渡せないですよね?
Avatar
うん
3:17 PM
上界と下界が一致するとき(つまり == )だけ
Avatar
omochimetaru 1/23/2020 3:17 PM
型安全性にするならそれでいいけど
Avatar
get したものを set できる。
Avatar
omochimetaru 1/23/2020 3:17 PM
AnyCollectionみたいに実行時クラッシュはするけど
3:17 PM
「正しいときは実行できる」ほうがいいきもする。
Avatar
いや、 AnyCollection はデフォルト型パラがなかったから、しかたなく型パラを制限してるだけで
Avatar
omochimetaru 1/23/2020 3:18 PM
コンパイルエラーだと、実際に正しいコード let c: any Collection<E = Int> = foo() print(c[c.startIndex]) これすら使えなくなっちゃう (edited)
Avatar
本当はすべての associatedtype を型パラに持ってた方が良かったと思うんよね。
3:19 PM
get して set が必要なときは指定すればいいんだから。
Avatar
omochimetaru 1/23/2020 3:19 PM
let c: any Collection<E = Int, I = Int> = foo() print(c[c.startIndex]) ↑こうしろって事ですか?
Avatar
うん。
Avatar
omochimetaru 1/23/2020 3:19 PM
ふ〜む。なるほど・・・
3:20 PM
書くのがめんどくさそうだけど正しくはありますね。
Avatar
うん、めんどうだけど、 Existential にそれくらいのペナルティあってもちょうど良さそう。
3:21 PM
多用するときは typealias だって書けるわけだし。
Avatar
omochimetaru 1/23/2020 3:23 PM
上界と下界が一致するとき(つまり == )だけ
これってありえますかね
3:24 PM
うーんありえるか?意味的に変な気がしたけど
Avatar
@swift-5.1.5 class C1 {} class C2: C1 {} class C3: C2 {} protocol Foo { associatedtype X: C1 where C3: X var x: X { get set } }
Avatar
exit status: 134 with stderr:swift: /home/buildnode/jenkins/workspace/oss-swift-5.1-package-linux-ubuntu-16_04/llvm/include/llvm/Support/Casting.h:255: typename cast_retty<X, Y *>::ret_type llvm::cast(Y *) [X = swift::DependentMemberType, Y = swift::TypeBase]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed. Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -I /Libraries/.build/x86_64-unknown-linux/debug -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOAtomics/include -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include -I /Libraries/.build/checkouts/OpenCombine/Sources/COpenCombineHelpers/include -module-cache-path /Libraries/.build/x86_64-unknown-linux/debug/ModuleCache -D DEBUG -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOAtomics.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/COpenCombineHelpers.build/module.modulemap -module-name main -lLibraries 1. While type-checking 'Foo' (at <stdin>:5:1) 2. While validating 'Foo' (at <stdin>:5:1) /usr/bin/swift[0x493d544] /usr/bin/swift[0x493b160] /usr/bin/swift[0x493d968] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7fe4b6470390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7fe4b4995428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7fe4b499702a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7fe4b498dbd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7fe4b498dc82] /usr/bin/swift[0x1447f41] /usr/bin/swift[0x1447cef] /usr/bin/swift[0x1458fb0] /usr/bin/swift[0x144c03f] /usr/bin/swift[0x1470c04] /usr/bin/swift[0x14ce5b9] /usr/bin/swift[0x1455f72] /usr/
Avatar
omochimetaru 1/23/2020 3:24 PM
多用するときは typealias だって書ける
まあそうかあ
3:25 PM
erausreを自作する代わりにちょっと面倒なtypealiasを書くならだいぶ楽。
Avatar
erasure自作してると、generalized existentialないのおかしいだろって気持ちになるもんねw
Avatar
omochimetaru 1/23/2020 3:28 PM
ボイラープレートもいいところですからねえ
3:30 PM
@swiftbot protocol P{} protocol Q { associatedtype P: X }
Avatar
swiftbot BOT 1/23/2020 3:30 PM
Author icon
omochimetaru
protocol P{} protocol Q { associatedtype P: X }
Version:
swift-5.1.3-RELEASE
Output:
Error:
/usercode/main.swift:3:21: error: use of undeclared type 'X' associatedtype P: X ^
Avatar
omochimetaru 1/23/2020 3:30 PM
あーそっか、最初に名前が来るから、lower boundの書きようが無いのか
Avatar
うん、なので where
Avatar
omochimetaru 1/23/2020 3:32 PM
@swiftbot protocol P1 {} protocol P2 {} protocol Q { associatedtype X where X: P1, X: P2 }
Avatar
swiftbot BOT 1/23/2020 3:32 PM
Author icon
omochimetaru
protocol P1 {} protocol P2 {} protocol Q { associatedtype X where X: P1, X: P2 }
Version:
swift-5.1.3-RELEASE
Output:
Error:
Avatar
omochimetaru 1/23/2020 3:32 PM
名前だけ書いてwhereで条件付けるのはいいのか。
Avatar
@swift-5.1.5 class C1 {} class C2: C1 {} class C3: C2 {} protocol Foo { associatedtype X where C3: X var x: X { get set } }
Avatar
exit status: 134 with stderr:swift: /home/buildnode/jenkins/workspace/oss-swift-5.1-package-linux-ubuntu-16_04/llvm/include/llvm/Support/Casting.h:255: typename cast_retty<X, Y *>::ret_type llvm::cast(Y *) [X = swift::DependentMemberType, Y = swift::TypeBase]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed. Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -I /Libraries/.build/x86_64-unknown-linux/debug -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOAtomics/include -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include -I /Libraries/.build/checkouts/OpenCombine/Sources/COpenCombineHelpers/include -module-cache-path /Libraries/.build/x86_64-unknown-linux/debug/ModuleCache -D DEBUG -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOAtomics.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/COpenCombineHelpers.build/module.modulemap -module-name main -lLibraries 1. While type-checking 'Foo' (at <stdin>:5:1) 2. While validating 'Foo' (at <stdin>:5:1) /usr/bin/swift[0x493d544] /usr/bin/swift[0x493b160] /usr/bin/swift[0x493d968] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f433d746390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f433bc6b428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f433bc6d02a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7f433bc63bd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7f433bc63c82] /usr/bin/swift[0x1447f41] /usr/bin/swift[0x1447cef] /usr/bin/swift[0x1458fb0] /usr/bin/swift[0x144c03f] /usr/bin/swift[0x1470c04] /usr/bin/swift[0x14ce5b9] /usr/bin/swift[0x1455f72] /usr/
Avatar
lower bound だけで死ぬ
Avatar
omochimetaru 1/23/2020 3:34 PM
報告だ
Avatar
lower boundsで調べてもそれっぽいバグレポないね
Avatar
omochimetaru 1/23/2020 3:42 PM
検索してみたけど、無さそう
3:42 PM
すごいシンプルだけど普通やらないからマジで誰も気づいてないのでは
Avatar
$ cat lower.swift class C1 {} class C2: C1 {} protocol Foo { associatedtype X where C2: X } $ swiftc lower.swift Stack dump: ... <unknown>:0: error: unable to execute command: Segmentation fault: 11 <unknown>:0: error: compile command failed due to signal 11 (use -v to see invocation) (edited)
Avatar
omochimetaru 1/23/2020 3:44 PM
離席します
3:58 PM
自分のバグチケット一覧見てるとなんでこんな変なコーナーケースばっかり突いてるのかという気持ちになるな・・・。コーナーだからバグが見つかるんだろうけど。
Avatar
Scala だと :> 使って簡単に lower bound を書けるのかぁ。 class A {} class B extends A {} trait T[-X >: B] { def bar(x: X): Unit } class C extends T[A] { def bar(x: A): Unit = { println("C.bar: " + x) } } val c: C = new C() val t: T[B] = c t.bar(new B())
4:13 PM
C.bar: Playground$B@16418d1a
Avatar
@swift-5.0.3 class C1 {} class C2: C1 {} protocol Foo { associatedtype X where C2: X }
1:26 AM
お、ほんとだ。 Swift 5 だと通る。
Avatar
This looks like a regression because we used to correctly diagnose this in Swift 5, but since 5.1 this is crashing.
Avatar
omochimetaru 1/24/2020 1:36 AM
テストケース漏れてて壊れしちゃったやつでしたね
Avatar
we used to correctly diagnose this in Swift 5
テストケースないのにどうやって "diagnose" したんだろう?
Avatar
omochimetaru 1/24/2020 1:38 AM
このdiagnoseは
1:38 AM
optimize and diagnose のコンパイラ用語の方のdiagnoseじゃないですか?
1:39 AM
あれ、でも普通に5でも通るのか
1:39 AM
エラーが出たりして結局できないよって話かと思った
Avatar
error: type 'C2' constrained to non-protocol, non-class type 'Self.X'
Avatar
omochimetaru 1/24/2020 1:42 AM
@swift-5.0.3 class C1 {} class C2: C1 {} protocol Foo { associatedtype X where C2: X } print(1)
Avatar
swift-5.0.3 ボットが死んでる?
Avatar
omochimetaru 1/24/2020 1:42 AM
そういうことかwややこしい
1:43 AM
rintaroさんはどうやって5系を叩いたんですか
1:43 AM
Xcodeたくさん入れてる?
Avatar
10.3 が手元にインストールされてます。
Avatar
omochimetaru 1/24/2020 1:44 AM
1:45 AM
なるほど。見てみたら僕も10.2もってたわ。
1:45 AM
じゃあやっぱり、さっきのコメントの英文の diagnose は↑のエラーメッセージが出ることを
1:45 AM
指しているんじゃないかしら。
Avatar
ボット落ちてたのか・・・
Avatar
omochimetaru 1/24/2020 1:48 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
なるほど < diagnose
Avatar
omochimetaru 1/24/2020 1:48 AM
↑似たようなやつはあるけど、同じのはないな。
Avatar
"non-class type" は、 X: AnyObject でもダメなのかな? X 自体はクラスじゃないしダメ?
Avatar
omochimetaru 1/24/2020 1:51 AM
これ右側が駄目なんですね
1:51 AM
C: P の右側のPはプロトコルじゃないといけないから ←これは誤りか (edited)
1:51 AM
associatedtype自体を コロンの右に書く時点で駄目なんだ
1:53 AM
1:53 AM
だめらしい
1:53 AM
微妙に変な気がするけどw
1:54 AM
: AnyObject なら絶対クラスだよな。文言からすると protocol じゃないのが駄目なのか? (edited)
1:54 AM
でも X: C は書けるしな。
1:55 AM
う〜ん??
Avatar
omochimetaru 1/24/2020 2:03 AM
ジェネリックパラメータに対してlower-boundが書ける場面ってもしかして無い??
2:04 AM
コロンの左右反転で書けるつもりになってたけど実は書いたことがない気がしてきた
Avatar
書けなさそうな気がする。
Avatar
omochimetaru 1/24/2020 2:07 AM
アハ体験
Avatar
書く機会はないけど、クロージャ型で引数の contravariance とか考えると、書けないとできないユースケースありそう。
Avatar
omochimetaru 1/24/2020 2:08 AM
関数型同士の間ではちゃんと効くんですよね
Avatar
昨日の未指定 associatedtype は仮定の話だけど、クロージャ型は現実の課題。
Avatar
omochimetaru 1/24/2020 2:09 AM
そうか、だから、ジェネリック型にそもそもvarianceがないからか?
Avatar
@swift-5.1.5 class C1 {} class C2: C1 {} func foo<X>(_ x: X) where C2: X {}
Avatar
exit status: 1 with stderr:<stdin>:4:29: error: type 'C2' constrained to non-protocol, non-class type 'X' func foo<X>(_ x: X) where C2: X {} ^
Avatar
omochimetaru 1/24/2020 2:10 AM
書けないとできないユースケース
関数型自体のsubtypingで事足りちゃう気がする。
Avatar
class BaseViewController<Inherit: UIViewController>: Inherit {}
2:11 AM
こういうケースのdiscussionはforumで見た覚えがあります。
Avatar
exit status: 1 with stderr:<stdin>:5:30: error: type 'C2' constrained to non-protocol, non-class type 'Self.X' associatedtype X where C2: X ^
2:17 AM
exit status: 1 with stderr:<stdin>:5:30: error: type 'C2' constrained to non-protocol, non-class type 'Self.X' associatedtype X where C2: X ^
Avatar
omochimetaru 1/24/2020 2:19 AM
@nanasi それはlower-boundなだけでなくてCRTPになってるから更にややこしそうですね 僕も見た記憶がある
Avatar
↑の Inherit のは upper bound じゃない?それぞれ、 InferitBaseViewController の、 UIViewControllerInherit の。
Avatar
omochimetaru 1/24/2020 2:24 AM
Inherit に対して BaseViewController というlower boundを与えているのでは さっきから実験している <X> C: X の形なので
2:24 AM
パラメータの方を主語に見てますよね。
Avatar
Inherit 不定の状態がイメージできなかったけど、ジェネリック関数の中とかだといいのか。
Avatar
単純に↓だけで X に対する upper/lower bounds が効いてるか。 class C1 {} class C2<X: C1>: X { func foo(_ x: X) -> X { x } func bar() { let c1: C1 = foo(self) } }
2:40 AM
さっきの形で lower bound が活きるのがどんなときかよくわからなくて考えてた。
Avatar
omochimetaru 1/24/2020 2:40 AM
C++でよくやるんですけどそのとき必要になるのは自身の型を返すメソッドをもたせるときですね
Avatar
自身の型ってメタタイプってこと?
Avatar
omochimetaru 1/24/2020 2:49 AM
template <Self> class RetainCounted<Self> { Self * retain() { ... } } class Cat: public RetainCounted<Cat> {} auto c1 = new Cat(); auto c2 = c1->retain(); // c2の型がCat*になってほしい (edited)
2:49 AM
ちょっと久しぶりで文法の自身ないですが↑これが頻出
Avatar
↑は c1Cat * だけど c2CatCat * ?とかわけわからなくなったので Swift に直してみたけど、↓みたいなことって理解で良い? class X<K> { func foo() -> K { ... } } class C: X<C> {} let c1 = C() let c2 = c1.foo() // c2の型がCになってほしい
Avatar
omochimetaru 1/24/2020 3:17 AM
あ〜やば。ポインタガバガバになってた。直しました。
3:17 AM
あってます→Swift
3:18 AM
これはSwiftでもコンパイルできるんですね。
3:18 AM
さっきのはまたちょっと違う形なんだな。 (edited)
Avatar
@swift-5.1.5 class X<K> { var value: K { fatalError() } func foo() -> K { value } } class C: X<C> { override var value: C { self } } let c1 = C() let c2 = c1.foo() print(c2) (edited)
Avatar
main.C (edited)
Avatar
実行もできた。
Avatar
たしかSwift5で出来るようになった気がします。
3:28 AM
@swift-4.2.4 class X<K> { var value: K { fatalError() } func foo() -> K { return value } } class C: X<C> { override var value: C { return self } } let c1 = C() let c2 = c1.foo() print(c2) (edited)
Avatar
execution timeout with no output (edited)
Avatar
@swift-4.2.4 print("Hello world")
Avatar
Hello world
Avatar
良かった、生きてた。
🙌 1
Avatar
omochimetaru 1/24/2020 3:35 AM
4.2.4では無限ループしてたやつなのか。
Avatar
omochimetaru 1/24/2020 5:49 AM
Refactor the implementation of function builders so they maintain the statement structure of the closure/function body to which they are applied. This replaces the previous &quot;fold everythin...
5:53 AM
This replaces the previous "fold everything into a single expression" implementation with one that is better in several regards:
It allows generalization to statement kinds that cannot be expressed in a single expression, e.g., if let, although each of these will require work.
5:54 AM
なんかよくなりそう
Avatar
omochimetaru 1/24/2020 7:17 AM
This is really part of a much larger effort to improve #SwiftLang function builders, parts of which have been landing over the last ~6 months. So, I wrote up a summary of what we've been up to in this area: https://t.co/WXaXQlNC9O https://t.co/X5dldpviYi
7:17 AM
ちょうど今アナウンス出たw
7:22 AM
one-way constraintsもこれだったのか
Avatar
omochimetaru 1/24/2020 7:56 AM
let書けるようになりそうなのか
It's scaffolding for supporting let declarations, if let, and switch statements to make function builders more expressive, although that generalization is still a work-in-progress.
7:58 AM
For example, right now a single-expression closure can infer a closure result type: but a multi-statement closure does not: and one will have to provide some type annotations to make this code compile. We should be able to infer the result type of the closure to avoid the need for extra type annotations.
7:58 AM
複数文クロージャの推論制限も外せるかもって言ってる!?
8:00 AM
なんかよくわからないけど、これまでは推論ステージを分けて制御していた部分が、 推論器の内部でステージを制御できるような機能を与えることでいろいろうまくいくみたいな事な気がするな。
Avatar
omochimetaru 1/24/2020 8:09 AM
Introduce the notion of &quot;one-way&quot; binding constraints of the form $T0 one-way bind to $T1 which treats the type variables $T0 and $T1 as independent up until the point where $T...
8:12 AM
今までは 左の式のInt8とInt16のそれぞれで、右の式のInt8とInt16の型チェックをしてたから、2*2で4通りになってたけど、 左と右それぞれでInt8とInt16を確定してから組み合わせるから、 ?: の評価は4通りやるにせよ、計算効率がめっちゃよくなる?(適切にone-wayを入れられる場所なら)
Avatar
omochimetaru 1/29/2020 1:45 AM
The Core Team has decided to reject proposal SE-0275: Allow more characters (like whitespaces and punctuations) for escaped identifiers.
1:45 AM
サクッと通りそうな気がしてたけどRejectだ
Avatar
omochimetaru 1/31/2020 2:49 AM
Hello, Swift community. The review of SE-0270 spanned three separate review periods, from November 11th, 2019, to January 28th, 2020. The latest round of review is here. Community feedback was highly positive on adding this feature in some form, but many details of the desi...
2:49 AM
インデックスの集合のやつ、ついにAcceptedだ
Avatar
```swift var numbers = Array(1...15) // Find the indices of all the even numbers let indicesOfEvens = numbers.subranges(where: { $0.isMultiple(of: 2) }) // Perform an operation with just the even numbers let sumOfEvens = numbers[indicesOfEvens].reduce(0, +) // sumOfEvens == 56 ```
↑の numbers[indicesOfEvens] の結果のコレクションにおけるインデックスの扱いがどうなるんだろうと思ってたけど(他の言語みたいに array[range] のインデックスが 0 から始まらないのでどう整合性をとるのかなと)、↓こうなるのかぁ。
```swift extension Collection { /// Accesses a view of this collection with the elements at the given /// indices. /// /// - Complexity: O(1) public subscript(subranges: RangeSet<Index>) -> DiscontiguousSlice<Self> { get } } extension MutableCollection { /// Accesses a mutable view of this collection with the elements at the /// given indices. /// /// - Complexity: O(1) to access the elements, O(m) to mutate the /// elements at the positions in subranges, where m is the number of /// elements indicated by subranges. public subscript(subranges: RangeSet<Index>) -> DiscontiguousSlice<Self> { get set } } /// A collection wrapper that provides access to the elements of a collection, /// indexed by a set of indices. public struct DiscontiguousSlice<Base: Collection>: Collection { /// The collection that the indexed collection wraps. public var base: Base { get set } /// The set of index ranges that are available through this indexing /// collection. public var subranges: RangeSet<Base.Index> { get set } /// A position in an DiscontiguousSlice. struct Index: Comparable { // ... } public var startIndex: Index { get } public var endIndex: Index { set } public subscript(i: Index) -> Base.Element { get } public subscript(bounds: Range<Index>) -> Self { get } } ```
(edited)
Avatar
omochimetaru 1/31/2020 4:36 AM
Sliceだから元のコレクションと互換性のあるindexが来るから、
4:36 AM
indexの数値だけ見ると飛び飛びになったりするってことかな。
Avatar
うん、そうだと思う。
4:40 AM
これに限らず、 ArraySlice とかのインデックスの取り扱いって他言語と比較して特殊だと思うんだけど( 0 スタートになるのが多い)、その利点や不利益についてどこかで論じられてたりしたっけ?
Avatar
omochimetaru 1/31/2020 4:59 AM
The review of SE-0265: Offset-Based Access to Indices, Elements, and Slices begins now and runs through October 21st, 2019. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep y...
4:59 AM
Michael ilsemanが
5:00 AM
Offset based String Accessの変の話をやっていたときに
5:00 AM
startIndexで扱うのがめんどくさいんだけど的な発言はちょいちょい見た気がするような
5:00 AM
てか、フォーラムではたまに誰かが不満を書き込んでる感じはある
5:01 AM
( 0 スタートになるのが多い)
個人的にそもそも無理だと思ってて
5:02 AM
UTF-8 StringをCollectionとして扱おうと思ったら
5:02 AM
indexからbyte offsetがO(1)で生成できないので
5:02 AM
こうならざるを得なくないですか?
5:02 AM
こう、というのは、「次のIndexを前のIndexに対するadvance操作で得る」体系ってこと。
Avatar
Index == Int に関しては?
Avatar
omochimetaru 1/31/2020 5:03 AM
Sliceに関しても、[0] がスライスの開始点を現せるようにしたところで、 [1] ができちゃったらダメだし。 (edited)
Avatar
共通の Collection プロトコルを考える時点で無理かな?
Avatar
omochimetaru 1/31/2020 5:03 AM
ダメそうな気がする、SliceのIndexを元のCollectionに渡して正当っていう仕様を
5:03 AM
Index型によらずに整合取らないといけないから。
Avatar
つまり、 ArrayArraySlice については Collection にひきづられて今の仕様になってるってこと?ゼロスタートしないこと自体に何かの利益があるわけではなくて。
Avatar
omochimetaru 1/31/2020 5:11 AM
という風に僕は勝手に納得しています
5:11 AM
Arrayについては必ず0スタートじゃなかったっけ
5:12 AM
ArraySliceだけ考えるなら、0スタートにすることはできたけど、一般的なCollectionとSliceの仕様を考えてそれに寄せてある。 (edited)
5:14 AM
てか、そのような 「0から始まるやつ」 を提案しているのが
5:14 AM
まさにSE-0265なような?
Avatar
Array は 0 スタートだけど、 ArraySlice もコピーなく 0 スタートにできるけどしない理由についてだね。 (edited)
Avatar
omochimetaru 1/31/2020 5:15 AM
func fifth<C: Collection>(_ c: C) -> C.Element? { return c[.first + 4] } let array = [1,2,3,4,5,6,7,8,9] print(fifth(array)!) // 5 print(fifth(array[2...])!) // 7
5:16 AM
fifth の中身では .first + 4 という形で 「4番目」と書いてるけど、
5:16 AM
ちゃんと array でも array[2...] でも、「4番目」が得られてる。
5:17 AM
ArraySlice を 0スタートにすると Slice にならなくなる。 ArraySliceがSliceでありながら0スタートになるようにすると、 StringのSliceが作れなくなる。
Avatar
そのあたりの整合性のためってのはわかるんだけど、それによって ArraySlice が使いにくくなってるとしたら悲しいから、 ArraySlice が 0 始まりじゃないことによる利点はないのかな?
5:19 AM
それこそ Collection としてまとめて扱えること?
Avatar
omochimetaru 1/31/2020 5:32 AM
ArraySlice が 0 始まりじゃないことによる利点は ArraySlice が Sliceに準拠することで、 ArraySliceもStrngSliceも同様に扱えるジェネリックなコードが書けるようになること、という理解・・・
Avatar
意外と ArraySlice が 0 はじまりじゃないこと自体が使いやすいケースもあると思うんだけどなぁ。
Avatar
ArraySlice の Index が元の Array のIndex である事を利用した例は https://developer.apple.com/documentation/swift/arrayslice にありますね (edited)
🙏 1
Avatar
omochimetaru 1/31/2020 8:22 AM
if let i = absences.firstIndex(where: { $0 > 0 }) { // 1 let absencesAfterFirst = absences[(i + 1)...] // 2 if let j = absencesAfterFirst.firstIndex(where: { $0 > 0 }) { // 3 print("The first day with absences had \(absences[i]).") // 4 print("The second day with absences had \(absences[j]).") } }
8:23 AM
なるほど・・・
8:23 AM
Collectionに対してindexを探したりする時に、操作範囲の制御のためにArraySliceを使うと、結果がそのまま使える。
Avatar
結局スライスから取ったインデックスを元のコレクションにそのまま使えるっていうだけの話ではある。
Avatar
omochimetaru 1/31/2020 8:24 AM
たしかに他の言語だとこういうfirstIndex 的なメソッドでは startIndex を引数に取る事が多いけど
8:25 AM
スライスがある前提で全部のコレクションアルゴリズム系の関数からオフセット制御の引数をなくせるな。
Avatar
omochimetaru 1/31/2020 8:35 AM
var array = [5, 4, 3, 2, 1] array[1...3].sort() print(array) // 5, 2, 3, 4, 1 へえ。
Avatar
そうそう、この一つ目みたいなやつは書いててあった気がする。二つ目のは考えたことなかった。おもしろいね。でもこれは subscript set で O(N) になる?
Avatar
omochimetaru 1/31/2020 9:13 AM
Nをスライスの要素数だとすると、 処理対象のコピーがO(N), ソートがO(N logN)、結果の下記戻しがO(N) じゃないですかね
Avatar
ああ、 get もか。その subscript get/set の O(N) を省略できたら理想的なんだけどね。オーナーシップで扱えるようになるのかもしれないけど、そこらへんを賢くやってくれるとうれしいなぁ。
9:27 AM
その二番目の sort の例ってどこから出てきたの? rintaro さんのリンク先になくない?
Avatar
omochimetaru 1/31/2020 9:28 AM
ん?僕が書いたコードです
9:28 AM
struct GetModify { var x: String = "👋🏽 Hello" var property: String { get { print("Getting",x); return x } modify { print("Yielding",x) yield &x print("Post yield",x) } } } https://forums.swift.org/t/modify-accessors/31872
9:30 AM
Modify accessorの例題に似た形をしてるのでownershipでいけるような気もするけど、 ArrayとArraySliceに関しては内部ストレージの共有とかあって、同じようにいける話なのかよくわかんないな。
Avatar
そうなのか。例として挙がってたのかと思った。
9:35 AM
でもよく考えたらそのコード、インデックス維持が利いてなくない? @swift-5.1.5 var array = [5, 4, 3, 2, 1] var slice = array[1...3] slice.sort() array[1...3] = ArraySlice(Array(slice)) print(array) (edited)
Avatar
[5, 2, 3, 4, 1] (edited)
Avatar
インデックスを 0 はじまりにリセットしてから subscript set しても同じ結果に。
Avatar
omochimetaru 1/31/2020 9:36 AM
@swift-5.1.5 var array = [5, 4, 3, 2, 1] var slice = array[1...3] slice.sort() array[1...3] = slice print(array) // 5, 2, 3, 4, 1
Avatar
[5, 2, 3, 4, 1]
Avatar
omochimetaru 1/31/2020 9:36 AM
こうじゃないですか?
Avatar
うん、どちらでも同じ結果になるから
9:37 AM
単純に array1...3 にコレクションを代入してるだけで
Avatar
omochimetaru 1/31/2020 9:37 AM
同じArrayに対するSliceで操作しないと不正な気がする。
Avatar
ArraySlice のインデックスが 0 はじまりでないからできることの例になってない気がする。
Avatar
omochimetaru 1/31/2020 9:38 AM
ああ、それはなってないですね。そもそもSliceに対するsubscriptを全くしていないので。
9:39 AM
@swift-5.1.5 var array = [5, 4, 3, 2, 1] var slice = array[1...3] slice.sort() array[0...1] = slice print(array)
Avatar
[2, 3, 4, 3, 2, 1]
Avatar
一瞬 subscript set されるときに ArraySlice 側のインデックスが利いてくるのかと思ったんよね。
Avatar
omochimetaru 1/31/2020 9:40 AM
場所も幅も(!)変えられますね
Avatar
あー。それは SwiftImage の ImageSliceArraySlice を踏襲してたつもりだけど 2 次元では真似できないな・・・。 < 幅も変えられる (edited)
9:42 AM
そもそも set がなかった・・・。サイズ違いは precondition してるのかと思ってたけど。 public subscript(xRange: Range<Int>, yRange: Range<Int>) -> ImageSlice<Pixel> { return ImageSlice(image: self, xRange: xRange, yRange: yRange) }
Avatar
同じ型であっても、同じ extension スコープからしかアクセスできないようなアクセス修飾子ほしくないですか? private より狭いやつ。 @swift-5.1.5 struct Foo {} extension Foo { private var a: Int { 42 } func f() { print(a) } // OK } extension Foo { func g() { print(a + 1) } // これを禁止したい } Foo().g()
Avatar
swift51 BOT 2/1/2020 3:18 AM
43
Avatar
↑でいうと f のサブの処理を a に切り出すようなときに、 a が他から可視である必要がないので。ローカル関数でもいいんですけど、スコープがネストするし個人的に読みづらい気がするんですよね。
3:21 AM
それに、その extension で共通に使われるけど他からは使われない関数とかだとローカル関数にできないし。
3:21 AM
その extension をファイルを分けて private にするとかがいいんでしょうか。
Avatar
ファイル分けるのが良さそうな気はします
6:49 AM
昔はprivateとfileprivateでその辺切り分けれた気がするんですけどね
Avatar
僕もそう思ったんですが、昔の private は今の fileprivate だったような気もしてきました・・・。
Avatar
Kishikawa Katsumi 2/1/2020 3:13 PM
確認してみた。 @swiftbot --version=3.0.1 class Foo { private var fooPrivate = "private property" } extension Foo { func bar() -> String { return fooPrivate } } print(Foo().bar())
Avatar
swiftbot BOT 2/1/2020 3:13 PM
Author icon
kishikawakatsumi
class Foo { private var fooPrivate = "private property" } extension Foo { func bar() -> String { return fooPrivate } } print(Foo().bar())
Version:
swift-5.1.3-RELEASE
Output:
private property
Error:
Avatar
Kishikawa Katsumi 2/1/2020 3:13 PM
あれ、3で実行されない。。 (edited)
3:15 PM
@swiftbot --version=3.0.1 class Foo { private var fooPrivate = "private property" } extension Foo { func bar() -> String { return fooPrivate } } print(Foo().bar())
Avatar
swiftbot BOT 2/1/2020 3:15 PM
Author icon
kishikawakatsumi
class Foo { private var fooPrivate = "private property" } extension Foo { func bar() -> String { return fooPrivate } } print(Foo().bar())
Version:
swift-3.0.1-RELEASE
Output:
Error:
/usercode/main.swift:7:16: error: 'fooPrivate' is inaccessible due to 'private' protection level return fooPrivate ^ /usercode/main.swift:2:17: note: 'fooPrivate' declared here private var fooPrivate = "private property" ^
Avatar
あれ?↓の時点ではスコープ内のみで、その後同一の型の extension からもアクセスできるようになったんでしたっけ? https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
3:36 PM
なんかそんな Proposal あったような気がしてきました。
3:36 PM
private: symbol visible within the current declaration
3:37 PM
```swift class A { private var counter = 0 // public API that hides the internal state func incrementCount() { ++counter } // hidden API, not visible outside of this lexical scope private func advanceCount(dx: Int) { counter += dx } // incrementTwice() is not visible here } ```
3:41 PM
Existing code will need to rename private to fileprivate to achieve the same semantics,
3:42 PM
なので、 Swift 2 では private は今の fileprivate で、その後レキシカルスコープまで狭められたけど、さらにその後同一の型の extension からは参照できるように修正された?
Avatar
Kishikawa Katsumi 2/1/2020 4:10 PM
全く思い出せない。。。fileprivateもあんまり使わないからなあ。
4:11 PM
今のfileprivateってあまり使いどころないような気がしている。。。
Avatar
僕はそのファイルローカルでしか使わない fileprivate な便利メソッドを extenion で既存の型に生やしたりします。 (edited)
Avatar
Kishikawa Katsumi 2/1/2020 4:21 PM
privateでも同じじゃないです?
Avatar
private な API (メソッドやプロパティ)って同じファイル内でも別の型からは呼べなくないですか? (edited)
Avatar
Kishikawa Katsumi 2/1/2020 4:24 PM
いや、できますよ。 こういうやつですよね?この例ではCGRect.integral() をImageResizerから呼んでいます。 import UIKit import AVFoundation public struct ImageResizer: ImageProcessing { ... } private extension CGRect { func integral(_ scale: CGFloat) -> CGRect { return CGRect(x: floor(origin.x * scale) / scale, y: floor(origin.y * scale) / scale, width: ceil(size.width * scale) / scale, height: ceil(size.height * scale) / scale) } }
Avatar
private extensionfileprivate になるとさっき調べていたときに見た気がします。
4:25 PM
トップレベルの privatefileprivate だということだったと思います。
Avatar
Kishikawa Katsumi 2/1/2020 4:26 PM
なのでfileprivate使わないなあ、と思いまして。あえてfileprivateじゃないと書けないことってあったっけ?と思って、そうすると、なんで変えたんだっけ?とわからなくなってきました。
4:28 PM
internal/publicのスコープのプロパティやメソッドに対して細かくこれはprivate、こっちはfileprivateってやるユースケースがあるのかな。
Avatar
@swift-5.1.5 struct Foo { var value: Int } extension Foo { private var squareValue: Int { value * value } func f() { print(squareValue) } } struct Bar { var foo: Foo func g() { print(foo.squareValue + 1) } } Bar(foo: Foo(value: 42)).g()
Avatar
swift51 BOT 2/1/2020 4:30 PM
exit status: 1 with stderr:<stdin>:12:26: error: 'squareValue' is inaccessible due to 'private' protection level func g() { print(foo.squareValue + 1) } ^~~~~~~~~~~ <stdin>:6:17: note: 'squareValue' declared here private var squareValue: Int { value * value } ^
Avatar
↑のケースで squareValueprivatefileprivate にするか、 private extension Foo にしないといけないんですが、後者の場合 f のアクセスレベルにも影響があるので f を分離しないといけません。が、 fileprivate にしたいものだけ分離して private extension Foo のように書けば良いので fileprivate は要らないってことですか?
4:32 PM
個人的には private extension Foo と書くよりも、個別に fileprivate を書いた方がわかりやすいような気がします。
Avatar
Kishikawa Katsumi 2/1/2020 4:41 PM
いや、私があんまりそういう感じに書かないだけなので、
トップレベルの private は fileprivate
というのに慣れていて、そうするとfileprivateなんであるんだっけ?と感じただけです。 fileprivateはユニークで良いと思っています。 私も private == fileprivate として使ってるわけですし。
Avatar
private extension 方式で書いていると、本物の private と混同してしまったりはしませんか?しないからその方式なのかもしれませんが・・・。
4:48 PM
まあ、トップレベルの private func とかは結局 fileprivate なんですよね。
Avatar
Kishikawa Katsumi 2/1/2020 4:54 PM
private extension CGRect { ... } ^ こう書いて、ファイルないの他のTypeから使えるの、自然だと思ってたけど私が単にそれに慣れただけって気がしてきましたね。
4:55 PM
つまり、 class Foo { ... // 同じ型なのでprivate extension Fooのメソッド・プロパティが呼べる } private extension Foo { ... } ^ これと (edited)
4:55 PM
class Foo { ... // fileprivate extension CGRectのメソッド・プロパティが呼べる } fileprivate extension CGRect { ... } これを使い分ける方が一貫性がありそう、っていう話ですね? (edited)
Avatar
そこまで強い意見があるわけではないんですが、 private extension Foo { func f() { ... } }extension Foo { fileprivate func f() { ... } } が同じになるのは、前者では字面上の private に引きづられて fileprivate ではなく private と勘違いしそうだなという感じです。僕が慣れてないだけかもしれませんが。
1:55 AM
それとは直交する話として、同じ型であってもレキシカルスコープに限定する private がほしいなと思ったと。 scopeprivate みたいな感じか、今の privatetypeprivate みたいにするか。まあでも今でも複雑だし、 tarunon さんの言うようにファイル分けるが現実的そうですね。
Avatar
@swift-5.1.5 func f(_ array: [[Int]]) -> Int { array .filter { $0.count > 2 } .reduce([Int.min, Int.min]) { switch ($0, $1) { case let (max, new) where max[0] > new[0]: return max case let (max, new) where max[0] == new[0]: return max case let (max, new) where max[0] < new[0]: return new } }[1] } print(f([[0, 0], [0, 1], [0, 3]]))
Avatar
exit status: 1 with stderr:<stdin>:5:9: error: switch must be exhaustive switch ($0, $1) { ^ <stdin>:5:9: note: add missing case: '(_, _)' switch ($0, $1) { ^
Avatar
怒られる。なぜなのか
Avatar
omochimetaru 2/6/2020 12:57 AM
whereは網羅チェッカーが対応してない
Avatar
そんなー。 頼りにしてるのに
Avatar
omochimetaru 2/6/2020 1:05 AM
比較結果をenumで返す関数を自作してそれを経由するとか・・・
Avatar
まじめにユニットテスト書いたりですね
Avatar
norio_nomura 2/7/2020 12:26 PM
Xcode 11.4 betaでSWIFT_CROSS_MODULE_OPTIMIZATION = YESとすると、-cross-module-optimizationが有効になる。
12:27 PM
This is a first version of cross module optimization (CMO). The basic idea for CMO is to use the existing library evolution compiler features, but in an automated way. A new SIL module pass &qu...
Avatar
norio_nomura 2/8/2020 12:29 AM
Xcode 11.4のSwiftに _forEachField() ってのが入ってる。 https://github.com/apple/swift/pull/29042
This function walks all the fields of a struct, class, or tuple type, and calls body with the name, offset, and type of each field. body can perform any required work or validation, returning true ...
Avatar
Mirrorから出来ること増えるだろうか
Avatar
omochimetaru 2/8/2020 1:58 AM
masterだとマージされてないけど配布版に入ってるのか
1:58 AM
SwiftUI Canvasとかで使ってるのかな
Avatar
offsetがあってフィールドの変更が可能なら、DynamicPropertyの実現に使えそうな気がする (edited)
2:04 AM
Mirrorだと出来ないんだよね
Avatar
omochimetaru 2/8/2020 2:06 AM
ポインターが来てるからできるんじゃない? (edited)
Avatar
できそうだよね。SwiftUIで使われてると思う
Avatar
激アツ
11:00 AM
これはワクワクするな〜
Avatar
omochimetaru 2/8/2020 11:01 AM
おー
Avatar
これどうなってるんだ
Avatar
_forEachFieldからフィールドへのオフセットと型を取り出して、structの先頭からのオフセットがフィールドの値なのでそこに新しい値をねじ込んでいます。 didSetも発生しているので
11:02 AM
これがあるとSwiftUIが作れる。
Avatar
UnsafeMutablePointer経由でwriteしてもdidSetトリガーされるのどうやってるんだろう
Avatar
もともとUnsafeMutablePointerから書き込んでもdidSetは発火してた気がする
Avatar
omochimetaru 2/8/2020 11:05 AM
それはないのでは
Avatar
あれれ
Avatar
omochimetaru 2/8/2020 11:05 AM
withUnsafePointer関数が
11:05 AM
inoutで受けてるから
Avatar
ああそうですね
11:05 AM
えーとなので
Avatar
omochimetaru 2/8/2020 11:05 AM
inoutに渡すと書きこみになるだけ
Avatar
各フィールドにdidSetつけても発火しない。
Avatar
あーそっか、なるほど
Avatar
mutable func updateAllDynamicProperties() 自体は十分に作れる素養はあるので (edited)
11:07 AM
今書いてるコードで萎えてたのは全部解決しそうだ
Avatar
omochimetaru 2/10/2020 6:43 AM
6:44 AM
タプルもいけるんだねえ
6:45 AM
nameがドット付きになってるのstructとは一貫性が無いな。
Avatar
omochimetaru 2/12/2020 9:14 AM
Accept trailing closures in following form: foo { &lt;label-1&gt;: { ... } &lt;label-2&gt;: { ... } ... &lt;label-N&gt;: { ... } } Consider each labeled block to be ...
9:14 AM
面白いマルチクロージャ記法をxedinさんが出してる
9:15 AM
結局2重カッコになってるので foo( label1: { }, label2: { } ) とあんまり辛さが変わってないと思うけど・・・ (trailing closureの嬉しさは末尾の }) の回避にあると思う)
9:16 AM
でも、カンマは要らなくなるみたいだな。 なんかこれもSwiftUIのView記法をいい感じにしたくてやってそう。
Avatar
Buttonとか結構辛いですからね
Avatar
omochimetaru 2/12/2020 6:15 PM
Swift currently supports a special syntax for a single trailing closure which makes it possible to pass a closure as function's final argument after parentheses as a block without a label. This is very useful when the closure expression is long. I propose to extend this func...
6:15 PM
ピッチここにあった
Avatar
殊SwiftUIに関して言えば、FunctionBuilderを如何に差し込むかみたいなところがあるので
Avatar
omochimetaru 2/12/2020 6:17 PM
I think the biggest advantage comes when these closure arguments grow in size especially in SwiftUI.
Avatar
この機能は欲しいだろうなぁという感じ
Avatar
omochimetaru 2/12/2020 6:17 PM
xedinさん自分で書いてた
Avatar
FBによる型の拡張とORTのシナジーが凄いんだよな、よく出来てる
6:18 PM
一方で複数closureが辛いかつ、表現が制限されるのも真なので
6:19 PM
どっちにしてもFBの一般化に伴ってSwiftuI以外でも必要とされるだろうなという気はしている (edited)
Avatar
omochimetaru 2/12/2020 6:19 PM
丸括弧で普通に書いたら何がダメなの?カンマ?
Avatar
複数closureならtrailing closureが禁止されるなら、それはアリ
6:21 PM
例えば2カラムのUIにおいて2引数がleft: FB(略), right: FB(略)の時に、見た目が補完で勝手に崩されるのが一番キツい (edited)
Avatar
omochimetaru 2/12/2020 6:21 PM
それって、Xcodeのフォーマッターが悪いのではないんかな
Avatar
trailing closureの言語機能というかデザイン自体が
6:23 PM
ラベル省略する仕様でありながら複数closureでも使えちゃう、というのはそもそも宜しくないというのが根底にあると思う。フォーマッターはそれが出現しやすくしてるだけ。
6:23 PM
確かにmap filter reduceを初め多くの関数が1closure引数なのはそうだとしても (edited)
Avatar
omochimetaru 2/12/2020 6:23 PM
ああ、rightだけtrailingでズレるのはまあそうか
Avatar
2closure引数の時を考慮できていない言語デザインというのは真だと思う
Avatar
omochimetaru 2/12/2020 6:24 PM
まあ確かに。
Avatar
だから保守的に行くなら禁止ならそれはそれでok
6:27 PM
あー
6:28 PM
ラベルがアンスコで利用側で省略される時だけtrailing可能ってのは、良い塩梅かもしれん (edited)
Avatar
omochimetaru 2/12/2020 6:28 PM
あー
6:28 PM
たしかにーーーー
Avatar
それはつまりclosureの用途が自明であることを指してるからね
Avatar
omochimetaru 2/12/2020 6:30 PM
でもそれは、ソース互換性が無いね。オートマイグレーションはいけそうだが。
Avatar
ソース互換性は別にいらないっしょ、皆慣れてる
Avatar
omochimetaru 2/12/2020 6:31 PM
いや、Swift4でなるべく保つ事になったような
6:31 PM
で、5からはABI。
Avatar
手遅れか〜
6:31 PM
まあでも再考して欲しいんだよな
Avatar
omochimetaru 2/12/2020 6:32 PM
たまには破壊して欲しいなあ(懐古
Avatar
なんかだから、本質的には「multiple trailing closureをどうするか」じゃなくて、「ラベル付きtrailing closureをどうするか」その延長として複数がどうなるか、だと議論が綺麗になりそうな気がするのよな
6:45 PM
まだ議論中なのかな?
6:47 PM
実際 .first { ... } とか良い例で、初見だとナンジャコリャでしょ
6:47 PM
where句なんだよ、わからんって
Avatar
omochimetaru 2/13/2020 1:22 AM
議論中だよ
Avatar
Kishikawa Katsumi 2/13/2020 3:35 AM
ソース互換性は細かいところでは結構壊れてる気もするけどな。いつの間にか直ってることもあるからリリースでは壊れてたことはないのかもしれないけど。
Avatar
omochimetaru 2/13/2020 6:13 AM
Introduce support for initialized let/var declarations within function builder closures, e.g., let (a, b) = c() We generate constraints for the declarations as elsewhere, but the types of the decl...
6:13 AM
FunctionBuilderでlet書けるのはとても良さそう。
Avatar
let書けるようにしたの、Optional Bindingやswitchの布石では!
Avatar
omochimetaru 2/13/2020 6:26 AM
Hi all, We've been making quite a bit of progress on the implementation of function builders within the Swift compiler's type checker. While I'm not quite ready to reopen the big design discussion, I wanted to call attention to some of the work we're doing (some of which has ...
6:27 AM
Douglasがここで方針予告してて
6:27 AM
With this refactor, it becomes easy to support aspects of statements that cannot be described in expressions, such as multiple conditions in an if 11 and support for if #available 4. It's scaffolding for supporting let declarations, if let, and switch statements to make function builders more expressive, although that generalization is still a work-in-progress.
6:27 AM
let、if let, switchって書いてるので、そのとおりだと思う。
6:28 AM
布石としてデカイのがこのone-way constraint https://github.com/apple/swift/pull/25983
Introduce the notion of &quot;one-way&quot; binding constraints of the form $T0 one-way bind to $T1 which treats the type variables $T0 and $T1 as independent up until the point where $T...
Avatar
新しい推論の方法ですか
Avatar
omochimetaru 2/13/2020 6:46 AM
うん
6:48 AM
今までの型推論って制約式をかき集めてエイヤで全部の関係を解いてたのに対して
6:49 AM
A <one-way bind> B は、Bが確定してからA := Bに変わるっていう壁として働くので
6:50 AM
この文を解いたら次はこの文を解く みたいな前後関係が扱えるように成った
6:50 AM
もともとSwiftは文ごとに推論してたから問題なかったんだけど
6:51 AM
FunctionBuilderは複数の文の結果をbuildExpressionの引数として並べるから
6:51 AM
通常のコードと違って複数の文をいっぺんに推論する必要がある
6:52 AM
ので、「FBの複数の文を同時に推論する」必要と、 従来の「1文ずつ推論を進める」機構を、両立させる必要があって
6:53 AM
推論機の内部で制約としてその「1区切りずつ進める」方法論を実現するのがone-way
2:16 PM
azoyさんがリフレクションやろうとしてる
Avatar
あってなかったようなreflection
Avatar
omochimetaru 3/6/2020 2:01 AM
ABI安定化したし、その上でSwiftUIもいろいろやってるし、キチンとしたやつが欲しいなーと思ってた
4:24 PM
レス数も期日も伸びまくってたSE-0279スレがついに閉じた。
4:24 PM
中盤でダグvsラトナーが伸びてたのがアツかった
Avatar
Kishikawa Katsumi 3/14/2020 4:27 PM
結局決まらなかったのかしら?
Avatar
omochimetaru 3/14/2020 4:27 PM
レビュースレッドがいったん閉じてから、後日アナウンスが別スレッドで投稿されるのがパターンです (edited)
Avatar
Kishikawa Katsumi 3/14/2020 4:27 PM
なるほど〜
Avatar
omochimetaru 3/14/2020 4:29 PM
これだけゴチャゴチャするときはreturn for revisionになる事が多いけど、 なんか圧を感じたので、説明付けてacceptになりそうで不安 (edited)
Avatar
ArraySlice<Element> にできて Slice<Array<Element>> にできないことってありますか?一見、 where Base.Index == Int とか色々付けて特殊化すればパフォーマンス含めて同じにできそうに思うんですが・・・。どうして typealias ArraySlice<Element> = Slice<Array<Element>> でないのかという疑問です。初期の Swift ではできなかったから?
Avatar
omochimetaru 3/20/2020 4:58 AM
ArraySliceってArrayを持っているんじゃなくてArrayの中のストレージオブジェクトを持っているのに対して、 Slice<C> は C を持つんじゃないでしたっけ。
Avatar
なるほど、 C を持たずにバッファだけを持てば Array のがわの分だけ領域が節約できると。
Avatar
omochimetaru 3/20/2020 4:59 AM
ガワの情報もそうだしメモリアクセスが一手減ったりするかも? CoWの都合で参照カウント2以上になってしまうケースが生じたりするかも別途気になる。 (edited)
Avatar
Arraystruct だからメモリアクセスの手数は変わらなくできないかな?
Avatar
omochimetaru 3/20/2020 5:02 AM
最適化でそうなる可能性は期待できますね。
Avatar
ガワの分の削減だけでも意味ありそうだけど、そうすると Slice ってサボって楽するためのものでしかなくて、個別実装した方が実行効率は良くなるのか。
Avatar
omochimetaru 3/20/2020 5:04 AM
一般的はそうな気がします。
5:04 AM
Sliceはジェネリック実装で必ずしも理想コードになるとは限らない。
Avatar
SliceProtocol があって、デフォルト実装いっぱいついてて、バッファの部分だけ個別実装とかもありだったのかな。
Avatar
omochimetaru 3/20/2020 5:06 AM
サボり用の Slice がある分には良さそう (edited)
Avatar
ArraySlice の方が効率良くて Slice はサボり用ということで納得しました。ありがとう🙏 (edited)
Avatar
omochimetaru 3/20/2020 5:09 AM
あ、 AnyCollection だと Slice より良い実装が無い、とかあるかしら?
5:14 AM
自分自身を使うみたい。
Avatar
omochimetaru 3/20/2020 5:14 AM
なるほど。
Avatar
抽象実装が二重になるより確かに効率良さそう。
Avatar
Linux の URLSession ってまだ Alamofire が動かないくらいダメなの? https://forums.swift.org/t/alamofire-on-linux-possible-but-not-release-ready/34553
Due to the heroic efforts of @SlaunchaMan, there's a WIP PR up that gets Alamofire mostly working on Linux, including tests! However, it's not really in a releasable state, even if were were ready for it, due to a few issues around Foundation on Linux, namely: URLSessionTas...
Avatar
今更ながらだけど、 callAsFunctionsubscript との一貫性を考えたら subscript のように特殊構文が良かった気がする・・・。 struct Foo { invoke(a: Int, b: String) -> Bar { ... } } みたいな。 subscriptgetForSubscriptingsetForSubscripting でないのと同じように。 (edited)
Avatar
Kishikawa Katsumi 3/25/2020 12:17 AM
同意ですねえ
Avatar
Proposal の Alternative Considered にそれっぽい記述がないんですが、検討されなかったんですかね?
Avatar
最初それでreturned for revisionでしたからね
12:18 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
そうなのか。
Avatar
そうここに書いてあります。
Avatar
ほんとだ。見落としてた。
Avatar
イマイチよくわからないけど↓この部分?
On the first two points, the core team debated several designs and came to recommend that we keep callable syntax directly aligned with func to keep the function grammar consistent and make naming clear. In particular, the core team recommends picking a standard name (like call or invoke) that can be used as a normal named member, and which is automatically callable with function invocation syntax. This would give us syntax like func call(). With this approach, you can invoke the callable with with either value() or value.call(), and can partially apply the callable with value.call.
https://forums.swift.org/t/returned-for-revision-se-0253-static-callables/23290
Hello Swift community, The review of SE-0253: Static callables ran from March 27... April 5, 2019. The core team is very positive about the idea of this feature, but would like to see some changes to the proposal, followed by another round of public review. As such, the prop...
12:28 AM
let foo = value.callAsFunction ができるのがうれしい理由の一つ?
Avatar
それだけならFoo.init もあるし……という気がしますね。
12:30 AM
initはフィールドの初期化という特殊な条件があるのに対してcallAsFunctionは普通のfuncと差がないとかそういうことを書いてる気がします。
12:31 AM
we keep callable syntax directly aligned with func to keep the function grammar consistent
Avatar
subscript は?
12:32 AM
callAsFunction って subscript と同種の存在だと思うんだけどなぁ。
12:33 AM
[] で呼び出すか () で呼び出すか。
Avatar
subscriptはget/setあるからvarのほうが近いのかとも思えますが
Avatar
でも今や subscript はジェネリックだし・・・
12:33 AM
throws はまだできないんだっけ?
Avatar
getに限ればcallAsFunctionと同じような話ですね
Avatar
@swift-5.2.5 struct Foo { subscript(i: Int) throws -> String { "XYZ" } } (edited)
Avatar
exit status: 1 with stderr:<stdin>:2:23: error: expected '->' for subscript element type subscript(i: Int) throws -> String { "XYZ" } ^ <stdin>:2:23: error: expected subscripting element type subscript(i: Int) throws -> String { "XYZ" } ^ <stdin>:2:23: error: single argument function types require parentheses subscript(i: Int) throws -> String { "XYZ" } ^~~~~~ ( ) (edited)
Avatar
throws はまだできないのか。昔議論されたまま放置か。
Avatar
あと、 Swift 5.2 で導入された↓の二つ、バランスおかしくないですか? // SE-0249 let getUserId1: (User) -> String = \.id // OK //print(\.id(user)) // NG print(user[keyPath: \.id]) // OK // SE-0253 struct GetUserId { func callAsFunction(_ user: User) -> String { user.id } } let getUserId = GetUserId() //let getUserId2: (User) -> String = getUserId // NG let getUserId2: (User) -> String = getUserId.callAsFunction // OK print(getUserId(user)) // OK
12:44 AM
KeyPath は関数型に暗黙変換できるけど value(...) の呼び出しはできない。 callAsFunction は関数型に暗黙変換できないけど value(...) の呼び出しはできる。
12:50 AM
callAsFunction 、↓すらできないのか・・・。関数のように見えるけど関数として渡せないって辛くないのかな。 let ids: [String] = users.map(getUserId)
Avatar
//let getUserId2: (User) -> String = getUserId // NG の時点で当然な気はしますね。
12:53 AM
callAsFunction自体S4TFのLayer用途から来てて、一般的なケースはあんまり考えてないんじゃないかという印象
Avatar
そりゃそうなんだけど、特に KeyPath と比べるとバランス悪いなと。
12:53 AM
Proposal には普通の関数だから .callAsFunction つければいいとか書いてあるけど。
12:54 AM
もし callAsFunction が関数型に暗黙変換できるなら、 KeyPath も単に callAsFunction 付ければ良かっただけだと思うんよね。
Avatar
users.map(getUserId.callAsFunction) より users.map({ getUserId($0) }) が短い😂
Avatar
keyPathの関数変換ってたしかmapとか高階関数で使いたいというモチベーションがあってやっと実装されたので、callAsFunctionもそういう需要があれば対応されるんじゃないでしょうか。
Avatar
うーん、やりたいとかそういうことじゃなくて、 () 呼び出しできないものが関数型に暗黙変換できて、 () 呼び出しできるものが関数型に暗黙変換できないって、バランスの取り方としてどうなんだと。
1:01 AM
しかも、 Swift 5.2 で導入されるたった二つの言語仕様の追加なのに・・・。
Avatar
同時期に独立に導入されたので整合性については考慮されてないとかな可能性はありそうですね。
Avatar
let getUserId1: (User) -> String = \User.id // OK let getUserId2 = \.id as (User) -> String // OK let getUserId3 = \User.id as (User) -> String // NG これはバグっぽいですね
Avatar
バグでしょうが何となくそうなっちゃった気持ちはわかりますねw (edited)
Avatar
callAsFunction 、無名 func にすれば良かったのでは。そうすれば新しいキーワードも要らないし、 func が関数ということとも一貫性があるし。 struct Foo { func(_ x: Int) -> Bar { ... } } let foo = Foo() foo(42) (edited)
2:01 AM
いや、それも検討されてたっぽいな。
How to spell a callable method: suggestions included things like call(), func call() , call func() , func() , func _ () , func function() , @callable func evaluate() {
Avatar
omochimetaru 3/25/2020 2:43 AM
無名系は、初見殺し要素が増える シンプルな名前は既存のコードが思わぬ意味をもつ
2:44 AM
って意見によって普通の関数定義かつcallAsFunctionになりました
Avatar
subscript(...) に対して function(...) にする、というのは個人的には好きだった
Avatar
omochimetaru 3/25/2020 2:45 AM
subscriptには左辺値参照をもつvarのような機能があるから
2:45 AM
callAsFunctionとは遠いと思います
2:47 AM
引数をもったvarがsubscriptって感じですね inoutに渡すと書き戻される。
Avatar
そうではなく、コードの見た目の話
Avatar
omochimetaru 3/25/2020 2:50 AM
どちらもキーワード定義により[]呼び出しと()呼び出しが実現できるようになって揃うって事ね。
Avatar
↓これは?やっぱり左辺値があるから func setForSubscripting は変って感じ?
subscript が getForSubscripting や setForSubscripting でないのと同じように。
Avatar
omochimetaru 3/25/2020 2:53 AM
そうですね。 特殊な名前のメソッドにしちゃったら
Avatar
initstatic func initializeAsInstance でないのは?プロパティ初期化が特殊だから?
Avatar
omochimetaru 3/25/2020 2:53 AM
inout書き戻しできる意味論が隠れる
2:56 AM
initとstatic funcは、 initの中にはselfがあるのと
Avatar
特別な名前のメソッドに役割を与えるってのが Swift っぽくなくて気持ち悪い・・・
Avatar
omochimetaru 3/25/2020 2:56 AM
required initに関わる継承関係の制約で、
2:56 AM
static funcにはない型的な意味論がある気がしてる きちんと考え切れてないけど。 (edited)
2:57 AM
ていうか、見えないallocとの絡みと言えばいいのかな allocの結果がselfとして渡ってくる
Avatar
無名 func 良かったと思うんだけどなぁ。キーワードかぶることもないし、これまでのコードを殺すこともないし。初見殺しより特定のメソッド名に役割を与える方が微妙な気が。
Avatar
omochimetaru 3/25/2020 2:58 AM
callAsFunctionは呼び出しが無名な事以外は実装する側の特別な型ルールがない
2:58 AM
検索性も議論されてましたね
2:59 AM
callAsFunctionなら、なにこれ?からググって答えに行きやすい
2:59 AM
個人的には名前がダサいしfunc call派でした 既存コードも多分同じ意味になってるだろう
Avatar
まあ、それはもうどうしようもないとして、 KeyPath との変換の整合性はどう思う?
Avatar
omochimetaru 3/25/2020 3:00 AM
それだけ見て特別な事が起きるってわからない問題はありますね もし無名ならそういうヒントは付くのが良い
Avatar
Swift 5.2 で KeyPath は関数型に暗黙型変換できるようになったけど、 () 呼び出しはできない。 callAsFunction が付いてる型は () 呼び出しできるけど関数型に暗黙変換できない。
3:02 AM
関数っぽいものが暗黙型変換できなくて、関数っぽくないものが変換できるのが微妙な気が。
3:02 AM
しかも、その二つだけが同時に導入されるので目立つ。
Avatar
omochimetaru 3/25/2020 3:11 AM
まずkeypathに関しては、関数形式で呼び出せないのは変な気はしているんですけど
3:12 AM
subscript での [keyPath: keyPath] 形式は、さっきと同じで、左辺値の概念が入ってるんで、
3:12 AM
そこは良いような気もしてます
3:12 AM
callAsFunctionに関しては、おかしいと思ってるんですけど、多分まだ途中だからだと思っていて
3:12 AM
callAsFunctionのその先の発展として、
3:12 AM
関数型プロトコルの追加というのがあるはずで、
3:13 AM
やるならそのタイミングなのかなと思ってます
3:14 AM
とりあえずTensorFlowチームがモデルのコードの見た目だけでも通したくて、今のスコープでproposalが切られたと勝手に思ってます。
Avatar
もし callAsFunction が暗黙的変換されるようになったら、 SE-0249 で色々がんばらなくても KeyPathcallAsFunction 付けたらそれで済むと思うんだけど、それだと key path 式に限らず KeyPath 全般が変換できるようになるのと、 KeyPath() でコールできるようになるのでまずいかな?
11:46 AM
subscript での [keyPath: keyPath] 形式は、さっきと同じで、左辺値の概念が入ってるんで、 そこは良いような気もしてます
一瞬なるほどと思ったけど、 foo[keyPath: \.bar]\.bar(foo) は主従が逆だからいいんじゃないかな? callAsFunction を持つのは KeyPath 側、 subscript(keyPath:) を持つのは Foo 側。
Avatar
ふ〜む KeyPathも関数オブジェクトとするのか、理にかなってるような気もします。
12:18 PM
KeyPathはあんまり使ったことがなくて見落としてる事がないか自信が無いですが。
Avatar
omochimetaru 4/3/2020 2:41 AM
C++ Exception Interop のスレで、C++の関数は無修飾だと例外を投げうるから、 これを全部throwsでインポートすると辛いので、 新たにthrows! という概念を追加して、 try できるけど何も書かない場合は try! 扱い というのはどうか、という話題が発生して、 そこにクリスラトナーが、 足し算のオーバーフローや配列の範囲外アクセスを throws! であることにすれば、 エラーハンドリングできるようになる って意見を書いている https://forums.swift.org/t/handling-c-exceptions/34823/38?u=omochimetaru
Yes, this seems reasonable to me. To reiterate other people's points and respond to Jon's comments upthread - I agree about the potential for abuse and agree that former Java programmers who haven't learned enough Swift may reach for throws! when they shouldn't - just like th...
👀 4
Avatar
ほー
2:43 AM
logic failureがthrows!に成り得るのかな。fatalErrorとの兼ね合いも気になる
Avatar
omochimetaru 4/3/2020 2:43 AM
IUOが ! が常に付いてる Optional であるのと同じノリで、 throws! な func は デフォルトで try! が付いてる(ただしはがせる) みたいな感じっすな
2:44 AM
fatalErrorも throws! にできるね、プロセス即死を廃止できる。
2:45 AM
あと話題としては、この throws! でのインポートは、 Python interop にもあったら便利だった、というのもある。
Avatar
func fatalError(...) throws! -> Never とか?
Avatar
omochimetaru 4/3/2020 6:09 AM
シグネチャはそうなりますね。
Avatar
preconsition とか assert は最適化でエラー投げたり投げなかったりになるけどいいのか?と思ったけど、別にシグネチャ的には問題なさそう。
6:12 AM
interop で ! が氾濫するの、 Obj-C のときもそうだったけど、仕方ないとはいえ辛みがあるなぁ。 Obj-C は大分解消されてきたのに。
6:13 AM
Python は動的型付けだからどうしようもないけど。
Avatar
omochimetaru 4/3/2020 6:13 AM
interopされたシグネチャがthrows!に見えるだけでSwiftユーザーは書けないっていう意見もありますね。
6:13 AM
KotlinのPlatform Type的な。
Avatar
Kotlin のFoo!
Avatar
omochimetaru 4/3/2020 6:14 AM
まあthrows!をSwiftで書けるようにする話題はスレ違いってことで止められちゃったけど。
Avatar
Swift Concurrency Manifesto. GitHub Gist: instantly share code, notes, and snippets.
Avatar
omochimetaru 4/3/2020 6:18 AM
ふむ
Avatar
Combine の foo.eraseToAnyPublisher() って AnyPublisher(foo) するのと何か違うんでしょうか?
8:21 AM
@omochimetaru combine チャネルあってもいいかも?
Avatar
omochimetaru 4/16/2020 8:22 AM
作りました
🙏 1
Avatar
norio_nomura 4/17/2020 5:59 AM
ここのボットでswift -frontend -replとかしてたまに使うintegrated REPLをswiftから削除するにあたり、使ってる人がいるかどうか調査するスレッドが出来てたので、コメントしておいた。 https://forums.swift.org/t/rfc-removing-the-integrated-repl/35441/4
Hi, I sometimes use integrated REPL explicitly as swift -frontend -repl because it works in a docker container launched without the --privileged option. If integrated REPL is removed, it would be nice if LLDB REPL could be invoked in a docker container without the --privileg...
👍 2
Avatar
@swift-5.1.5 @swift-5.2.5 enum Foo { case a(Int, String) } switch Foo.a(42, "XYZ") { case .a(let x): print("\(x.0), \(x.1)") } (edited)
Avatar
42, XYZstderr:<stdin>:6:9: warning: cannot match several associated values at once, implicitly tupling the associated values and trying to match that instead case .a(let x): ^ (edited)
Avatar
42, XYZ
Avatar
これが今でもできると思ってなかった。 5.2 で warning になったのか。
Avatar
@swift-5.3.3 print([true, true, true].allSatisfy()) print([true, false, true].allSatisfy())
Avatar
swift53 BOT 5/6/2020 3:05 PM
exit status: 1 with stderr:<stdin>:1:37: error: missing argument for parameter #1 in call print([true, true, true].allSatisfy()) ^ <#(Bool) throws -> Bool#> Swift.Sequence:3:28: note: 'allSatisfy' declared here @inlinable public func allSatisfy(_ predicate: (Self.Element) throws -> Bool) rethrows -> Bool ^ <stdin>:2:38: error: missing argument for parameter #1 in call print([true, false, true].allSatisfy()) ^ <#(Bool) throws -> Bool#> Swift.Sequence:3:28: note: 'allSatisfy' declared here @inlinable public func allSatisfy(_ predicate: (Self.Element) throws -> Bool) rethrows -> Bool ^
Avatar
@swift-5.3.3 extension Sequence where Element == Bool { func allSatisfy() -> Bool { return allSatisfy { $0 } } } print([true, true, true].allSatisfy()) print([true, false, true].allSatisfy())
Avatar
swift53 BOT 5/6/2020 3:05 PM
true false
Avatar
これってなんでないんでしたっけ?
3:06 PM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
1:02 AM
Don’t push RangeSet into 5.3 since the additions are all available via the preview package. This will give it more time to bake. rdar://problem/63285386
👀 1
Avatar
omochimetaru 5/16/2020 5:06 AM
まだPreviewPackageで提供するのか。 それを経てacceptしたんじゃないのか・・・ まあまだみんなそんなに使ってないしってことかなあ
Avatar
This will give it more time to bake.
なので、まだ不安があるということなのかな?
Avatar
omochimetaru 5/17/2020 1:19 AM
The core team has asked that discussion be spawned in a separate thread regarding support for use of an optional label for the first trailing closure. Therefore, later today, I'll be sharing a draft proposal here which addresses that topic. While it has been brought to mind b...
1:20 AM
単一末尾クロージャと、複数末尾クロージャの一つ目のクロージャに、ラベルをつける記法を導入する提案
1:20 AM
これめちゃくちゃ良いと思う
Avatar
よさそう
Avatar
omochimetaru 5/17/2020 1:21 AM
なぜなら、複数末尾クロージャが導入されたせいで、「末尾の最初のクロージャはラベルが無くてもわかりやすい関数名にする」っていう新しい命名指針が生まれちゃったのが、気持ち悪かったから。 この記法があれば、ラベルが消えることを気にした命名がいらない
Avatar
(,) がなくなるだけ、と。
Avatar
omochimetaru 5/17/2020 1:27 AM
そうですね。右端の閉じかっこが移動して、通り過ぎたカンマが消えるだけになりますね
Avatar
func呼び出しにそもそも()なければよかったのでは...
4:15 AM
print a
4:15 AM
とかできる感じで
Avatar
omochimetaru 5/17/2020 4:16 AM
objectiveCの[]が無い状態がそんなんですね
4:16 AM
丸括弧無いとC系と違いすぎて流行らなかったのではないか
Avatar
まあそれはわかる気がする
Avatar
omochimetaru 5/17/2020 4:18 AM
そのスタイルだとrubyが似てるけど
4:19 AM
関数呼び出しのオペランドと、二項演算子の組み合わせが
4:19 AM
文法的に見た目が曖昧でわかりにくそう
4:19 AM
f a + b
Avatar
rubyはパーサーが凄いから...
Avatar
omochimetaru 5/17/2020 4:21 AM
パーサーがすごくても人間が慣れるハードルはあるから。
4:23 AM
(f a) + b なのか f(a + b)なのか。
Avatar
人間もすごくなれる! kwargsとか...
Avatar
omochimetaru 5/19/2020 4:27 PM
I read these kind of things very frequent in the last couple weeks. That makes me wonder, what kind of breaking changes are considered/allowed in Swift 6? There are a couple other things that come to my mind that would require a breaking change to be really fixed / work.
4:28 PM
あるスレでJoeGroffが「Swift6で破壊的変更する?」みたいな事言ったのを受けてアツいスレが立ってる
Avatar
break things move fast.
Avatar
omochimetaru 5/19/2020 4:30 PM
破壊的な事は早く進む?
Avatar
Move fast and break things may refer to: Move fast and break things (motto), internal motto used by Facebook until 2014 Move Fast and Break Things (book), 2017 book by Jonathan Taplin subtitled How Facebook, Google and Amazon Have Cornered Culture and Undermined Democracy
4:31 PM
逆だった
Avatar
激アツでワロタ
Avatar
omochimetaru 5/19/2020 4:32 PM
なんか元の発言はだいぶ細かい話なんだけどw
4:33 PM
resilent buildでない状況でも後から追加できる@extensible enumができたらいいよねみたいなスレ。
4:34 PM
Move Fast and Break Things: How Facebook, Google, and Amazon Cornered Culture and Undermined Democracy
本のタイトルなのか。
(edited)
4:34 PM
>>2 から結構過激なんだよな
Removing inout-to-pointer conversions would be great.
4:35 PM
Slava_Perstov
I don't claim to speak for the core team, but my personal opinion is that we should consider a potential small number of changes to fix quirks in the language that are actively harmful in practice, or make the language harder to learn
4:36 PM
Slavaが「コアチーム見解ではないが個人的には言語の実戦でよくハマる問題や言語を学びにくくしてる事は少しの修正をすることを考えて良いと思ってる」てきな事書いてる! (edited)
4:37 PM
Examples would be cleaning up some of the implicit conversions in the type checker
4:37 PM
some of the implicit conversionsに Optional wrapping は入りますか
Avatar
いれてくれ!!!w
4:38 PM
ObjC互換という壁があるので精算はできないと思うけど
4:39 PM
some of the implicit conversionsにOptional誰も突っ込んでないのな(´・_・`)
Avatar
omochimetaru 5/19/2020 4:39 PM
今眺めてるけど誰も書いてなさそうw
4:39 PM
if let 構文 直せないかな・・・
Avatar
John_McCall The Core Team has no interest in pursuing changes that would massively invalidate existing code.
https://forums.swift.org/t/breaking-changes-in-swift-6/35928/14
Avatar
omochimetaru 5/19/2020 4:46 PM
massively invalidate existing code
ですよね
Avatar
massively はどの程度なんだろう?
Avatar
omochimetaru 5/19/2020 4:49 PM
10%のコードの修正が必要ならmassivelyと感じるな
4:49 PM
現実的には影響範囲1%ぐらいまでしか許されなさそう
Avatar
if let 直したら半分くらいのコードはビルドできなくなりそう😢
Avatar
omochimetaru 5/19/2020 4:50 PM
半分じゃ済まないでしょうw
Avatar
0%と1%は大きな違いだけど
4:50 PM
1%と10%はたいしたことないと思うんだよね
4:50 PM
だからぶっ壊すなら壊せばいいと思う派
Avatar
omochimetaru 5/19/2020 4:50 PM
なるほど?
Avatar
all or nothingだと思う
4:51 PM
1% だから手で直せる〜
4:51 PM
かどうかはコードの規模による
Avatar
0.1%くらいが想定されてそうな気も?
Avatar
0.1% だろうか 1% だろうが 10% だろうが、結局は相対的なものなので、同じことかなあって。 (edited)
Avatar
連続的ならそうですが、0.1%くらいになると個々人の体験では0%になる人が多そうなので、そのあたりは結構違いそうに思います。
4:52 PM
10%と20%なら同じだと思いますが・・・。
Avatar
ああ、そうか、マイナーな機能かどうかという意味ではありうるかな
4:53 PM
まあでもどうだろうね。
4:53 PM
swiftは壊れ続きてきた過去があって
4:53 PM
今もあるから
4:54 PM
ちょっとくらい壊れてもなんとも思わないというバイアスが利用者にあると思う
Avatar
omochimetaru 5/19/2020 4:54 PM
ww
Avatar
すくなくとも自分は if let かわっても文句言わない
Avatar
omochimetaru 5/19/2020 4:54 PM
新社会人と話すと、落ち着いたここ2年ぐらいから触ってる人も結構居ますよ
Avatar
そっかー。
4:55 PM
python2を知らない世代
Avatar
omochimetaru 5/19/2020 4:55 PM
「Swift 1, 2, 3 の地獄を見てきた者たちだ、面構えが違う」のやつ (edited)
Avatar
ruby1.8を知らない世代
Avatar
omochimetaru 5/19/2020 4:55 PM
意外とafter4世代が居る。
Avatar
まあ、破壊的変更に完璧に自動で書き換えられればなんの問題もないと思うな。
Avatar
Swift 2 → 3 は massive だけど、 Swift 4 → 5 だと修正なしで通ったコードベースも多そうな気も。巨大なアプリは無理かもだけど、そこそこの大きさまでのライブラリとか。
Avatar
omochimetaru 5/19/2020 4:56 PM
python2は実際現行なので知らない世代まだいないかもw
😩 1
4:56 PM
auto migrateできればいいのでは説は僕もある
Avatar
$ /usr/bin/python --version Python 2.7.16
4:57 PM
辛い現実
Avatar
論点違うけど、 if let foo =if case let foo? = があるけどダメ?
Avatar
omochimetaru 5/19/2020 4:57 PM
そのcaseの省略って事になってほしい
Avatar
case 省略したい気持ちはすごくわかる。 switchcase もだるい・・・。
4:58 PM
パターンマッチの気持ちよさを削がれる・・・。
Avatar
omochimetaru 5/19/2020 4:58 PM
確かにswitchcase めっちゃ書いてるな
Avatar
パタンマッチがうぬぬって感じなのはSwiftの残念な部分
4:59 PM
スパーンって感じがない
4:59 PM
unapply 欲しい
Avatar
AtCoderでRustを使う一億個の理由のうちの一つがこれ
Likes
482
5:00 PM
こういう気持ちよさがない。まあ、文指向の Swift ではこれできないけど。
Avatar
インデントの色付けに目がいった
Avatar
確かに色付いてますね。色つけるなら (){} と色合わせてほしい気も? (edited)
Avatar
omochimetaru 5/19/2020 5:04 PM
ゲーミングカラーリングってあんのかな 7色がアニメーションし続けて欲しい
5:05 PM
インデントの場所に応じてキーボードの色も変わると
5:05 PM
便利かも
Avatar
omochimetaru 5/19/2020 5:05 PM
かっこいい
Avatar
最近仕事でコード書いてて struct のプロパティで let 使った方が良さそうな新しい(?)パターンを発見した。 (参考) https://qiita.com/omochimetaru/items/7265e440418b38088ccb (edited)
記事について この記事は potatotips#39 という勉強会で発表した内容を再掲したものです。スライドの画像と、喋った言葉を載せました。 以下スライド それではこれから、Swift の struct の st...
1:30 AM
たとえば、 Identifiable みたいなやつで、 id をキーにした Dictionary を作った場合、 id か書き換えられるとキーと整合性が取れなくなる。
1:31 AM
まあでもこれは何にでも言えるので Dictionary の使い方の問題の範疇かな?
1:31 AM
id の場合はキーとして使われやすいのでそういうケースが起こりやすいという違いはあるけど。
Avatar
私も基本、イニシャライザーを通して欲しいstructはletでプロパティー宣言していますね
Avatar
↑は、それで本質的に防げてることはないという意見だったかと思います。
1:36 AM
@swift-5.2.5 struct Foo: Identifiable { typealias ID = Int var id: ID var value: String } let foos: [Foo] = [ .init(id: 1, value: "ABC"), .init(id: 2, value: "XYZ"), ] var idToFoo: [Foo.ID: Foo] = .init(uniqueKeysWithValues: foos.map { ($0.id, $0) }) print(idToFoo) idToFoo[1]?.id = 999 print(idToFoo)
Avatar
[1: main.Foo(id: 1, value: "ABC"), 2: main.Foo(id: 2, value: "XYZ")] [1: main.Foo(id: 999, value: "ABC"), 2: main.Foo(id: 2, value: "XYZ")]
Avatar
↑で 1 で引ける Fooid999 になってしまっているのが、 idlet なら防げる。他のプロパティでも同じことだけど、 id はキーとなることが想定されているものだから(そのために Hashable が強制されてるわけだし)、 let の方が望ましそう。
Avatar
はい、私が言いたかったのも、このような場合私は idvaluelet 宣言しますね struct Foo: Identifiable { typealias ID = Int let id: ID let value: String }
Avatar
↑の登校にはそこまで書かれてませんでした・・・。僕がおもちと話す中で感じてたことかも?
1:47 AM
たとえば、 idlet にしても↓はできてしまうみたいな話ですね。 struct Foo: Identifiable { let id: Int var value: String } struct Bar { var foo: Foo } var bar = Bar(foo: Foo(id: 1, value: "ABC")) //bar.foo.id = 999 // NG bar.foo = Foo(id: 999, value: bar.foo.value) // OK
1:49 AM
同じインスタンスを変更したのか、新しいインスタンスに差し替えたのかは、共有されていなければ区別できない。
投稿のこのあたりの意見に通づることかと。
1:52 AM
var が適切でない既知パターンとしては複数のプロパティが連動しているケースで片方だけ変更された場合に困るということがありましたが( didSet 等で辻褄を合わせるか、変更を禁止するか)、 id はキーとしての利用が想定されているので Dictionary に入れた後で変更されると困るというのは新しいパターンかなと。
Avatar
「Nominalなタプル」ではない場合においては、letの意味があると思います。
https://twitter.com/omochimetaru/status/1127854216569995264?s=20 まさにこれですね。
@kateinoigakukun はい、プロパティの範囲や、複数のプロパティ間の関係を制約している場合や、キャッシュになるプロパティを持っているなど、「Nominalなタプル」ではない場合においては、letの意味があると思います。
♥️ 1
💯 1
Avatar
omochimetaru 5/22/2020 3:36 PM
よくそんなむかしのリプライでてきたね
😋 1
Avatar
Swift.Setなんですけど、この動作ってどうなんでしょう? 普通に考えると、すべてのインスタンスのhashValueは同じで且つEqutableでもないので追加されるelementは1つだけだと思うんですけど、そうならないんですよね。 しかもなぜか勝手にvalueが同一のものを同じものと認識していますし。 これって便利だけどバグなのでは? (edited)
Avatar
0 4157596543199416033 1 4157596543199416033 2 4157596543199416033 3 4157596543199416033 4 4157596543199416033 5 4157596543199416033 6 4157596543199416033 7 4157596543199416033 8 4157596543199416033 9 4157596543199416033 (edited)
Avatar
@swift-5.2.5 struct A: Hashable, CustomStringConvertible { let value: Int var description: String { value.description } func hash(into hasher: inout Hasher) { hasher.combine(0) // ハッシュは常にコンフリクトする } } let set1 = Set((0..<10).map(A.init)) let set2 = Set((0..<10).map(A.init)) set1.union(set2) .forEach { print($0, $0.hashValue) } (edited)
Avatar
HashableEquatable ですね。
7:53 AM
なので、ハッシュは衝突しているけど同一ではないので別の要素として追加されてると思います。
Avatar
勘違いでした!
7:55 AM
objcの逆だった
Avatar
CVarArg めっちゃくわしいひといますか?
9:48 PM
extension Optional : CVarArg { } がなぜ動くのか知りたい...
🤔 1
9:49 PM
_ObjectiveCBridgeable が関係してそうなんだけど。
9:52 PM
@swift-5.2.5 import Foundation extension Optional: CVarArg { } struct S { } let a: Any? = S() let s = String(format: "%@", a) print(s)
Avatar
exit status: 1 with stderr:<stdin>:2:1: error: type 'Optional<Wrapped>' does not conform to protocol 'CVarArg' extension Optional: CVarArg { ^ Swift.CVarArg:2:9: note: protocol requires property '_cVarArgEncoding' with type '[Int]' var _cVarArgEncoding: [Int] { get } ^ <stdin>:10:15: error: incorrect argument labels in call (have 'format:_:', expected 'repeating:count:') let s = String(format: "%@", a) ^~~~~~~ repeating count: <stdin>:10:30: error: cannot convert value of type 'Any?' to expected argument type 'Int' let s = String(format: "%@", a) ^ as! Int
Avatar
あれっ..
Avatar
Kishikawa Katsumi 6/10/2020 9:53 PM
Macじゃないとダメそうっすね
Avatar
Foundation.framework あるなしの違い... (edited)
9:54 PM
えー、じゃあなにか Foundation.framework に魔法があるのか
9:55 PM
// protocol witness for CVarArg._cVarArgEncoding.getter in conformance A? sil shared [transparent] [serialized] [thunk] @$sxSgs7CVarArg4mainsABP05_cVarB8EncodingSaySiGvgTW : $@convention(witness_method: CVarArg) <τ_0_0> (@in_guaranteed Optional<τ_0_0>) -> @owned Array<Int> { // %0 // user: %2 bb0(%0 : $*Optional<τ_0_0>): // function_ref CVarArg<>._cVarArgEncoding.getter %1 = function_ref @$ss7CVarArgP10Foundations21_ObjectiveCBridgeableRzrlE05_cVarB8EncodingSaySiGvg : $@convention(method) <τ_0_0 where τ_0_0 : CVarArg, τ_0_0 : _ObjectiveCBridgeable> (@in_guaranteed τ_0_0) -> @owned Array<Int> // user: %2 %2 = apply %1<τ_0_0?>(%0) : $@convention(method) <τ_0_0 where τ_0_0 : CVarArg, τ_0_0 : _ObjectiveCBridgeable> (@in_guaranteed τ_0_0) -> @owned Array<Int> // user: %3 return %2 : $Array<Int> // id: %3 } // end sil function '$sxSgs7CVarArg4mainsABP05_cVarB8EncodingSaySiGvgTW'
9:55 PM
SIL
Avatar
omochimetaru 6/10/2020 9:56 PM
Foundationがあれば、SwiftのAnyはobjcのidにブリッジできるんじゃないかしら
Avatar
なるほど?
9:58 PM
CVarArgstruct とか Optional<T> が動かなくてひじょうにしんどいのになんかこれは動くしなんやねん
9:58 PM
って。
9:58 PM
os_log とかで不便すぎる
9:58 PM
(てかloggingみんなどうしてるの...)
Avatar
Kishikawa Katsumi 6/10/2020 10:00 PM
os_logに与えるパラメータはとりあえず "\(foo)" ってしてます。
Avatar
一度Anyに入れるとObjCに渡せるのはNSDictionaryのAPI周りでよくある
Avatar
@Kishikawa Katsumi それだとos_logの機能まったくアレですよね...
10:02 PM
{private} とか。
Avatar
NSDictionaryがDictionary<AnyHashable, Any>だから。
Avatar
AnyCVarArgじゃないので
Avatar
僕も岸川さんと同じでSwiftで文字列化してます
Avatar
このハックをするとAny? にすればなんでもいけるようになる
10:03 PM
ふむむ
Avatar
Kishikawa Katsumi 6/10/2020 10:04 PM
"{private}%s %s", "\(foo)", "\(bar)" ちょっとうろ覚えですけどこんな感じっすね。左側は必要に応じてマスクできるようにしておいて、右辺(というのか?)はStringにしちゃう。 (edited)
Avatar
なるほど
10:05 PM
"\()" かあ...
10:05 PM
きもい
Avatar
“\(foo)”は型検査もクソもないから僕も嫌いだけど楽だから使っちゃってる (edited)
Avatar
まあしょうがないのかなあ...
10:07 PM
Foundation.framework ない状況ないから、Any == id の世界がいい...
Avatar
Linuxだと無さそう?
10:08 PM
FoundationはあるけどObjCがない
Avatar
LinuxにはUIViewなんてないから
10:09 PM
そんな環境はしらない的な
Avatar
oslogもないのかな
Avatar
os_logもないんじゃないかなあ
Avatar
そういえばSSSWGがLoggingのライブラリ出してたな。
Avatar
Kishikawa Katsumi 6/10/2020 10:13 PM
SwiftLogはインターフェースで実装は結局os_logや他の仕組みを使う必要があるんですよね。
Avatar
てことは
10:14 PM
書式転送もしてるのかな
10:14 PM
無さそうな気がするな・・・
Avatar
ふむー
Avatar
Kishikawa Katsumi 6/10/2020 10:16 PM
どうなんでしょう。それだったらOSLog直接でいいんじゃないか、と思って結局使ったことなくて、実際は便利なのかも。
Avatar
loggingはなんかもうちょっとswiftレベルできれいになって欲しいきもち
10:19 PM
(あるいはきれいにできるなにかを提供)
Avatar
さっき出てきた{private}はどんな機能なんですか?
Avatar
%{private}d
10:19 PM
とかやると、ロギングするときにその値がproductionではログされなくなります
10:19 PM
パスワードとかそう言うのに使います
10:20 PM
%@os_log ではデフォでprivate
Avatar
ほお〜、なるほど。
Avatar
ほら、Appleはプライバーシーコンサーンな会社だから。 (edited)
Avatar
それでログの書式パラメータを転送して維持しておきたいのか
Avatar
そうですねえ
Avatar
”\(private: foo)” なら自作できそう
10:23 PM
書式って型チェック的に、言語に対して外回りでやることになるから
10:24 PM
Swift的に良い方向は、↑みたいに、カスタム文字列埋め込みを使っていく事じゃなかろうかと思ってる (edited)
Avatar
なるほど
Avatar
Foundation.NSStriing.init(format:)も
10:25 PM
割と使ってるけど、ヤダな〜と思ってる。
10:26 PM
浮動小数に対する桁数指定子とかが型チェックされない、書式文字列に埋めこまれてるから。
10:26 PM
あーでも多言語化のためには語順入れ替えとかも必要だから文字列埋め込みだけじゃダメかもしれん・・・
10:27 PM
あ、実際には、リテラル文字列に対して型チェックされるんですけど、そのために特別な仕組みでやってるのが気持ち悪いという事です
Avatar
ほかの言語はどうなんでしょうね
Avatar
言語というか、swiftコンパイラだと
10:31 PM
言語はc++だけど、そこは凝った仕組みがあって
10:31 PM
書式文字列を定義するDSLがあって、それがc++に事前コンパイルされて
10:32 PM
C++側から見ると、書式文字列ごとに、引数の型がオーバーロードされた関数として生成されます (edited)
10:33 PM
だからc++言語の上で、パラメータの型がちゃんと関数の引数の型としてチェックされるし、 複数形のsをつけるとかのちょっとした条件式も使えるし
10:33 PM
あれは理想的だなと思う
Avatar
ただとても特別な仕組みだと。
Avatar
そうですね、c++言語とは別に専用言語を事前コンパイルするので・・・
Avatar
前に、参照を維持し続けるだけのための方法について話しませんでしたっけ?検索してもうまく見つけられなかったんですが・・・。たとえば、 do { let _ = publisher.sink { value in ... } ... } ってやっちゃうと即時キャンセルされちゃうけど、 let cancellable = にしても、その後使わないから警告になっちゃうから、ただスコープの間参照を保持しつづけてくれるみたいなの。 (edited)
10:20 AM
標準ライブラリにそんなやつがありませんでしたっけ?
Avatar
deinit dealloc辺りでここで検索すると出てきそう
10:23 AM
@tarunon ありがとうございます!
😉 1
Avatar
public extension で名前被りがあったときってどうやって解決されるんですかね
3:34 AM
public extension UIView { public func neko() -> String { "meow"} } が複数存在したときとか
Avatar
Kishikawa Katsumi 6/19/2020 3:58 AM
どっちも使用できる状況だったらAmbiguousになるんじゃなかったでしたっけ
3:59 AM
importをするかしないかで区別できる場合は呼び分けられるとかそんなんじゃなかったかな。。
3:59 AM
呼び分けられるというか、コンパイル単位でAmbiguousにならずにどちらか1つを使える。
Avatar
importするかしないかで変わる感じか...
4:02 AM
module名付加で区別みたいなこともできないのか...
Avatar
omochimetaru 6/19/2020 4:09 AM
メソッドに関してはmodule名による完全修飾はできないですね。
4:09 AM
そのモジュールの中でトップレベル関数版を用意しておくしかないと思います。 (edited)
4:09 AM
トップレベル関数ならモジュール名で修飾できるから。
Avatar
なるほど、、、
4:15 AM
厳しい
Avatar
たとえば、 extensionsomeMethod が被ったとして、別ファイルで、 import Foo extension Int { func foo_someMethod() -> Int { someMethod() } } を作るなどして呼び分ける?
Avatar
omochimetaru 6/19/2020 5:55 AM
呼び分け用の別名を用意する手もありますね。それだとメソッド名を修飾するのと使う側の手間はあまり変わらないな。 (edited)
Avatar
既存の複数のライブラリを使っていて名前が衝突してしまった場合に、どうしても一つのファイルの中で呼びわけないといけなかった場合の手段という意味で。
Avatar
おー、確かにそれで回避できる
6:26 AM
ていうかそれを実装しなきゃいけないのがしんどい
Avatar
そうですね。しんどいのでうまい方法があればいいんですが( import as とか)。まあ、最悪やらないといけなかったときになんとかする手段ということで。
Avatar
なんらか完全修飾できればよいですねえ
Avatar
foo.(ModuleName)bar とかできるといいですよね。 (edited)
Avatar
module越えがあえてしにくくしてある、っていうのならまあそういう思想も理解できなくはない
6:28 AM
でもそれならいっそextesnionはモジュールを超えられないとかでよかったかもしれない
6:29 AM
foo.[Module]bar() (edited)
Avatar
そうすると protocol に適合して外部モジュールに食わせるとかもできなくなりそうです・・・。
6:29 AM
後ろに []subscript と衝突するかなと。
6:29 AM
[] はいいかもですね。 foo.[Module]bar
Avatar
こうか
6:29 AM
たしかに
Avatar
Kishikawa Katsumi 6/19/2020 6:30 AM
お、これは受け入れられるんじゃないですか
Avatar
Swift's name lookup is…messy. Very messy. This causes a number of problems, and today I'd like to talk about a potential solution for one of them. Swift allows names to be shadowed by declarations in a nested scope. The idea is that, if you import WidgetKit to access its Widg...
Avatar
いろいろなパターンが。
Avatar
foo.Module::bar よりも foo.[Module]bar の方が読みやすそう。 (edited)
Avatar
dropLast(while:)suffix(while:) がほしくなった。
  • 履歴のようなものをソート済 Array で持っていて、指定された範囲にマッチするものを抜き出したい。
  • 履歴は後ろに積み上がるので、要素追加を O(1) で行うためには昇順で要素を保持する必要がある。
  • 指定される範囲は最近のものであることが多いので末尾から検索したい。
この要件を満たすコードを考えると、 history .dropLast(while: { $0.date >= range.upperBound }) .suffix(while: { $0.date >= range.lowerBound }) のようなことがしたくなる。 RandomAccessCollection なら dropLast(while:)suffix(while:) があってもいいと思う。 SortedDictionary があれば解決する話ではあるけど。
Avatar
suffix(while:) の方は lastIndex(where:) で意図どおりなんでしょうか?
Avatar
lastIndex(where:) だとインデックスしかとれないんで、それを使って SubSequence がほしいですね。
Avatar
あ、いや、なんか対照的に firstIndex(where:) なのかと思ったのですが
3:45 AM
ああ、わかりました。残す方なのか。こっちは。
Avatar
drop(while:)prefix(while:) の対になるものがほしい感じです。
👌 1
3:46 AM
prefix(_:Int)suffix(_:Int)prefix(while:)drop(while:)firstIndex(where:)lastIndex(where:) はあるんですよね。
Avatar
index(where:)firstIndex(where:) になったように、 drop(while:)dropFirst(while:) に変えたくなってしまいそうなやつですね。
Avatar
そうですねー。 dropLast がないからそのままですが、 dropLast が導入されたら禍根を残しそうですね。
Avatar
dropLast(while:) がないのは多分複雑どがO(n)になるからじゃないですかね 🤔
9:26 AM
あでも drop も理屈上O(n)になるのか 🤔
Avatar
omochimetaru 6/23/2020 9:27 AM
無限長でも動くかどうかかな?
Avatar
あー確かに drop(while:) はSequenceのメソッドだから、dropLast(while:) 作りたいならせめてCollectionじゃないと無理ですね
Avatar
RandomAccessCollection を想定しています。
9:32 AM
末尾から読めればいいから、 BidirectionalCollection でいいのかな? (edited)
Avatar
omochimetaru 6/23/2020 9:32 AM
後ろから逐次見ていけば良いからRandomAccessはいらなそう
9:32 AM
無印Collectionは逆方向はダメなんですっけ。
9:33 AM
お〜、そうっぽい、無印Collectionはindex(after:)しかないのかあ。
Avatar
index(before:)BidirectionalCollection にしかなくて、なので lastIndex(where:)Collection にはないね。 https://developer.apple.com/documentation/swift/bidirectionalcollection
9:38 AM
GitHub のコードも BidirectionalCollection に更新したけど、問題なくテスト通った。
1:20 AM
1:20 AM
final classはイニシャライザが自動生成されてる?
1:21 AM
下はFixを押した結果
Avatar
publicが2個ついてる
1:22 AM
めっちゃpublic
Avatar
public initにしようとして、でもinitがないのでそこに入ったんじゃないかと
Avatar
イニシャライザを1つも作らなかったらデフォルトイニシャライザが自動生成されるんじゃないですかね。finalにかかわらず。
Avatar
@swift-5.2.5 class NoValue {} class OneValue { var x: Int } let noValue = NoValue() let oneValue = OneValue(x: 0)
Avatar
swift52 BOT 7/6/2020 4:48 AM
exit status: 1 with stderr:<stdin>:2:7: error: class 'OneValue' has no initializers class OneValue { var x: Int } ^ <stdin>:2:22: note: stored property 'x' without initial value prevents synthesized initializers class OneValue { var x: Int } ^ = 0 <stdin>:5:16: error: 'OneValue' cannot be constructed because it has no accessible initializers let oneValue = OneValue(x: 0) ^~~~~~~~
Avatar
デフォルトイニシャライザについてはこのあたり。 https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID213
Avatar
フィールドが全部デフォルト値を持ってる場合は生成されるんですね。
Avatar
あ、そうです。
4:51 AM
あと、Access Controlの方をみたら、型のaccess levelが public なら、default initializerは internal になるって書いてありました。そんなこと書いてあったのか。記憶になかった。 https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html#ID20 (edited)
4:52 AM
finalじゃない場合はrequiredが要求されたり、publicだと同じ現象になったりしますね。
Avatar
あーなるほど。プロトコルで init() が要求されてるから、継承したクラスで init() をなくせないように required をつけなきゃいけないということですね。
4:55 AM
finalなら継承する可能性がないから書かなくていいのか。へえ。すごい。
Avatar
デフォルトinitializerはstructとかと同じで基本internalというイメージ
Avatar
omochimetaru 7/15/2020 7:22 AM
import Foundation import XCTest public final class EncodableTests: XCTestCase { struct S: Encodable { func encode(to encoder: Encoder) throws { var c = encoder.singleValueContainer() try c.encode(A()) try c.encode(B()) // EXC_BREAKPOINT } } struct A: Encodable { var a: Int = 1 } struct B: Encodable { var b: Int = 2 } func testEncodeDouble() throws { let encoder = JSONEncoder() _ = try encoder.encode(S()) } }
7:22 AM
2回encodeする裏技が使えなくなってた。
Avatar
func encode(to encoder: Encoder) throws { try A().encode(to: encoder) try B().encode(to: encoder) }
8:14 AM
こちらはいけるみたいですね
Avatar
omochimetaru 7/15/2020 8:15 AM
お〜マジか なるほど
Avatar
omochimetaru 7/16/2020 9:40 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
💯 1
9:41 AM
1. TextOutputStreamable かつ CustomStringConvertibleの場合 2. TextOutputStreamableの場合 3. CustomStringConvertibleの場合 4. 任意の<T> 5. Any.Type の場合 の5つのオーバーロードがあるっぽい
9:42 AM
4のケースは _print_unlocked っていう謎の関数に転送されていて
9:43 AM
Mirror.swift において定義されている String.init<T>(describing: T) の実装も、 _print_unlocked への転送だった。
9:43 AM
_print_unlocked の実装は結構面白くて
9:46 AM
6-1 最初の分岐が魔法関数 _openExistential を使ってる if _openExistential(type(of: value as Any), do: _isOptional) { let debugPrintable = value as! CustomDebugStringConvertible debugPrintable.debugDescription.write(to: &target) return }
9:47 AM
_isOptionalは<T> を受けるので必ずopenできるがその先でoptionalかチェックするから、これでAnyの中に入ってるOptionalとかをおそらく必ず展開できて、 OptionalだからCustomDebugStringConvertibleが通る
9:49 AM
その先は 6-2: String分岐, 6-3: TextOutputStreamable分岐, 6-4: CustomSTringConvertible分岐, 6-5: CustomDebugStringConvertible分岐, で、最後のelseが 6-6: Mirror(reflecting: value)
9:50 AM
1が定義されているのは、もし1が無かった場合、2と3のオーバーロード解決が曖昧になるからだと思う。 で、1の実装は2と同じで、 2の実装と3の実装は6-3と6-4と同じになってる
9:51 AM
ということは、2と3は4からの6-Xに対する最適化ショートカットで、1は2と3の都合で必要になった関数
9:51 AM
気になるのは6-5のショートカットが無いことだけど
9:52 AM
もしそれを実装してしまうと(7とする)、 2と3と7の重複組合せを順序付けするためには、 1に相当するやつの(2,7)版、(3,7)版、(2,3,7)版が必要になって
9:52 AM
組合せ爆発するからあきらめたんじゃなかろうか。
9:54 AM
ちなみに、foo はオプショナルの場合の fix-itが2つ出るが、片方は、 String(describing: foo) への書き換えだから、 String.init(describing:) の実装と 4の実装が同じ( _print_unlocked )なのは暗黙的な規約っぽい。
9:56 AM
_print_unlocked は第二引数でStreamを取れるけどstdlib internalなので、 これはユーザーに提供されていない事になる。 String.init(describing:) を使ってエミュレートできるけど、ストリーム処理可能な場合にパフォーマンスロスが出ちゃう。
Avatar
なんでこれ調べてたかというと
10:06 AM
public func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) { print("error \(error, "")") } ↑Optionalの時に警告出るけど、第二引数でデフォルト与えるようにしたくて
10:06 AM
(あと.someの時に外側の Optional( ... ) いらん)
10:06 AM
カスタムintepolation書こうとしてた extension DefaultStringInterpolation { public mutating func appendInterpolation<T>(_ x: Optional<T>, _ defaultValue: String) where T: TextOutputStreamable, T: CustomStringConvertible { if let x = x { self.appendInterpolation(x) } else { self.appendInterpolation(defaultValue) } } public mutating func appendInterpolation<T>(_ x: Optional<T>, _ defaultValue: String) where T: TextOutputStreamable { if let x = x { self.appendInterpolation(x) } else { self.appendInterpolation(defaultValue) } } public mutating func appendInterpolation<T>(_ x: Optional<T>, _ defaultValue: String) where T: CustomStringConvertible { if let x = x { self.appendInterpolation(x) } else { self.appendInterpolation(defaultValue) } } public mutating func appendInterpolation<T>(_ x: Optional<T>, _ defaultValue: String) { if let x = x { self.appendInterpolation(x) } else { self.appendInterpolation(defaultValue) } } }
10:07 AM
多分適切な実装がコレなんだけどなんとかならんかな・・・
Avatar
DidOccur ってめずらしい名前
Avatar
omochimetaru 7/17/2020 6:45 AM
たしかに。
Avatar
UTF16Viewcount って内部表現が UTF-16 のときは O(1) になりますか?
Avatar
かなあ
2:12 AM
NSStringってわかってるならならcastしてlengthのほうがいいような気がする
Avatar
必要に迫られてるわけじゃないんですけど、 https://qiita.com/kntkymt/items/4f02c6b90462f354de6d を見て気になって。コード見てみたけど多重にラップされててぱっと見ではわからなかった・・・。
普段はiOS/Androidのアプリ開発をしている自分ですが、ここ最近競技プログラミングの人気が爆上がりしている1 という噂は聞いており、やろうかなと思っていた所... AtCoderでSwift5.2が使える様になった との情報を耳...
2:15 AM
まあでも内部表現によって O(1) か O(n) か心配しながら使うより、素直に [Character] とか NSString とかで書いた方が良さそうですね。
Avatar
ちゃんと理解したい気持ちはある (edited)
Avatar
@swift-5.2.5 struct Foo { lazy var value = 1 mutating func reset() { $__lazy_storage_$_value = nil } } var foo = Foo() print(foo.value) foo.value = 2 print(foo.value) foo.reset() print(foo.value) (edited)
swift 1
Avatar
1 2 1
1:55 AM
べんり
Avatar
lazyの実体にアクセスする方法あったんですね😮 (edited)
1:56 AM
There is a way to reset lazy var if you want. I think it's probably a bug, but you can access the underlying storage of a lazy var using $_lazy_storage$_{property_name} and set it to nil. For example: class A { lazy var foo: Int = { print("A") return 0 ...
Avatar
https://github.com/apple/swift/pull/33144 $__lazy_storage_$_{name} への直接アクセスは意図されておらず、塞がれるのでご注意を。
Since #21996, the name of the underlying storage variable of a lazy var has been changed to $_lazy_storage$_{property_name}. You couldn&#39;t actually write an identifier in (Swift) source be...
👀 3
Avatar
ですよね
Avatar
omochimetaru 7/31/2020 6:34 AM
あれもしかして、property wrapperのときに $ がキーワードとして使えるようになった影響で穴が空いた?
6:34 AM
元々の $__lazy_... は アクセスしないために $ ついてたのかなって思った。 (edited)
Avatar
べんりなのにな
3:32 AM
easter egg的に残しておく
Avatar
lazy って @Lazy にならないのかな?
Avatar
swift3か4のころはlazy foo: Foo!にnilを代入したらreset扱い、というのが動いてましたね
4:36 AM
IUO型が無くなったことでこの挙動もなくなった、だったかな
Avatar
omochimetaru 8/1/2020 4:38 AM
@Lazyはautoclosureで実装できるんかな?
4:39 AM
コンパイラのコード生成からライブラリに移せると嬉しいですね 既存コードのマイグレーションの問題はあるけど
Avatar
@Lazy var foo: Foo = ... これの時に、initialValue/wrappedValueのinitをescaping autoclosureにしていても、宣言した位置で... が評価されてるからダメみたいですね
Avatar
Property Wrapper の Proposal で @Lazy が例に挙げられてなかったっけ?
12:07 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 8/4/2020 8:59 AM
KeyedDecodingContainer<K> と KeyedDecodingContainerProtocol って
8:59 AM
今更なんだけど
8:59 AM
AnyKeyedDecodingContainer<K> と KeyedDecodingContainer って名前のペアであるべきだったんじゃ?
Avatar
takasekさんのツイートかな
9:01 AM
私もそう思います
Avatar
omochimetaru 8/4/2020 9:01 AM
話してて思った。
Avatar
リプ書いてる途中だった
9:01 AM
送ってしまおう
Avatar
omochimetaru 8/4/2020 9:02 AM
あの時点で AnySequence って存在してたから
9:02 AM
この判断できる可能性あったよね。 (edited)
Avatar
norio_nomura 8/4/2020 11:33 AM
Codableの実装初期PRでは、 KeyedDecodingContainerKeyedDecodingContainerProtocolに準拠するけど、 KeyedEncodingContainerKeyedEncodingContainerProtocolに準拠してない、 と一貫性がなかったのを思い出した。 https://github.com/apple/swift/pull/9004#pullrequestreview-37206353 (edited)
What&#39;s in this pull request? Now that the core types introduced by SE-0166 have been sunk into the Swift standard library, the stdlib and compiler portions of #8124 and #8125 can be combine...
Avatar
omochimetaru 8/4/2020 11:34 AM
ほーー
11:34 AM
@omochimetaru @tarunon だいたいのerasureは文脈の汽空域に現れるのでerasureであることを意識させたいけど、DecodingContainerは文脈が閉じてるので、erasureであることすら知識として表現したくなかった…とか?
11:35 AM
ツイッターで話してて、Anyを付けないのはイレイジャとしてのAPIの提供が主たる関心ではないから、という意見を受けて、ありかもと思いました
Avatar
これって仕様?? DictionaryArrayencode される。 @swift-5.2.5 import Foundation struct Foo: Hashable { var value: String } extension Foo: Encodable { func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(value) } } let dictionary: [Foo: Int] = [Foo(value: "a"): 42] let data = try! JSONEncoder().encode(dictionary) let string = String(data: data, encoding: .utf8)! print(string)
Avatar
["a",42]
Avatar
omochimetaru 8/7/2020 10:47 AM
KeyがEncodableな場合はそうな気がする
10:47 AM
Stringだったら JS.Object になりませんか?
10:47 AM
なぜならJSのObjectは文字列しかキーに取れないから。
Avatar
うん、 String だと object になる。
Avatar
omochimetaru 8/7/2020 10:48 AM
もし Foo の Encoding が JS.Array とかだったら
10:48 AM
JS.Object にできないから、保守的に タプルの配列にするしかないと思う
Avatar
single value の string に encode した場合はキーとして使ってほしい気もするけど、そこだけ対処するのは難しいか・・・
10:49 AM
できそうな気もするけど・・・。
Avatar
omochimetaru 8/7/2020 10:50 AM
実装がだいぶごちゃっとしそうですね
Avatar
JSONEncoder 側は、 encode 前に型で判断してるのか。 (edited)
Avatar
omochimetaru 8/7/2020 10:51 AM
そうですね
Avatar
そうすると、 encode で対応しようがないよね?
10:52 AM
なんか変じゃない?
Avatar
omochimetaru 8/7/2020 10:52 AM
対応しようがない?
Avatar
object として encode させる方法がない?
Avatar
omochimetaru 8/7/2020 10:53 AM
ああ
Avatar
たとえそれをラップしてる型の encode を独自実装しても?
10:53 AM
それはさすがにできるか?
Avatar
omochimetaru 8/7/2020 10:53 AM
コンテナのところで
10:53 AM
var container = encoder.keyedEncodingContainer() すればできますよ
10:53 AM
それかいったん [String: T] に mapする
10:54 AM
さっきのコードみたいにキーの型のencode()の実装だけで制御するのは無理そう。 (edited)
Avatar
イマイチ処理のフローがイメージできてないけど、 mutating func encode<T>(_ value: T, forKey key: KeyedEncodingContainer<K>.Key) throws where T : Encodable こいつが呼ばれるときに一度 JSONEncoder に処理が戻って、そこから Encodable.encode が呼ばれるか判断されるってことやんね?
10:58 AM
保持してる側の encode 実装で対処可能ってことは。 (edited)
Avatar
takasekさんがその辺なんかtwitterでやってた記憶がある
Avatar
保持してる側を自力実装にするのは辛いなぁ・・・。 (edited)
Avatar
Dictionary のラッパーを用意して、それの encode/decode を実装することにした。さすがに保持してる型の encode/decode は色んなプロパティが生えてて辛いので。
Avatar
omochimetaru 8/19/2020 6:06 AM
struct Entry { var manyCountArray: [Foo] mutating func update() { ... } } var map: [String: Entry] = ... for item in items { guard var entry = map[item.name] else { continue } entry.update(item) map[item.name] = entry } ↑このパターンって素朴な解釈では map[item.name]var entry で 2つ参照があるから entry.update の中で manyCountArray の要素を変更したら配列のコピーが発生しそうだけど、 どうだろう (edited)
6:07 AM
map[item.name]?.update(item) こう書けばmodifyなので参照1つなのが表明できるんだけど。 (edited)
Avatar
updatemanyCountArray を変更するならコピー発生するんじゃないかな?( entry に一度代入するパターンのとき) (edited)
6:16 AM
map[item.name]?.update(item) のパターンで書くとき、根っこから深くなればなるほど、そのパスをたどらないといけなくて辛いなと思うんだけど、変数に代入する代わりに inout なクロージャに渡して別名付けるとかすればいいのかな。
6:16 AM
modify(map[item.name]) { entry in entry.update(item) } 的な。
6:17 AM
参照すべきものが二つになった瞬間に詰みそう。
Avatar
omochimetaru 8/19/2020 6:26 AM
最適化で map[item.name] の get から set までに map[item.name] が触られていないことを検出して、entry へのコピーを共有に書き換えてくれたらコピーされずに済みそうだけどそこまでやってくれるのかなあと思って。
6:27 AM
変数に代入する代わりに inout なクロージャに渡して別名付けるとかすればいいのかな。
そうですね。僕は protocol Modifiable を作って map[item.name]?.modify { entry in entry... entry... } って書いてます実際は
6:28 AM
2つになっても modify の入れ子にしたら書けますよ
6:29 AM
ただこういうCoWも含めたコピーの振る舞いを気にしてコードを書くのは言語としては難しいし微妙だなあと思って。
Avatar
同じツリーに属してる二つの枝葉を modify しようとしたら inout で同時編集のエラーにならない?
Avatar
omochimetaru 8/19/2020 7:03 AM
同じツリーに属してるときは、共通部分までは一緒のmodifyにしてないとだめですね。
7:04 AM
foo.bar.modify { (bar) in bar.a.modify { (a) in bar.b.modify { (b) in bar.a = a + b bar.b = a - b } } } ↑これはいけるはず (edited)
7:04 AM
foo.bar.a.modify { (a) in foo.bar.b.modify { (b) in ↑これはだめ (edited)
Avatar
bar.a.modify { (a) in bar.b.modify { (b) inbar に対する同時編集にならない? (edited)
Avatar
omochimetaru 8/19/2020 7:05 AM
ab が stored property なら 分割される
7:05 AM
computed property だとだめ
Avatar
そういうルールなのか。 subscript は computed だから↓ができないのか。 swap(&array[i], &array[j])
Avatar
omochimetaru 8/19/2020 7:07 AM
そうそう。
7:07 AM
そうすると分岐するところがArrayかDictionaryだとだめか・・・
Avatar
そうすると、 stored だけどジェネリック関数の型パラで受けたらプロトコルでの宣言が var foo: Foo { get } になっててダメとかある?
7:09 AM
ある型のカプセル化されたプロパティが stored か computed かで挙動が変わるってちょっと微妙な気が・・・。 stored を computed に変えたらコード破壊されるかもしれないってこと?
Avatar
omochimetaru 8/19/2020 7:10 AM
プロトコルで受けたらcomputedあつかいになってだめはありえる気がする・・・
stored を computed に変えたらコード破壊されるかもしれない
そう
Avatar
そうすると分岐するところがArrayかDictionaryだとだめか・・・
結構ありそう・・・。 users[i].modify { user1 in users[j].modify { user2 in guard user1.points >= points else { return } user1.points += points user2.points = min(user2.points + points, 9999) } }`
(edited)
Avatar
omochimetaru 8/19/2020 7:12 AM
@swift-5.3.3 func modify<T>(_ t: inout T, _ f: (inout T) -> Void) { f(&t) } struct S { var a: Int = 3 var b: Int = 1 } var s = S() modify(&s) { (s) in modify(&s.a) { (a) in modify(&s.b) { (b) in a = a + b b = a - b } } } print(s)
Avatar
S(a: 4, b: 3)
Avatar
omochimetaru 8/19/2020 7:13 AM
@swift-5.3.3 func modify<T>(_ t: inout T, _ f: (inout T) -> Void) { f(&t) } struct S { var a: Int = 3 var b: Int { get { _b } set { _b = newValue } } var _b: Int = 1 } var s = S() modify(&s) { (s) in modify(&s.a) { (a) in modify(&s.b) { (b) in a = a + b b = a - b } } } print(s)
Avatar
exit status: 1 with stderr:<stdin>:14:12: error: overlapping accesses to 's.a', but modification requires exclusive access; consider copying to a local variable modify(&s.a) { (a) in ^~~~ <stdin>:15:16: note: conflicting access is here modify(&s.b) { (b) in ^~~~
Avatar
omochimetaru 8/19/2020 7:13 AM
確認した。
Avatar
これはちょっと微妙な挙動だな・・・。気持ちはわかるけど。
Avatar
omochimetaru 8/19/2020 7:14 AM
ちなみに
7:14 AM
Arrayに.swapAtメソッドがあるのはそのためです。
7:15 AM
Swift.swap(a[i], a[j]) は違反だけど a.swapAt(i, j) はOK
Avatar
@swift-5.3.3 func modify<T>(_ t: inout T, _ f: (inout T) -> Void) { f(&t) } protocol P { var a: Int { get set } var b: Int { get set } } struct S: P { var a: Int = 3 var b: Int = 1 } var s = S() func foo<T: P>(_ s: inout T) { modify(&s) { (s) in modify(&s.a) { (a) in modify(&s.b) { (b) in a = a + b b = a - b } } } print(s) } foo(&s) (edited)
Avatar
exit status: 1 with stderr:<stdin>:15:16: error: overlapping accesses to 's', but modification requires exclusive access; consider copying to a local variable modify(&s.a) { (a) in ^~~~ <stdin>:16:20: note: conflicting access is here modify(&s.b) { (b) in ^~~~ (edited)
Avatar
omochimetaru 8/19/2020 7:15 AM
fooの冒頭で var s = s が必要ですね
Avatar
var にコピーじゃなくて inout にした。 overlapping になった。
7:17 AM
Arrayに.swapAtメソッドがあるのはそのためです。
うん、しかたないんだけど Swift の微妙なところの一つだと思ってる・・・。
Avatar
omochimetaru 8/19/2020 7:24 AM
高速化のために値型+参照を安全に使える言語として設計した結果、
7:24 AM
カジュアルに値型を使うことになってるけど、 (edited)
7:25 AM
特にその高速性が必要ない状況では、排他則にたまに引っかかるのはデメリットのほうが大きそうですね
7:25 AM
上級者向けの言語設計になってると思う。
Avatar
一つの解決策は、変数に保存する代わりにKeyPathに保存することかなぁ。
8:45 AM
Optional挟んだKeyPathに確か書き込めなかったと思うんだけど、それ辛いよね。
Avatar
omochimetaru 8/19/2020 8:45 AM
変数に保存する代わりにKeyPathに保存すること
どういうことですか?
8:46 AM
Optional挟んだKeyPath
これも、なんのことか?
Avatar
let a = foo.bar.baz.qux a.x += 1 a.y *= 2 みたいな一時的に変数に保存して操作することができないから modify を使ってたけど、
8:48 AM
オーバーラップの問題があるから、常に根っこからアクセスする前提で、変数に一時保存する代わりに KeyPath を保存して操作する手があるかなと。
Avatar
omochimetaru 8/19/2020 8:49 AM
ああなるほど
8:49 AM
ツリーをめぐるのを root[keyPath: keyPath] で書けば毎回短く書けるからか。
Avatar
うん。
Avatar
omochimetaru 8/19/2020 8:50 AM
それでコピーしないように書けると・・・。
Avatar
でも、 ?. が挟まると writable にできない…。
Avatar
omochimetaru 8/19/2020 8:50 AM
ほ〜 しらんかった
Avatar
たしか Forum でも不満が出てたけど、そういう設計なんだって押し切られてた気が。
Avatar
async なメソッドでもメソッドコール中は self が retain されてて await してる間に self が解放されることはないのかな? (edited)
Avatar
omochimetaru 8/24/2020 4:32 AM
そこのポリシーがasyncだから変わるってことはないように思います。
Avatar
強制 strong self だけど、 async/await は必ず終わる前提だから問題になることはないのか。前も似た話した気がしてきた。
Avatar
omochimetaru 8/24/2020 4:34 AM
それもそう思います。リークにはならない。
Avatar
あと、これも前に話した気がするけど、 mutating func の中で await したらその後は変更不能になるよね?すごく使いづらそうな気が・・・。 (edited)
Avatar
omochimetaru 8/24/2020 4:34 AM
相互再帰して一生終わらない呼び出しを作ることとかはできるだろうけど
4:34 AM
まあそれはそれで一生終わらない呼び出しの間一生解放されないのは正しいし。
4:35 AM
その後は変更不能に
何がですか?
Avatar
self が。
Avatar
omochimetaru 8/24/2020 4:36 AM
mutating funcasync mutating func の間違い?
Avatar
mutating func foo() async -> Bar
Avatar
omochimetaru 8/24/2020 4:36 AM
asyncは後ろか。
4:37 AM
その後が変更不能になるというのがよくわからない、なぜそうなるの?
Avatar
await の後ろって非同期コールバックと同じだと思うんだけど、非同期コールバックから self を変更できないのと同じことにならない?
Avatar
omochimetaru 8/24/2020 4:39 AM
ならないと思う
4:39 AM
非同期コールバックがselfを変更できないのは、再代入先がないというか、
4:39 AM
そのメソッド呼び出し自体は脱出して終わっているからで
4:39 AM
asyncの場合は、
4:39 AM
asyncなfunc自体が終わるのはそのawaitが終わったあとだから
4:40 AM
コルーチンコンテキスト上の値としてselfへのinout参照がずっと残っているはず
Avatar
呼び出し側が async であることが強制されることで、書き込み先が消えないのか。
Avatar
omochimetaru 8/24/2020 4:41 AM
はい。
4:41 AM
普通のfuncがゆっくり実行されてるようなイメージ。
4:41 AM
終わらないまま戻ってこれるのがコルーチン。
Avatar
そうすると、 async/await だと今の値型と非同期処理の相性の悪さを解消できるのか。
Avatar
omochimetaru 8/24/2020 4:43 AM
おー、そういうことになりますね
Avatar
それは単に書きやすくなる以上の恩恵になりそう。
Avatar
omochimetaru 8/24/2020 4:43 AM
そのinout参照絡みで変な事が起こらないことも、排他則が同じように効いてきて保護されるはず
Avatar
なんかあんま解決してない気がしてきた。
4:47 AM
非同期処理投げてさっさとメソッド抜けたいときには beginAsync を使うわけで、 beginAsync を挟むと結局 self 変更できなくなる。
Avatar
omochimetaru 8/24/2020 4:48 AM
たしかにasyncとnon-asyncの境界は結局面倒なことになりますね。
Avatar
Button("Run") { self.foo = heavyOperation() } ↑の heavyOperation が重いから非同期にしたところで、 Button("Run") { beginAsync { self.foo = await heavyOperation() } } みたいになって self を更新できない。ただし、 SwiftUI の @State なら更新できるのがややこしいけど。
Avatar
これって結局元々の非同期+クロージャコールバックの書き方と等しいわけで、クロージャコールバックとして考えると@Stateでしか更新できないというのは、正常なように思える (edited)
Avatar
はい、 @State でしか更新できないのは正当なんですけど、↑のようなコードは self を書き換えられなくなるけど、 foo が値型でも @State なら書き換えられる(ので例としてちょっとややこしいけど)という意でした。 (edited)
Avatar
@Stateは値型の皮を冠った参照なので…
Avatar
ですねー。そこが便利さを生んでるですけどそこがややこしいんですよね・・・。
Avatar
@swift-5.2.5 func main() { let a: Result<Int, Never> = .success(42) print(a.get()) } main()
Avatar
swift52 BOT 9/1/2020 7:33 AM
exit status: 1 with stderr:<stdin>:3:11: error: call can throw, but it is not marked with 'try' and the error is not handled print(a.get()) ^
Avatar
@swift-5.2.5 extension Result where Failure == Never { func get() -> Success { switch self { case .success(let value): return value } } } func main() { let a: Result<Int, Never> = .success(42) print(a.get()) } main()
Avatar
swift52 BOT 9/1/2020 7:33 AM
42
Avatar
↑この extension 標準でほしくないですか?
7:34 AM
Typed Throws が導入されて、標準の getthrows Failure になれば解決するのかな。
Avatar
omochimetaru 9/1/2020 8:48 AM
typed throwsで自動解決したらスマートですね たしかプロポーザルの時にもそれは提案されてたけど、Never as bottomがまだだったから飛ばされたんだっけな?
Avatar
そもそもの話で言うと、Resultを返す構造自体がFailure==Neverの時にResult<T>ではなくTを返すべき、というのが根底にありそう
Avatar
omochimetaru 9/1/2020 8:49 AM
たしかに?
Avatar
それって tagged union じゃなくて untagged union な世界観な気も。
Avatar
omochimetaru 9/1/2020 8:50 AM
ObservableやPromiseと違ってResultは外せるなあ。
Avatar
taggedかuntaggedかはあんまり関係ないと思うけど
Avatar
omochimetaru 9/1/2020 8:50 AM
エラーのないそれはそもそもただのTと等価だ
Avatar
もっと言うとOptional同様サブタイピング関係が定義できれば〜というのがありそう
8:51 AM
個人的にはOptionalのサブタイピングは嘘なので、そっちの方向は嫌なんだけど
8:51 AM
やりたいことの本質はそれに見える
Avatar
Foo|Never == Foo が自動的に成り立つという意味で < untagged
Avatar
taggedでも、そういうルールを作れば成り立ちそうな気はしていますね
Avatar
そういう意味では Typed Throws は良い塩梅なんじゃないですか? tagged と等価だけど throws Never は消える。
Avatar
omochimetaru 9/1/2020 8:55 AM
たるのんの言うようにするためには、Result.mapErrorに対して結局where U == Neverのオーバーロードが必要になるから
8:55 AM
定義回数を減らすためにはやっぱりResult<T,Never>.get()はあったほうがよさそう
8:56 AM
Resultを作る側で対応しようとするとそのたびにオーバーロードが必要
8:57 AM
typed throwsだとResultに限らず全部タダでついてくるのでベスト
8:57 AM
そもそもtyped throwsうまくいくのかイマイチ想像つかんけど・・・
Avatar
個人的にはtyped throwはあんまり筋良くなさそうという言語化できてない懸念(直観に近い)があるんですが (edited)
8:58 AM
まあ大体Javaのせいなんだが
Avatar
アプリ開発において typed にこだわると邪魔になると思います。
Avatar
omochimetaru 9/1/2020 8:58 AM
エラー型の再定義をするか雑にSwift.Errorにアップキャストしちゃうのかで毎回悩みそう
Avatar
ライブラリにはほしい気もしますが、エラーの型設計が難しい。 (edited)
Avatar
Resultとの棲み分けで良い塩梅なんじゃないか、というのはある
Avatar
Typed Throws ないから Result 使ってるってのは本末転倒だと思うんですよね。
8:59 AM
async/await 入ったら Result 使いたいケースも減るし。
9:00 AM
デフォルトは Untyped Throws だけど、 Typed Throws という選択肢があってもいいとは思うんですよね。
9:01 AM
Forum で話されてるように、 throws に複数の型を書けるのは止めた方が良いと思います。
Avatar
Resultのためにany Error: Errorになったのを考えると
Avatar
omochimetaru 9/1/2020 9:02 AM
Typed Throws ないから Result 使ってるってのは本末転倒
そう思う。Swift 1.xに戻ってしまう。Swiftのtry-throws構文はJavaとは違ってよくできてる。
(edited)
Avatar
やはりというかtyped Errorはマイノリティみを感じる要因でもある
Avatar
Typed にこだわってる範囲ではきちんと API ごとに型付けされたエラー型に包み直す。 < throws に書けるのは一つの型のみ
Avatar
omochimetaru 9/1/2020 9:02 AM
Resultってなんでエラーの型パラメータもってるんだっけ・・・
Avatar
複数Errorを書こうとするなら、まずその前にuntagged unionがいる
Avatar
omochimetaru 9/1/2020 9:03 AM
いや、合成用のenumを定義すれば、そのままでも大丈夫だよ
Avatar
それはそうだが、提案のそれはユーザーサイドでenum書きたくねーぜという話でしょ (edited)
Avatar
Java 、あそこだけ untagged union になってて、 catch でも union っぽい記法になってるのおもしろい。もうどうせなら untagged union 導入しちゃえばいいのに。
Avatar
omochimetaru 9/1/2020 9:04 AM
そういうユーザーは Swift.Error にアップすればいいんじゃないかしら。
Avatar
だったらtyped throwsいらねーじゃん、で議論がループする
9:04 AM
typed throwsに突入する前に、多分色々前提があって
Avatar
omochimetaru 9/1/2020 9:04 AM
いやそれだとResultのエラー型パラメータもいらないという事になるw
Avatar
それを埋めていかなければいけないの気がするね
Avatar
any Error: Error については、 throws Errorthrows と等価であることを扱うためにも意味あるんじゃないでしょうか。
Avatar
omochimetaru 9/1/2020 9:05 AM
自分でやってて、ロジックエラーとしてこれだけはありえる、みたいな
9:05 AM
下層のエラーが浮かんでくるケースとは別で
Avatar
僕はアプリ開発においてほとんどのケースで Untyped なエラーで十分だと思っていて、本当に必要なところやライブラリなんかで選択的に Typed が使えるというのが良いと思います。
Avatar
omochimetaru 9/1/2020 9:06 AM
明確に処理結果の成功以外のバリエーションでエラーが列挙できる状況はあって
9:06 AM
そういうときはenumにしてるけど、typed throwsがあったらバッチリはまるんだけどなあと思うことはあるよ
Avatar
ResultにErrorの型パラを入れないという選択肢もあったけど、any Error:Errorの択が取られたのだよな、という
Avatar
それと同じように Typed Throws を入れるという選択をするときに any Error: Error が実現されてなければ同じ話になったんじゃないでしょうか? Typed Throws は不要というより単に話が進んでないだけで。
9:09 AM
今思えば、 Result 入れないって言ってたのに急に入れる方向に傾いた背景に、 SwiftUI と Combine があった可能性があるかもしれない。 (edited)
Avatar
それはありそうだなぁ、特にCombine
Avatar
だから先に Result を進めないといけなかったとか。一方で Typed Throws に急ぎの事情はない(し Result と違って実装も大変だ)から話が進んでない。
9:10 AM
2016 年には、 Joe Groff が Result は入れないという結論になったって言ってましたからね。
Avatar
omochimetaru 9/1/2020 9:11 AM
asyncとかのほうがさっさと欲しいですしね。
Avatar
で、裏で SwiftUI 作ってる中で、こういうケースでないと困るよというユースケースが溜まってきて、考えを改めたのかなと。
Avatar
asyncとthrowsで解決できるのはFutureまでですからね。一般的なPublisherに拡張しようとするとyield/generatorが必要になってくる
9:18 AM
それら全部をちゃんと提供するとなると重すぎなので一旦Resultになる、と言うのは理解できます
Avatar
ですねー。
9:19 AM
Result だとサクッと入れられるし、 async/await や Typed Throws ですら Result と比べると相当重いアップデートですし。
9:25 AM
ResultFailure == Never のときに keypath member lookup あると便利そうじゃないですか?
9:25 AM
@swift-5.2.5 @dynamicMemberLookup enum MyResult<Success, Failure: Error> { case success(Success) case failure(Failure) subscript<T>(dynamicMember keyPath: KeyPath<Success, T>) -> T where Failure == Never { switch self { case .success(let value): return value[keyPath: keyPath] } } } struct User { var name: String var age: Int } let user: MyResult<User, Never> = .success(User(name: "Name", age: 42)) print(user.name)
Avatar
swift52 BOT 9/1/2020 9:25 AM
Name
Avatar
さらに逃げの方向ですが。
Avatar
これを公式に出すならResult<T, Never>をTに暗黙変換出来るようにしてしまったほうが筋が良いように思える
Avatar
変な暗黙変換が加わるのは嫌ですねぇ・・・。 Result はエラーハンドリングにおいてサブ的な位置づけだし。 keypath memberlookup はやりすぎとしても、最初に書いた try なしの get は標準でできて良いと思います。 (edited)
Avatar
ちゃんと言語化出来ていなかったと思うので、もう一度説明すると
  • Result<T, Never>とTを暗黙変換するのは流石にきついものがある
  • しかしResultを無理くり拡張するのは暗黙変換より筋が良いかと言うと…
  • 故に、Resultを返す側のIFとして、Failure==Neverのときは直接Tを返すインターフェイスのオーバーロードであったほうが末端の利用者にとっては嬉しい場面が多そうだ。
  • のでnot throwsのget()が存在しないんじゃないか
という推論です。でもCombineのextensionとか見てると、not throwsのget()はproposal書けば案外すんなり通るんじゃないかなとも思えてきました。
(edited)
7:48 AM
例えばこんな感じで、Resultを返す方にdisfavoredOverloadをつけておけば、NeverのときにResultでないTを優先出来たりするので。 struct MyClass<T, Failure: Error> { @_disfavoredOverload func getResponse() -> Result<T, Failure> { fatalError() } } extension MyClass where Failure == Never { func getResponse() -> T { fatalError() } } let t = MyClass<Int, Never>().getResponse()
7:48 AM
Resultが欲しい場面はクロージャの引数とかなんですが、同じ使い方で成り立つ (edited)
Avatar
ふと思ったけど、 func on(_ queue: DispatchQueue) async { await suspendAsync { continuation in queue.async { continuation(()) } } } みたいな関数を作ったら、 func foo() { let x = await bar() await on(.main) self.label.text = x } みたいなことできそう。
Avatar
yutailang0119 9/10/2020 9:28 AM
Kotlin Coroutinesっぽいみため (edited)
Avatar
よく考えたら、普通に DistatchQueue.asyncasync になりそう。 func foo() { let x = await bar() await DispatchQueue.main.async() self.label.text = x }
9:29 AM
でも await on(.main) の方が下記心地良さそう。
9:29 AM
@yutailang0119 Kotlin Coroutines と実質同じでしょうね。
😋 1
9:30 AM
Kotlin は await 相当のマークが要らないみたいだけど。
Avatar
Combine のこのメソッド、禁断の技使ってないですか?前に flatten で回避されたやつ。 https://developer.apple.com/documentation/combine/future/replacenil(with:)
5:54 AM
func replaceNil<T>(with output: T) -> Publishers.Map<Future<Output, Failure>, T> where Self.Output == T?
5:55 AM
where Self.Output == T? の部分。 Parameterized extensions https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#parameterized-extensions 代わりの。 (edited)
Avatar
昔は壊れたけど今は壊れなくなってる…?
Avatar
昔(によるけど)もできたけど、 ABI stability が達成できないからとかで Proposal 上げた人が取り下げた件があったと思います。
Avatar
自分もずっと flatten 使ってるけど禁断なんだろうか
Avatar
昔はArray<Array>以外から呼べて酷いコンパイルエラーが出てた記憶があります
Avatar
ふむ
12:41 PM
呼べて、コンパイルエラー?
12:41 PM
コンパイルエラーなら呼べない。
Avatar
IDE上で警告が出ないがコンパイルエラーが出る、だったかな
Avatar
補間候補に出てきちゃうってこと? (edited)
Avatar
そうそう
12:44 PM
何かdiscordで話題にしてた気がするんだよな〜
12:44 PM
野村さんいたはず
Avatar
あー、 tarunon さんが補完の話してたのなんとなく覚えてます。
2:28 PM
Forum の方は、これで flatten 実装できるって話になったけど、もし Parameterized Extensions が実現されたら ABI 変わっちゃうから今は追加しない方が良いのでは?みたいな話が出て取り下げられてたはず。
4:43 PM
なお野村さんは居なかったw
Avatar
omochimetaru 9/14/2020 9:45 PM
TLDR: I propose @StatementLifter. Hello. I've read this thread in broad strokes. And I've seen some interesting conversations about many new names. There are some good ideas, but I'm writing because I got a better idea from there. The name of function should be represent...
9:46 PM
Function Builderのレビュースレッドで、「Function Builderって名前は微妙じゃない?」という話題がずっと続いていたので、 自分でも考えて、「Statement Lifter」を提案してみました。
Avatar
Declarative Builder とか?
1:34 AM
単に @builder とかでもいい気も・・・。 (edited)
Avatar
omochimetaru 9/15/2020 9:20 AM
この機能自体はビルダーじゃないと思うんですよね。この機能を使うとビルダーが組めるよというだけで。
Avatar
これによって作られる型は builder なんじゃない? builder だという情報を付与する attribute の名前に builder が入ってても変じゃない気が。
Avatar
if文とかwhile文の評価結果を関数呼び出しに変換する機能であって、
11:47 AM
それをSwiftUI.ViewBuilderみたいなビルダーの構成につかうかどうかはユーザー次第と思うんですよね
11:49 AM
例えば、Kotlinの
11:49 AM
receiver closureという言語機能を使うと、HTMLBuilderが構成できるけど
11:49 AM
もし、あれにbuilder closureって名前が付いていたら違和感がある。 (edited)
Avatar
swift5.3だとまだFunctionBuilderでfor/whileは使えないんですね
Avatar
omochimetaru 9/17/2020 8:19 AM
あら
Avatar
if letswitch は使えるようになったんでしたっけ?
Avatar
ifletとswitch使えますね (edited)
🙂 1
8:45 AM
@resultBuilder になって再Reviewになりそうな気配がする。
Avatar
FunctionBuilderよりは良いのかな
Avatar
omochimetaru 9/24/2020 8:46 AM
そう思う
8:47 AM
構文変換する魔術について触れてない名前だから個人的には微妙だが・・・ (edited)
8:47 AM
まあ後続の人たちは resultBuilder でググって頑張ってって感じかな。
8:47 AM
(ただの builder は紛らわしいという指摘はあった )
Avatar
ブロック内を式指向に変換する、が正しい機能なのだよね
Avatar
omochimetaru 9/24/2020 8:48 AM
そう思う。
8:48 AM
文指向のSwiftにおいて式指向の魔法を解放する
8:48 AM
式指向にするだけじゃなくてそこに任意のフィルタ関数が挟まるからさらに複雑だけども。
Avatar
これで「if式無いんですか?」ってマウント取られた時に、「コンテキストを限定して使えますよ。まさかどこでも使えちゃうんですか?w」って返せるようになった
Avatar
omochimetaru 9/24/2020 8:49 AM
www
8:50 AM
ややこしい設計だと思うけど、そういうふうに言うとそれっぽいな。
Avatar
if 式ってなんでそんなに人気あんのかよくわかんないんですよね。巨大な式は可読性良くないし、小さな式なら三項演算子でいいし。
Avatar
omochimetaru 9/24/2020 1:06 PM
let a = { if ... { return 1 } else { return 2 } }() ↑これよく書くけどif式なら楽だなあとは思います
1:06 PM
このままなら三項演算子でいいけど、return 1 のところで 2文書きたかったりする。
Avatar
僕はそのパターンは let a: Int if ... { a = 1 } else { a = 2 } で書きます。 a がここで初期化されるのが保証されないというのはあるけど、普通に読めば読めると思う。
Avatar
omochimetaru 9/24/2020 1:08 PM
aが3回出てくるのが冗長で嫌いなんですよね。
1:08 PM
制御フローがチェックされてるから安全なのはわかるんですけど。
Avatar
return も冗長では?
Avatar
omochimetaru 9/24/2020 1:08 PM
それはそうですね。
1:08 PM
if - else じゃなくて、
1:08 PM
guard とかだと早期脱出の意味があったりして
1:08 PM
returnで書く意味も出てくるけど。
1:09 PM
値がないときにデフォルト値を構築するみたいな場合は、guard + return のほうがニュアンスが強まってわかりやすい事もある。
1:10 PM
あ、でもその形はそもそもif式にならないか?
Avatar
: Int を書かなきゃいけないというのはあるけど、三項演算子で書けないくらい巨大になるなら型が書いてあった方が読みやすいと思うし。
1:11 PM
guard については、 if で書く場合と比べて早期脱出を意味するという意味で比較対象になりうるとは思う。
Avatar
omochimetaru 9/24/2020 1:11 PM
Kotlinだったらif式と合わせてreturnも書かないですね。
1:11 PM
というかreturnだとif文を飛び越えて出ていっちゃう。
Avatar
最後の式が戻り値になるのも一長一短だと思うしなぁ。
Avatar
omochimetaru 9/24/2020 1:12 PM
うーんとだから、最初に書いた即時クロージャの書き方は、if式のマネごとで
1:12 PM
やっぱりif式よりはreturnの分で冗長。
1:12 PM
あーあと、
1:12 PM
koherの変数の左辺を3回書く方式は
Avatar
最後の式が戻り値になるのを全面的に受け入れた上で if 式導入するのはわかるけど。 (edited)
Avatar
omochimetaru 9/24/2020 1:12 PM
コピペしづらいんですよね。
1:13 PM
代入文の形になってると、別の変数の右辺値のところにコピペしても機能するけど、
1:13 PM
3回出てくると全部リネームしないと再利用できない。スニペットの環境に対する結合度が強い。
Avatar
if 式まるごとコピペするようなときは関数にするのが正解な気も・・・。
Avatar
omochimetaru 9/24/2020 1:14 PM
僕は結構
1:14 PM
設計をするまえに雑に書いて書きながら設計するんで
1:14 PM
そういう操作を結構やります
Avatar
なるほど。
Avatar
omochimetaru 9/24/2020 1:14 PM
最終的には関数に切り出すこともあるし、その場に残すこともあるけど
1:14 PM
最終形を見えない状態でガチャガチャ取り回しやすいコード片を意識しがち (edited)
1:16 PM
一度完成させた後に再利用したくなったときはコピペじゃなくて関数化ですね。
Avatar
参照型中心の言語でイミュータブルクラス中心だとどうしても式指向にならざるを得なくて、その一貫性の元に最後の式を戻り値にして return 省略を前提に if 式はわかるけど、
Avatar
omochimetaru 9/24/2020 1:18 PM
ああ、たしかに。
1:18 PM
値型だとvarが出てきて更新文が出てきますね。
Avatar
Swift みたいな値型中心の言語では話が違うから途中をすっとばして if 式というのは違うと思うから、「 Swift って if 式ないの?」っていうのは Swift 理解してないんだろうなという気持ち。
Avatar
omochimetaru 9/24/2020 1:19 PM
まあそれはそうですね。
1:19 PM
残念ながら現実は煽ってくるほどの知名度も無いと思う・・・ (edited)
😂 1
Avatar
そうかな
1:19 PM
結構私はScalaの民に言われる印象があって
Avatar
omochimetaru 9/24/2020 1:20 PM
ほう
Avatar
個人経験に基づくものかもだけど
Avatar
値型がない言語を使ってるとイメージしづらいだろうなとは思います。
1:20 PM
僕が Swift をやる前は絶対そっち側の意見だったと思うので。
Avatar
例えば三項演算子で解決出来ないシーンは結構あって
1:21 PM
if letが出てくると三項演算子だと!を使うことになってモニョいし
Avatar
プロパティの初期値とかはそうですね。 (edited)
Avatar
Arrayの要素において2から4個目の値が特定条件で切り替わる、みたいなシーンとか
Avatar
omochimetaru 9/24/2020 1:22 PM
そのケースは Optional.map にできんかな > if let
Avatar
欲しいな〜〜〜ってなることは結構ある
1:22 PM
あー確かに
1:22 PM
Optional1個なら確かにmapで良いんだけど
Avatar
if let ... else は無理かも? < map
1:23 PM
?? でいけるか。
Avatar
数個になったときにmapflatMapflatMapflatMapってやるのが
1:23 PM
読みやすいかは疑問
Avatar
omochimetaru 9/24/2020 1:23 PM
まあそうね。
Avatar
ifletはOptionalに対するdo構文の側面もあるので
1:23 PM
沢山使うならこっちの方が良いよね〜とか
Avatar
omochimetaru 9/24/2020 1:23 PM
mapよりはif let のほうが良いね。
Avatar
それが if で解決できないのって、プロパティの初期化とかを想定してますか?
Avatar
プロパティの初期化もそうだし
Avatar
let a: Int if ... { a = 1 } else { a = 2 }
1:25 PM
↑の形では書けないとき。
Avatar
Arrayの2番目から4番目…みたいなシチュエーションも
1:26 PM
クッソ冗長になる
Avatar
omochimetaru 9/24/2020 1:26 PM
Arrayの要素において2から4個目の値が特定条件で切り替わる、みたいなシーンとか
これは 三項演算子と [] 使ってflatMapするか
1:26 PM
varつかうか迷う。
Avatar
とにかく冗長になるっていうのがまぁヤなんですよね
Avatar
omochimetaru 9/24/2020 1:26 PM
でもif式でも、
1:27 PM
2個目の要素をなくすってできないんじゃない?
Avatar
例えばpropertyの初期値だと、宣言した箇所とinit内のifって分散しちゃうので
1:27 PM
素直にif式でやる場合はOptionalにしてcompactMapになりそう (edited)
1:28 PM
これがreturnBuilderなら、もう少し進んで
Avatar
そういうケースは resultBuilder が利いてきそうですね。
Avatar
Arrayの入れ子を宣言してflattenする、という構文に昇華できるので
Avatar
むしろ if 式よりもよさそう。
Avatar
かなり使いやすそうだな〜トか考えてます
1:29 PM
シンプルなif式では無いってところが、難しいポイントなんですが嬉しいところでもありますね
Avatar
omochimetaru 9/24/2020 1:30 PM
たしかに。
Avatar
でまあif式がなくって悲鳴を上げていたの
1:31 PM
例えば struct Foo { var bar = if let x = productionVersion { ... } else { } }
1:31 PM
凄ーくエッジケースではありますが
Avatar
omochimetaru 9/24/2020 1:32 PM
あープロパティの初期値の右辺値か。
Avatar
この辺とかもinitに分散して宣言と散けなくて済むとか
Avatar
omochimetaru 9/24/2020 1:32 PM
それは3回書けないね。
Avatar
色々な可能性があります (edited)
Avatar
omochimetaru 9/24/2020 1:32 PM
initで書くと2回書いて、検査はされる。
1:32 PM
(Optionalだとnilのままスルーされる事がある)
👉 1
1:33 PM
あれ微妙だよなあ
Avatar
まあOptionalはすくえないかもてすが…w
👉 1
Avatar
omochimetaru 9/24/2020 1:33 PM
Kotlinだと = null が必須なんだけど、
1:33 PM
こっちのほうがいいなあとよく思う。
Avatar
Optionalnil 初期化必須でいいよね。
1:33 PM
= nil って大したタイプ数じゃないし。
👉 1
Avatar
struct Container<Value> { var value: Value init(value: Value) { self.value = value } func withValue(action: (Value) -> ()) { action(value) } } var container = Container<Any>(value: "foo") container.withValue { value in print(value) container.value = "bar" print(value) }
10:05 PM
swiftc -O a.swift && ./aswiftc a.swift && ./a で結果が異なる (edited)
Avatar
最適化のバグっぽい。
Avatar
これvalueがclassへのポインタとかだったりするとcrashする模様 (edited)
11:18 PM
structじゃなくてclassでも起こる
11:18 PM
(発見者: 同僚)
Avatar
omochimetaru 9/25/2020 3:52 AM
あれ、これLoE違反のはず?
Avatar
とも思ったんだけど、どうだろう。mutating だったらそうだけど、value をコピーして渡しているから安全なはず?
Avatar
omochimetaru 9/25/2020 3:56 AM
withValueメソッドの呼び出しの間は Container に対する read access で、 クロージャの中の container.value への書き込みが write access だから、それがコンフリクトと思ったけど
Avatar
omochimetaru 9/25/2020 3:58 AM
withValueの実装まで見た場合はactionの呼び出しの間、Containerへのreadは終わってるから許されるやつか
4:01 AM
表示がbarになるって なかなかアグレッシブだな action の引数だけどコピー省略してポインタ共有になってるのか
Avatar
おー、globalでも...
Avatar
initasync にできない想定なのかな?まだ実装されてないだけ? @swift-main -Xfrontend -enable-experimental-concurrency struct Foo { init() async throws { fatalError() } } (edited)
Avatar
swiftNightly BOT 9/30/2020 4:51 AM
exit status: 1 with stderr:<stdin>:2:12: error: initializer cannot be marked 'async' init() async throws { ^~~~~~ (edited)
Avatar
↓こっちはできる。 @swift-main -Xfrontend -enable-experimental-concurrency struct Foo { func foo() async throws { fatalError() } } (edited)
Avatar
swiftNightly BOT 9/30/2020 4:51 AM
no output (edited)
Avatar
あれ?できない? コピペしたときに -emit-sil が含まれてただけだった・・・。 (edited)
4:55 AM
init を非同期にできるのは( Promise を使う JS とかではできない)おもしろい特徴だから是非入れてほしいところ。
Avatar
最初からできなくても後から拡張するでも全然いいと思うので、追々proposal上げるのが良いのでは
5:05 AM
互換性に問題はないはず
Avatar
まだ正式な Proposal 出てないですし、実装がまだなだけかもなので、 Proposal 出て init 入ってなかったら意見を上げたいですね。 (edited)
Avatar
omochimetaru 9/30/2020 5:35 AM
ですね
Avatar
swiftdepsをswiftmoduleに埋め込んでクロスモジュールでインクリメンタルビルドするやつ出てた https://github.com/apple/swift/pull/34196 (edited)
Cross-Module incremental dependencies are a new experimental mode of the Swift driver and frontend. Through a tight partnership between the two, we enable the driver to have far greater visibility ...
Avatar
Kishikawa Katsumi 10/8/2020 1:44 AM
これが標準で用意されるのはとてもいい
🙂 1
Avatar
探し方が悪いのかもですが、 API Reference の Int https://developer.apple.com/documentation/swift/int からたどって Comparable に適合しているパスを見つけられなかったんですが、 Int ってどの経路で Comparable に適合しているかわかりますか?
Avatar
Int
2:02 AM
FixedWidth Integer
2:02 AM
BinaryInteger
2:02 AM
Stridable
2:02 AM
Comparable
2:02 AM
で到達できましたよ。
Avatar
matt先生のswift-doc的なやつでグラフィカルに経路がわかると良さそうですね
2:11 AM
たとえばこんな感じで継承関係がビジュアライズされます https://swiftwasm.github.io/JavaScriptKit/JSObject/
Avatar
スマホだと見えない?
Avatar
ホントですね、スマホだと絵が出ないや
Avatar
見えないっぽいんや デスクトップモードにしてもスマホサイトだった
Avatar
いいね。
Avatar
Strideable😳
2:14 AM
integer 関連とか Numeric とかばっかり探してた・・・。
Avatar
strideableって不思議な型だなぁ
2:18 AM
stride関数を通すとSequenceになるんすね。そのままではSequenceではない。
2:21 AM
でもその定義から数直線上?に乗る事とか、差分の型と値の型が同一である事などが定められるのか
Avatar
stride といえば、最近 AtCoder 用にパフォーマンス計測しながらコード書いてるんだけど、 for k in 2 ... number / m { sieve[k * m] = true } っていうコードを for k in stride(from: 2, through: number / 2, by: 2) { sieve[k] = true } に書き換えたら乗算を減らせて速くなるかと思ったら激遅になっておどろいたんだけど、 Range<Int>ClosedRange<Int> の場合だけ特殊な最適化が行われてる? (edited)
2:23 AM
それとも + 2 と比べてインクリメントが速い? (edited)
Avatar
げきおそであれば、
2:25 AM
stridableによる抽象化のディスパッチコストな気がするな
2:25 AM
SILをみるとわかりそう
2:26 AM
インライン化と特殊化がされきってないんじゃないすかね
Avatar
多分、 Range の場合はイテレータとか消えて for (int i = 0; i < n; i++) とか相当になってるんだろうと予測してるんだけど
2:27 AM
stride の場合はイテレータで回してるのかなって。
Avatar
arcodrerはコンパイラオプションは見えるんですか?
Avatar
見れるんだけどどこだっけな
Avatar
同じビルドして手元で結果を観察するのが良いと思いますよ
Avatar
-Ounchecked なのは間違いない。
Avatar
予測だと間違いがあると知見にならないし・・・
Avatar
あ、激遅なのは XCTest の measure した結果です。
2:28 AM
-Ounchecked で。
Avatar
なるほど
2:29 AM
あとは前者だけベクトル化できたとかかなぁ予想では・・・
Avatar
他には、下手に .lazy 使って無駄な Array の生成を防ごうとしたら遅くなったとか、色々おもしろい。
Avatar
そういうのぜひ調べてわいわいswiftcで話して・・・ (edited)
Avatar
たしかに SIL とか LLVM まで調べたらわいわいのテーマとしておもしろそうだね。
Avatar
sil最適化は何ステップも通して少しずつコード変形していくので
2:32 AM
これひとつ完全に調べるだけでかなりの事が出てきそう
Avatar
今度 Swift Zoomin' で競プロやるけど、わいわいの方が競プロと相性良さそうな気がする。
2:34 AM
最適化を考慮しまくって、過去問のある問題の最速を目指すとかおもしろそう。
Avatar
競技プロの会があるならそっちにも需要ありそうですね。 (edited)
2:35 AM
アルゴリズムが思いつくかどうかだけじゃなくて最速コードにする部分の競技性もあるんか。
Avatar
過去問でも提出して時間計測できるからおもしろい。 https://atcoder.jp/contests/abc138/submissions?f.Task=&f.LanguageName=&f.Status=&f.User=koher
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
Avatar
へえー
Avatar
わいわいのみんなで誰が最速を叩き出せるかやってみたらおもしろそう。
2:38 AM
全ユーザーの最速も見れるから、 C++ の最速にどこまで迫れるかとか。
Avatar
@swift-5.3.3 @swift-5.2.5 @swift-5.1.5 func primes(upTo number: Int) -> [Int] { precondition(number >= 0) if number < 2 { return [] } var sieve: [Bool] = .init(repeating: false, count: number + 1) for m in stride(from: 3, through: Int(Double(number).squareRoot() + 1.5), by: 2) { if sieve[m] { continue } let maxK = number / m if maxK < 2 { continue } for k in 2 ... maxK { sieve[k * m] = true } } var result: [Int] = [2] for m in stride(from: 3, through: number, by: 2) { if sieve[m] { continue } result.append(m) } return result } print(primes(upTo: 100))
Avatar
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Avatar
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Avatar
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Avatar
↑のコードを AtCoder の実行環境 https://atcoder.jp/contests/practice/custom_test で実行すると、 import Foundation がないとコンパイルエラーになるんだけど、どういう状態だろう? Swift 5.2.1 だけど、 5.2.1 特有のバグ?そんなバグありましたか?それとも実行環境が特殊?
10:38 AM
↓ 5.2.1 でも実行できたから AtCoder の環境が何かおかしそう? https://swiftfiddle.com/wg6dv2tpofhjdlw3q6zyv46thi (edited)
10:42 AM
↓で実行されてる模様 swiftc -Ounchecked -o {dirname}/a.out {dirname}/{basename} {dirname}/a.out https://atcoder.jp/contests/language-test-202001
Avatar
リンクに失敗してるみたいですね
10:44 AM
libcがリンクされてないっぽい?
10:46 AM
おー再現しました
Avatar
squareRoot って標準ライブラリですけど libc 依存なんですっけ?
Avatar
Kishikawa Katsumi 10/19/2020 10:52 AM
AtCoderの環境がSwift.orgがダウンロード提供してるものとは違うっぽいすね。
Avatar
Swift stdlibは特に断りなくlibcには依存してると思います
Avatar
実装を追っていったところLLVM intrinsic instructionのllvm.sqrt経由でlibmに依存してるみたいです
Avatar
intrinsic経由なんだ。
Avatar
swiftCoreに対してはautolinkの仕組みが効かないからこういうことになるのか
Avatar
どういうことなんだ
Avatar
えーと
11:00 AM
Mach-Oにはオブジェクトファイルの仕様としてautolinkの仕組みがあって、オブジェクトファイルに記述されたライブラリをリンカが読んで自動でリンクするんですけど、 (edited)
11:01 AM
ELFはそういうリンカとコンパイラの間のコンベンションが無いので、Swiftは勝手にELFオブジェクトファイルにautolinkセクションを作ってリンカオプションを書いて、
11:03 AM
ドライバがリンカへ渡す入力全体に対して、swift-autolink-extractでautolinkセクションを読んでリンカオプションを集めて、リンカに渡す、っていう仕組みになってるんですけど、
Avatar
ふむふむ
Avatar
リンカにオブジェクトファイルと一緒に渡されるswiftCoreは特別扱いされていて、リンカオプションがハードコーディングされていて、ドライバ的にリンカの入力の一つとして扱われているわけじゃないので、autolink-extractが走らないんですよね。 https://github.com/apple/swift/blob/main/lib/Driver/UnixToolChains.cpp#L302
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
11:07 AM
なのでswiftCoreが外部のシンボルに依存している、かつそのシンボルがclangリンカドライバが自動で挿入するライブラリに含まれていない場合リンクに失敗すると思います。
11:07 AM
libcはclangリンカドライバが自動で挿入するけどlibmは挿入されない。 (edited)
Avatar
ドライバ的にリンカの入力の一つとして扱われているわけじゃないので、autolink-extractが走らない
はは〜ん
11:08 AM
めちゃくちゃ細かいバグだね
Avatar
ドライバ博士
Avatar
swiftの技巧としては追記していく配列にContiguousArrayを使うだけで速くなります (edited)
11:39 AM
for-inの所はwhereつけて2の倍数を除外 遅くなってた (edited)
11:40 AM
for m in (3...number) where !m.isMultiple(of: 2) (edited)
👀 1
Avatar
なのでswiftCoreが外部のシンボルに依存している
これについては
実装を追っていったところLLVM intrinsic instructionのllvm.sqrt経由でlibmに依存してるみたいです
ということは、 squareRoot については内部で libc の sqrt に依存してて、環境に寄らないですよね?ということは、
かつそのシンボルがclangリンカドライバが自動で挿入するライブラリに含まれていない場合リンクに失敗すると思います。
この「自動で挿入するライブラリに含まれ」るかどうかが環境に依存してて、 AtCoder は含まれない環境ってことでしょうか?
1:45 PM
おそらく、 Docker か何かのコンテナの上で実行されていると思うんですが、利用しているイメージがそのような環境になってる?
Avatar
OSがどのlibcを提供しているかによるんですかねぇ
1:46 PM
少なくとも手元のLinuxマシンでは再現しました (edited)
Avatar
え、再現って何か手を加えたわけじゃなくて普通に起こったんですか?
Avatar
ですです。
Avatar
swiftbot や SwiftFiddle では起こってないから、何が違うのか知りたいですね・・・
1:49 PM
とりあえず AtCoder だと import Glibc 付けとくのが良さそう。
Avatar
とりあえず手元の環境はこれです FROM ubuntu:20.04 RUN apt -y update # Install development utils RUN DEBIAN_FRONTEND=noninteractive \ apt install -y wget tar vim openssh-server sudo tmux lldb \ git cmake ninja-build \ clang python uuid-dev \ libicu-dev icu-devtools \ libedit-dev libxml2-dev \ libsqlite3-dev swig libtinfo5 \ libpython2-dev libncurses5-dev \ pkg-config libcurl4-openssl-dev \ systemtap-sdt-dev \ tzdata rsync python-six \ libncurses5 \ libz3-dev python3-distutils
🙏 1
Avatar
AtCoder で↓を実行してみたんですが、 import Foundation let processInfo: ProcessInfo = .processInfo print(processInfo.operatingSystemVersionString) 結果は↓でした。 Ubuntu 5.4.0-1025.25~18.04.1-aws 5.4.60
Avatar
お、前に言語実行環境の募集があったんですが、↓のように書かれてました。(この通りに行われているかはわかりません。) "適宜sudoをつけてください apt install clang libicu-dev libpython-all-dev wget https://swift.org/builds/swift-5.1.3-release/ubuntu1804/swift-5.1.3-RELEASE/swift-5.1.3-RELEASE-ubuntu18.04.tar.gz tar xvfz ./swift-5.1.3-RELEASE-ubuntu18.04.tar.gz mv ./swift-5.1.3-RELEASE-ubuntu18.04/usr {install_dir} export PATH={install_dir}/usr/bin:""${PATH}"" # パスを通す" https://docs.google.com/spreadsheets/d/1PmsqufkF3wjKN6g1L0STS80yP4a6u-VdGiEv5uOHe0M/ (edited)
4:32 PM
(↑では 5.1.3 になってますが、実際には 5.2.1 です。)
Avatar
Kishikawa Katsumi 10/20/2020 1:02 AM
普通にSwift.orgの手順通り提供されているのを ダウンロードしてるだけっぽいですねえ。
1:02 AM
なんで違いが出るんだろう
Avatar
swiftcを使うとリンクエラーになりますね。ボットはswiftを使ってる。 $ pbpaste|docker-swift-run swiftc -Ounchecked - /tmp/--90f083.o:--90f083.o:function $s4main6primes4upToSaySiGSi_tF: error: undefined reference to 'sqrt' clang-10: error: linker command failed with exit code 1 (use -v to see invocation) <unknown>:0: error: link command failed with exit code 1 (use -v to see invocation) $ pbpaste|docker-swift-run swift -Ounchecked - [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97] (edited)
Avatar
Kishikawa Katsumi 10/20/2020 1:31 AM
あ、なるほど!納得しました。
1:32 AM
swiftcで一回コンパイルしないとビルド時間と実行時間分けられないですしね。
Avatar
なるほど。 swiftc だとダメなんですね。
2:01 AM
ボットも swiftc かと思ってました。
Avatar
demangleとかも呼べる様にswiftなのです。 @swift-5.3.3 demangle $s4main1aSivp
👀 1
Avatar
$s4main1aSivp ---> main.a : Swift.Int
Avatar
なるほどswift コマンドでimmediateモードで走らせるとLLVMのJITで実行されるからllvm.sqrtがlibmのシンボルに依存しない形で実行されるのか (edited)
👀 1
Avatar
‾ (overline, U+203E) and _ (low line, U+005F) have a good upper-lower relationship. The downside however is that ‾ is a bit harder to type.
4:25 PM
型として不明な型を表す_を導入する提案
Avatar
Rust的なやつ?
Avatar
左辺値の明示的な型指定をするときに、ResultやPublisherの右側だけ指定して、左側は_にするなどの使い方ができる
4:26 PM
推論器が右辺値から左側だけは推論機できるが右側は推論できない、みたいなときに、
4:26 PM
推論できない方だけをアノテートすればよくて便利
4:27 PM
スレの序盤でドーグとラトナーが良いねって言ってる
4:27 PM
Rustのは知らないからわかんない〜
Avatar
おー、見た感じRustの型パラプレースホルダーと似た感じっぽいですね
4:28 PM
これは良さそう
Avatar
SwiftUIでややこしい型が出てくるようになったからニーズが高まったらしい
4:28 PM
個人的におもしろいと思ったのはこの機能を作るときに推論エンジンに大きな改修は要らない点
4:29 PM
たんに_を型変数としておいて推論させたら良いだけ!
Avatar
複雑な型パラを省略するという面ではORTと似てるけど全く違うアプローチで面白い
🦀 1
Avatar
Javaにもあったような
Avatar
Javaはそもそも型推論が無いよ(厳密には少しあるけど
Avatar
ビルド時間は伸びないんですかね?
Avatar
他の型推論と同じで推論箇所が増えると少しは伸びると思います
👌 1
Avatar
やはりそうですよね。仕事で書いてるコードのビルド時間がそれはもう長くて気になってしまいました🙄
Avatar
でもこの機能は「全く与えない」と「完全に与える」の間の「一部欠けた型を与える」機能を提供するものなので
5:17 AM
使い所を間違えなければデメリットは気にならないと思います、そのときは今まで通り完全な型を書けばよい。 (edited)
5:18 AM
推論が重くない時に楽するための追加機能って感じ。
5:18 AM
仕事で書いてるコードのビルド時間がそれはもう長くて
これ使って型推論が重い部分を調べると良いですよ https://dev.classmethod.jp/articles/investigated_compiletime_swift/
Avatar
たしかに、時と場合で使い分けが重要ですね。情報ありがとうございます。遅いところ調べてみます。
Avatar
Swiftの推論は、全体的に遅いってことはあんまりなくて、
5:39 AM
特定のパターンでいきなり1000倍重くなるみたいな感じなので
👀 1
5:39 AM
そういう急所を直せると良いです。
Avatar
Int(S_IRUSR) | Int(S_IWUSR) | Int(S_IRGRP) | Int(S_IWGRP) | Int(S_IROTH) | Int(S_IWOTH) を思い出した
Avatar
それ!
Avatar
オーバーロードされてるやつだ
Avatar
51でりんたろさんの書いてる _() でinitできる説おもろ
Avatar
https://github.com/apple/swift/pull/34523 protocol extension のスタティックメンバーがプロトコルのメタタイプから呼び出せるようになる! protocol P {} struct S: P {} extension P { static var bar: S { S() } } func foo<T: P>(_: T) {} foo(.bar)
Avatar
おお?それS見つけられるの凄い気がする
7:54 AM
推論されてるのP.barじゃなくてS.barですよね? (edited)
Avatar
P.bar ですね。現状では P.bar はそもそも使えない (Static member 'bar' cannot be used on protocol metatype 'P.Protocol') けどそれが使えるようになって、さらにコンテクストタイプが : P の時に implicit member expression で参照できる (edited)
7:57 AM
Swift's dot shorthand for static factories is wonderful! Unfortunately, it currently requires a concrete type context in order to work. A while ago I pitched an idea for lifting this limitation. It turned out that the original idea in that pitch isn't viable, but the thread ...
Avatar
protocol P { associatedtype Arg } struct S: P { typealias Arg = Int } extension P { static func bar(x: Arg) -> S { S() } } func foo<T: P>(_: T) {} foo(.bar(x: 12)) なので、たぶんこれは無理と思います。
Avatar
ああー、そういうことか
8:08 AM
あれ、でも、.barで見つけられるのって、返り値の型とレシーバの型が同じ時じゃ?
8:10 AM
レシーバはany Pで返り値はSですよね
Avatar
class B { static var c: C { C() } } class C: B {} func foo(_: B) {} foo(.c) ルール的にはレシーバのサブタイプなので、矛盾はしてないかな?
Avatar
なるほど
8:20 AM
SwiftUIで辛いことになってたStaticMemberのやつができるようになるの大きいですね
Avatar
Pにstaticメソッド定義できるのネームスペース兼ねられて便利そう inner typeが定義できないか
Avatar
any Pがstatic methodの実装を持てるなら、any PがPにconformできない理由が一つ減るな
9:14 AM
もはやexistential metatype containerでは無くなってて変な感じ
9:20 AM
P.Typeとの話だからいいのかな?
9:22 AM
P.Protocolとどっちがどっちだったっけ
9:23 AM
このへんかな
🙏 1
Avatar
P.Protocolにstatic funcが生やせるようになった これによってP.Protocol.self is P.Typeにできない理由が緩和された かな?
Avatar
タプルの Equatable とかのやつ、 AdditiveArithmetic とか Numeric もほしくなる。標準で付けるのは微妙だけど、コンパイラでやらないとできないし・・・。
Avatar
タプルの要素の型すべてがあるprotocolが準拠してたら、そのタプル自身も準拠するようにしてほしい感があります
5:36 PM
どうなんだろ
Avatar
それはちょっとやりすぎな気も。↓とかできるってことですよね? protocol P { associatedtype Foo func foo() -> Foo } extension Int: P { func foo() -> Int { self * self } } let a = (2, 3, 5) print(a.foo()) (edited)
Avatar
それはタプル側のfooの実装が自明じゃなさそうですよねー
Avatar
ってか、よく考えたら無理ですね。 protocol P { func foo() -> Int } extension Int: P { func foo() -> Int { self * self } } let a = (2, 3, 5) print(a.foo())
1:11 AM
↑だと (Int, Int, Int).foo()Int を返さないので。
Avatar
なるほどなあ
Avatar
AdditiveArithmeticは横ベクトル同士の自然な加減算があるのでできなくはなさそうですよね
Avatar
omochimetaru 12/2/2020 6:26 AM
なんかいろいろproposal review走ってるな
6:26 AM
Hello Swift community, The review of SE-0295 "Codable synthesis for enums with associated values"" begins now and runs through Dec 11, 2020. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager....
6:27 AM
Structure of encoded enums The following enum with associated values enum Command: Codable { case load(key: String) case store(key: String, value: Int) } would be encoded to { "load": { "key": "MyKey" } } and { "store": { "key": "MyKey", "value": 42 } }
6:27 AM
これはいつもめんどくさかったから嬉しい
Avatar
いつも手書きしてるやつだ
Avatar
たすかる
Avatar
自分で書くときはこうやりがち { "kind": "store", "key": "MyKey", "value": 42 }
Avatar
decodeするときに困りますもんね
6:31 AM
その辺よしなにやってくれるのかな(直感的にパフォーマンス悪そう
Avatar
omochimetaru 12/2/2020 6:32 AM
エンコード方式いろいろ悩んでて
6:33 AM
{ "kind": "store", "value": { "key": "MyKey", "value": 42 } }
Avatar
名前空間汚さないパターンだ
Avatar
omochimetaru 12/2/2020 6:33 AM
家庭君の書いたやつでやったこともあるし、↑これもやったし、
6:33 AM
このproposalのやつもやった。
6:34 AM
そうね>名前空間
Avatar
proposalの形式だとデコードどうやってますか?
Avatar
omochimetaru 12/2/2020 6:35 AM
enum Command { struct JSON: Codable { var load: Load? var store: Store? } }
Avatar
なるほど
Avatar
omochimetaru 12/2/2020 6:35 AM
いったんこういうstructでcodableする。
6:35 AM
これにした理由の一つが、
6:36 AM
TypeScriptの type 文で 相互に受け渡すのが楽だった。
Avatar
type JSON = { load: { key: string } } | { store: { key: string, value: number } } こういうことですか?
Avatar
omochimetaru 12/2/2020 6:38 AM
type JSON = { load?: { ... } store?: { ... } } いやこっち
6:39 AM
たしかにunionでそれでいいのかな
Avatar
いや、このunion取り出せないw
Avatar
omochimetaru 12/2/2020 6:39 AM
取り出せないっすか?
Avatar
これ困るパターンの予感
Avatar
omochimetaru 12/2/2020 6:39 AM
そのあたり、まだよくわかっていないので、↑のenumになってない書き方をした。
Avatar
loadとstoreを逆側にundefinedで定義すると
6:40 AM
!==undefinedで取り出せるようになります (edited)
Avatar
なるほど
Avatar
omochimetaru 12/2/2020 6:40 AM
全ケースにあるプロパティじゃないと取り出せなくて、それを使ってsmart分岐する感じなのか。
Avatar
でもTSでTagged Unionするなら
Avatar
omochimetaru 12/2/2020 6:40 AM
いまいちめんどくさいね。kind: string つけたほうが楽やな。
Avatar
プロパティがあったり無かったりすると死にがち
Avatar
そうそう
Avatar
omochimetaru 12/2/2020 6:41 AM
そうするとSwift側でいうとkind付きのcase名プロパティのパターンだね。 (edited)
Avatar
コツとしては一通り定義して無ければundefinedにしておく
Avatar
Rustのserdeのデフォルト形式はcase名をキーにするっぽい (edited)
Avatar
omochimetaru 12/2/2020 6:43 AM
じゃあそれと相互運用しやすい?
Avatar
どうだろう。。
6:45 AM
微妙に互換性がないって言ってた
With the exception of the last case, this solution is closely following the default behavior of the Rust library serde.
Avatar
omochimetaru 12/2/2020 6:58 AM
ラベルなしの場合に配列になるのね
Avatar
TypeScriptで読みづらそう
Avatar
omochimetaru 12/2/2020 7:02 AM
TypeScriptと受け渡すなら絶対ラベルはつけておいて
7:02 AM
kindはないから↑で書いたunionじゃないstructの形で受けるかな
Avatar
それしか助からなそう
7:04 AM
でも大抵のユースケースではSwiftからEn/Decodeするだけだからまあいいか…
Avatar
omochimetaru 12/2/2020 7:05 AM
まあTypeScriptでtypeで受けるのもそもそもサボりかなとは思っている
7:05 AM
ちゃんとencode/decodeを挟まないと
7:06 AM
URI 型とか TypeScript側でただの string になっちゃう。
Avatar
なるほど
Avatar
omochimetaru 12/2/2020 7:06 AM
User.ID 型とかも。
Avatar
クライアントもSwiftならまるっと解決 (edited)
Avatar
omochimetaru 12/2/2020 7:10 AM
いやそうなんだよな
Avatar
JSONを構築する側とパースする側が別れてる場合、大抵Swiftはパースする側なのでおもちさんのユースケースはそもそも特殊w いや、全然そんなことなかった。 (edited)
Avatar
omochimetaru 12/2/2020 7:16 AM
API request送る時はまあ同じかな
Avatar
アプリ書かなさすぎてすっかり忘れてたw
Avatar
omochimetaru 12/2/2020 7:17 AM
アプリSwift<->サーバサイドSwift はこれのおかげで更にはかどってしまう
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
9:18 AM
configurationによる制約の方の状況がよくわからない…
Avatar
@koher 僕の理解だと(fとgは) async let a = f() async let b = g() await h(a, b) は並行で await h(await f(), await g()) は直列 後者のような書き方で並行になってほしい 変数/定数に入れたくない
9:40 AM
@masakihori fooとbarがasync funcとして、 await (foo() + bar()) // 並行 (await foo()) + (await bar()) // 直列 とかだと良かったかもですね。ただ、tryとの整合性の問題で今からだと難しそうです。
9:41 AM
try と整合性が取れなくなってしまうけど、わざわざ async let で代入しなくても前者の書き方で並行になってくれたらうれしい?
9:41 AM
try との整合性」というのは https://gist.github.com/koher/ca74ef2c882418f683d06092f4408c3c のような意味です。 (edited)
Avatar
他のところで無限に面倒が発生しそう
11:52 AM
これはtsを書いてる感想ですが、向こうは都度await明記しなきゃいけないんで既にだるい。並行並列の機能があったら許せるかと言うとそんな事はないぐらいに怠いので
11:52 AM
1個await書けばその行はオッケー!というのは、大半のユースケースにおいて便利なので、それが壊れるのは微妙かなぁ
11:53 AM
まで書いて、koherさんの真意を確認しにいく (edited)
11:53 AM
あってそう
Avatar
そう考えると async let で 1 回代入挟むくらいがバランス良さそうですね。
Avatar
僕はasync/awaitちゃんのことは噂では聞いてたけどお話ししたのはKoherさんに紹介された時が初めてなので、全然分かってないし、誤解とかもいっぱいあると思うのであまり真面目にとらえられると困っちゃいます
😭 1
Avatar
ところで私がコンフリクトするな〜と感じたのは、例えばメソッドチェーンでasyncな関数を呼ぶ時で
2:31 PM
async foo() async bar()を呼ぶ時に await hoge.foo().bar() って呼べるので嬉しい、これがコンフリクトしそうだなと
2:32 PM
或いはasyncな関数の引数に別のasyncの結果を渡す場合 await hoge.foo(bar()) みたいなの (edited)
2:33 PM
どちらも結構頻出で、やっぱり所感としては並列より直列の方が多いんですよね。8割ぐらい直列。なので直列の使いやすさを上げるから並列は多少犠牲にする、みたいなのも割と納得だなとは思っています
Avatar
omochimetaru 1/27/2021 2:37 PM
並列かどうかが明示的な文法として表現されないのは事故(思わぬ並列化による深刻なバグ)につながるのは良くないと思います。
2:38 PM
async let は一見わかりにくいけど、文法として新しいコードの形になっている(これまでの文法として、letの左にasyncは書けない)ので、暴発することはない。 (edited)
Avatar
omochimetaru 1/27/2021 3:32 PM
await でまとめた式は並列になる」は、async/awaitで新しく導入されるといっても、「await がついてない部分について実行順序の挙動が変わる」のは、 これまでと変化がある部分に対して見た目の変化がないのでわかりづらいと思う。
Avatar
チーム勉強会で async let の話があったので、まとめるとこうなります
Avatar
Avatar
Kishikawa Katsumi
なのでfileprivate使わないなあ、と思いまして。あえてfileprivateじゃないと書けないことってあったっけ?と思って、そうすると、なんで変えたんだっけ?とわからなくなってきました。
これ、この会話の後でたしかに fileprivate 書かなきゃいけないケースってあまりないなと思ってたんですが、↓のようなケースで fileprivate でしか書けなさそうなのを発見しました。 struct S {} private struct T {} private protocol P { func foo() -> T } extension S: P { fileprivate func foo() -> T { T() } }
5:46 AM
Protocol Conformance にアクセスレベル修飾子を書けないという方が本質かもしれませんが・・・。
Avatar
Kishikawa Katsumi 2/1/2021 6:00 AM
なるほど!おもしろい。
Avatar
Swift 5.2.1 で let s = readLine()! let a = (0..<2).map(s.dropFirst).count を実行して 11111111111111111 など 15 or 16 文字以上の文字列を標準入力として与えると -O または -Ounchecked 時に実行時エラーになるそうです。気持ち悪い・・・。 https://twitter.com/_kebo/status/1357011619440599044
以前 AtCoder を Swift で解いているときにぶち当たった特定の環境で特定の条件下で最適化時のみ発生する実行時エラー (Segmentation fault または Illegal instruction) になるコード、どうやら Ubuntu 18.04 の 5.2.1, 5.2.5 では再現するけど 5.3.3 では再現しないことがわかった。
Avatar
Avatar
koher
Swift 5.2.1 で let s = readLine()! let a = (0..<2).map(s.dropFirst).count を実行して 11111111111111111 など 15 or 16 文字以上の文字列を標準入力として与えると -O または -Ounchecked 時に実行時エラーになるそうです。気持ち悪い・・・。 https://twitter.com/_kebo/status/1357011619440599044
そうなんですよね。koher さんがリプライで書いてくださっていた s.dropFirst を変数に束縛するのでも再現しなくなるみたいですし、{ s.dropFirst($0) } のようにクロージャにしても再現しなくなりますし、あとは (ちゃんと記録してませんでしたが) 形を変えて行った時にどこかで二重解放の実行時エラーが出ていたので、s が解放されちゃいけないタイミングで解放されているのかなぁという気がしてます。 かといって withExtendedLifetimes のライフタイムを伸ばしても変わらなかったので、何処かの最適化フェーズに問題があったのではと睨んでます。
4:12 AM
5.3 で再現しなくなったので意識して修正された問題だとしたら apple/swift のコミットログを追うとそれっぽいのがあるかなと思って昨日見ていたんですが、ざっと探したかぎりではそれっぽいのはありませんでしたね...
Avatar
意図せず直っただけならそれはそれで怖いですね・・・。
Avatar
そうなんですよねぇ...
Avatar
15 or 16 文字以上とか、標準入力じゃないと起こらないとか、変数に一度代入すると起こらないとか、再現条件めちゃくちゃすぎて笑えますね😅
Avatar
バグレポ送っときましょ
Avatar
Avatar
tarunon
バグレポ送っときましょ
過去バージョンでしか再現しないのでバグとして報告して良いものなのか迷ってました。
Avatar
把握せずにたまたま治っただけ、だと再発して困るので
5:42 AM
このバージョンで発生していたが新しいバージョンでは治っている、と言うレポートで良いのではないでしょうか
👍 1
Avatar
omochimetaru 2/4/2021 5:42 AM
確かにバグレポあるとリグレッションテストが追加されて後々も保護されるので良い
Avatar
上記の議論を見る限りは結構ディープな奴なので、報告した方が良い
Avatar
言われてみるとおっしゃる通りですね。bugs.swift.org に報告しようと思います。
Avatar
Protocol extension で mixin するのってわりとやられている手法かな?
Avatar
omochimetaru 2/9/2021 6:09 AM
やると思う
Avatar
派生を封印してmixinだけでとかはあるか。
Avatar
この前の問題のバグレポートを出してみました。下手にミニマムな再現コードを用意しようとしたせいで挙動が変わったので結局元の冗長なコードでの実行例も載せることになって見辛いかもしれないですが... https://bugs.swift.org/browse/SR-14202
👏🏼 3
Avatar
Avatar
kebo
この前の問題のバグレポートを出してみました。下手にミニマムな再現コードを用意しようとしたせいで挙動が変わったので結局元の冗長なコードでの実行例も載せることになって見辛いかもしれないですが... https://bugs.swift.org/browse/SR-14202
結局 5.3 では解決してるからってことでクローズされちゃいましたね。やっぱり古いバージョンでしか再現しないバグは基本的に受け付けてもらえなさそうですね。
😢 2
Avatar
https://discord.com/channels/291054398077927425/430242233468452865/813326991989538826 同じコードがmacでは問題なく動くのですが、どこかおかしいところあるでしょうか?
Avatar
availableDataが最後空で呼ばれるかどうかがLinuxとMacで違うとか?
Avatar
concurrentPerform の引数を1にするとわかりやすいんですが、最後に0のデータが来るかどうかがランダムなんですよね。
8:43 AM
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
Avatar
printが出力されてないのはバッファがフラッシュされてないからなので頭に「おまじない」をしてバッファ経由しないようにするとdebugできる?
9:02 AM
// おまじない func print(_ item: String) { fputs(item + "\n", stderr) }
Avatar
Avatar
masakihori
printが出力されてないのはバッファがフラッシュされてないからなので頭に「おまじない」をしてバッファ経由しないようにするとdebugできる?
出せました。(字数制限かかるのでstderrの取得部分を省略しました)
Avatar
Foundationのコードを真似たらうまく動くようになりました。 SOの回答で availableData が空だったらEOFだからhandlerをnilにするってのを何件かみたんですが、 ドキュメントだと使い方が不明瞭ですね……低レイヤなれてる人なら常識なのかもしれませんが。 https://developer.apple.com/documentation/foundation/filehandle/1412413-readabilityhandler https://developer.apple.com/documentation/foundation/filehandle/1411463-availabledata availableData が空ならEOFというのは合ってそうですが、readabilityHandlerのほうはEOFが来ることを保証していないような気がする。
9:24 AM
readToEnd はmacOS10.15.4からなのにPackage.swiftでは.v10_15 しか指定できない……
Avatar
omochimetaru 2/22/2021 9:25 AM
#ifの分岐ならできるんじゃ?
9:26 AM
それ以前ではdeprecatedなメソッドを使う
Avatar
omochimetaru 2/22/2021 9:28 AM
waitが終わったらコールバック外してから改めて吸い出すのかなるほど
Avatar
omochimetaru 3/10/2021 2:27 AM
Hello! I’m YR Chen from University of Science and Technology of China, majoring in Computer Science. I’ve been using Swift for a long time (mostly in server side) and starting last year I began to contribute codes to Swift and other projects. My works include a simple Swift toolchain management script for Linux, and a forked version of swift-aws...
2:28 AM
スクリプティングに立候補してる人が居る
Avatar
すごい、日本で言う東工大レベルの人だ 👀
Avatar
omochimetaru 3/10/2021 8:16 AM
他のOSSの活動とかテンセントの仕事とかも凄い
Avatar
個人的に米中貿易戦争の飛び火でIT周りが分断されて、所謂「西側スタンダード」と「中国スタンダード」ができてしまって中国からSwiftのコントリビュートが制限されたりするじゃないのってすごい怖かったですけど、とりあえず国立大学でまだSwiftのコントリビュートができるの見てちょっと一安心です 😅
8:23 AM
言っても中国からGitHubまだアクセスできるけどなぜかSpeakerDeckがアクセスできないんですよねw
Avatar
Avatar
lovee
個人的に米中貿易戦争の飛び火でIT周りが分断されて、所謂「西側スタンダード」と「中国スタンダード」ができてしまって中国からSwiftのコントリビュートが制限されたりするじゃないのってすごい怖かったですけど、とりあえず国立大学でまだSwiftのコントリビュートができるの見てちょっと一安心です 😅
omochimetaru 3/10/2021 8:30 AM
たしかに・・・。中国の人たちがGitHubでテクニカルなコードを結構上げたりしてるし、そういう分断はおきてほしくないです
8:31 AM
TikTokとかあるからなのか、iOSの動画処理のマニアックなの結構中国だったりする
Avatar
多分それだけじゃないと思います;まあ国際的に有名なのはTikTokですが、中国国内でも他に快手とか西瓜とかめっちゃ色々あります
8:35 AM
しかも中国5Gになった今でも未だに従量課金ですからね…(単価はだいぶ安くなってはいますが)やはりトラフィック気にする人が多いから、多分ライブストリーミングの圧縮アルゴリズムとかめっちゃ強そう
Avatar
omochimetaru 3/10/2021 8:48 AM
なるほどー
Avatar
SpeakerDeck は GitHub じゃなくなったからなあ (edited)
Avatar
まじで!?
Avatar
https://twitter.com/niw/status/1307488577106796544 そう、知らなくて、slide shareとか関係あんのかなあって言ったら作った本人から返事来た
今更だけど、@speakerdeck が売却されていたことを知った。Slide Share が Microsoft だからとかなのか。
👀 1
11:42 AM
議論がとっ散らかるとよくないのでサブタイプが存在することによって発生する大きな問題点を2つ、整理します。
11:45 AM
まず1つ目がサブタイプであるにも関わらず、実体が異なってしまうという点 var s = 1 var a: Int = s var b: Int? = s のaとbが異なるということですね。クラスサブクラス、あるいはExistentialと具体型の関係なら、これは同じものを指すわけです。(Existentialは厳密には異なるが省略) var s = Cat() var a: Animal = s var b: Cat = s この結果発生する問題として、 実態が異なっているということを知っているユーザーと知らないユーザーとの間で、期待する挙動に差が出てきます。例えば
11:46 AM
https://discord.com/channels/291054398077927425/375206337937801216/806433474579005440 最近発生したバグとされるこの挙動。 AnyHashableにInt?の値を入れた時に、Intを入れた時と異なってしまう、というバグ
11:46 AM
でもこれは、「いやいやそうは言っても .some(1)1 は別でしょ」っていう理解のユーザーからは、AnyHashableの値が異なることこそが期待される挙動なはずです。
11:48 AM
このOptionalであるか否かが同一かどうかというのは、文脈によっても期待される挙動が異なるので、ケースバイケースでコンパイラの挙動が変わることが期待されてしまう。
11:48 AM
片方を立てれば片方は立たなくなる、という問題の根源になりえるわけです。
11:48 AM
次 2つ目、サブタイプのルールづけに優先順位が必要という話。
11:51 AM
これは結構私は方々でぶーを垂れてるので知ってるかもですが、 TがT?のサブタイプである UがTのサブタイプであるならばU?はT?のサブタイプである この2点がSwiftでは許可されています。で、下のコードはコンパイルが通る。 var s = Cat() var a: Animal = s // CatとAnimalのサブタイプ関係が成り立つことを示す var b: Cat? = s var c: Animal? = b U?はT?のサブタイプ、は具体のコードとしては、 UITableViewController? な変数が UIViewController? に渡せる、というのが頻出すると思います。 (edited)
11:52 AM
もちろんOptionalは実体は別なので、暗黙的な変換が挟まるわけですが、どうなっているかというと
11:53 AM
var s = Cat() var a: Animal = s // CatとAnimalのサブタイプ関係が成り立つことを示す var b: Cat? = .some(s) var c: Animal? = b.map { $0 as Animal } mapのところは本当は違うと思うんですが、まあ雑にこんな感じ。 (edited)
11:54 AM
じゃあここに一行付け加えて、これはどうあるべきでしょうか。というのが問題になります。 var d: Cat?? = b // b: Cat?
11:55 AM
解釈としては2通りあって、 1. オプショナルのサブタイプなので.someでラップする 2. CatはCat?のサブタイプなのだから、.mapでOK
11:57 AM
今このコードだと、Cat?は.someなので結果は同じなんですが、Cat?が.noneだと、1,2のどちらを採用するかで結果が変わります。
11:58 AM
// 1. var d1 = .some(b) // 見たまま.some(.none)になります // 2. var d2 = b.map { $0 as Cat? } // これは.noneになります じゃあこれがどういう問題を引き起こしたかというと
11:59 AM
過去のSwiftではコンテキストの差によって2.の変換が採用されていた時代がありました。
12:01 PM
Avatar
なるほど
Avatar
以上2点がメジャーな問題だと私が感じている点
12:02 PM
期待される挙動が人や文脈によって異なる、というのが問題という議論ですね。
Avatar
どちらも確かにと思うところがあるし、2つ目はどうなるんだっけと悩んだ記憶もありますね
12:06 PM
本質的に実体が異なるものを文法とコンパイラによってほとんどWrappedとして扱えるように隠蔽していた部分でエッジケースで齟齬が出るのはしょうがないという感じもしますね
12:08 PM
Optionalが仮にKotlinやTSのようなUnionだったらどう不便になるんだろう?
12:08 PM
そもそも値型が扱えないとかの問題になるのかな
Avatar
Unionの場合はOptionalのOptionalが表現できなくなるので
12:13 PM
まあそれはそれで困ることがある
12:13 PM
例えばGenericsにOptionalを渡すことは出来ないはず
Avatar
Optionalのネストは我慢できるような気がしてますが、型パラにOptional渡せないのは厳しそう
Avatar
Avatar
tarunon
これは結構私は方々でぶーを垂れてるので知ってるかもですが、 TがT?のサブタイプである UがTのサブタイプであるならばU?はT?のサブタイプである この2点がSwiftでは許可されています。で、下のコードはコンパイルが通る。 var s = Cat() var a: Animal = s // CatとAnimalのサブタイプ関係が成り立つことを示す var b: Cat? = s var c: Animal? = b U?はT?のサブタイプ、は具体のコードとしては、 UITableViewController? な変数が UIViewController? に渡せる、というのが頻出すると思います。 (edited)
ここ UIView? の間違い?
12:23 PM
暗黙の型変換だと、変換元の型から変換先への型への妥当な変換方法が複数存在した場合に、どちらを選択しているのかがわからず、場合によってはその違いによって振る舞いが変わるケースが出てくる、ということだなあ
12:24 PM
暗黙の型変換が無ければ陽に記述されるから曖昧性はないし、一貫して区別できない同じものとみなすアプローチでも曖昧性は無いと・・・
Avatar
Avatar
omochimetaru
ここ UIView? の間違い?
なおした、tx
Avatar
Avatar
tarunon
なおした、tx
よくまとまってるしgistかzenかなんかに貼っておくと良いのでは
Avatar
置くわ〜
12:26 PM
Unionだったらどうなの、とかサブタイプのどれを諦めたら何が起きるのみたいなのまでまとめて
Avatar
この文章をほとんど一筆書きしてるのがすごい
Avatar
置いとくかな
12:26 PM
アイスマンはリアタイで見てたからねw
Avatar
omochimetaru 3/24/2021 5:30 PM
結構前からあった文書で、そろそろレビューに進めようって話が出たところか
Avatar
omochimetaru 3/24/2021 5:49 PM
プロポーザルの英語が難しくて自信ないけど、実装の方のテストも合わせて見た感じでは (edited)
5:50 PM
今まで Existential type として使えないようなprotocolでも使えるようにするが、
5:50 PM
contravariant Self と associatedtype が絡んでるメンバは呼び出せないという制限付きになる
5:50 PM
という話っぽい
Avatar
ウーンまあしょうがないか
Avatar
omochimetaru 3/24/2021 5:51 PM
protocol IntCollection: RangeReplaceableCollection where Self.Element == Int {} こういうふうにassociatedtypeを埋めて再定義してやれば使えるけど
5:51 PM
汎用的に any Collection<Element = Int> みたいにパラメータを埋められる、
5:52 PM
いわゆる generalized existential ではないっぽいね
5:53 PM
この範囲であれば実は現状でも、
5:53 PM
問題が起こらないメンバだけ集めた別名のプロトコルが定義してあれば、できるんだよな
5:53 PM
後付はできないけど
Avatar
割とそれはやった記憶がある
5:54 PM
ワークアラウンド無しに直接書けるようにはなるものの
5:54 PM
そこまで大きく表現できるコードは変わらなさそうだなぁ
Avatar
omochimetaru 3/24/2021 5:54 PM
そういう感じだね。できるようになる事もあるけど、
5:55 PM
肝心のtype erasureを手書きする時のユースケースに関してはあまり役に立たなそう
Avatar
Swift Collections の話、 OrderedSet/Dictionary もいいけど SortedSet/Dictionary も欲しくないですか?ツリーで実装されてて、各種操作が O(log N) で、イテレートしたらソート済で全要素 O(N) で取得できるやつ。
Avatar
omochimetaru 4/6/2021 9:47 AM
そっちは欲しかったことないけどたまに使いたい時がありそうですね
9:48 AM
OrderedDictionaryは HTTP Cookieの値とかJSON objectの値を表現するときにわりとよく出てくる
Avatar
single element なタプルってラベル付けられないのか。 @swift-5.3.3 let a: (foo: Int) a = (foo: 42) print(a)
Avatar
exit status: 1 with stderr:<stdin>:1:9: error: cannot create a single-element tuple with an element label let a: (foo: Int) ^~~~~ <stdin>:2:5: error: cannot assign value of type '(foo: Int)' to type 'Int' a = (foo: 42) ^~~~~~~~~
Avatar
TSやってると欲しいなーってなることがチョイチョイある
Avatar
omochimetaru 4/6/2021 10:09 AM
ラベル付きの方を禁止すると
10:09 AM
ラベルなしの方はただの丸括弧式のように見えるようにもなって
10:10 AM
シングルタプルは存在しない世界になる 気がする
10:11 AM
型の場合も (T)T が同じものですよね
Avatar
single element なタプルはただの値と等価だけど存在してるんじゃないの? let a: (Int) = 42
Avatar
omochimetaru 4/6/2021 10:11 AM
let a: (Int) = 42 print(type(of: a)) // Int
Avatar
single element なタプルが存在しないんじゃなくて、ただの値が single element なタプルという理解。
Avatar
omochimetaru 4/6/2021 10:12 AM
let f: () -> (Int) = { 0 } print(type(of: f)) // () -> Int
10:13 AM
single elementなタプルは存在しないんじゃないかしら?まあ、Tと(T)が同じものなのだ、って解釈なら意味は同じですね
Avatar
うん、 T(T) は同じものですべての値は single element なタプルだと思ってる。内部的な扱いは別として、概念的に。
10:16 AM
ラベル付けられて↓みたいに書けたら便利そう。 func foo() -> (isUpdated: Bool) { ... }
Avatar
omochimetaru 4/6/2021 10:17 AM
それはありますね〜
10:17 AM
Bool返すときにそのBoolの意味が表現できなくて困る
Avatar
コレクションのインデックスと要素をペアにして取得するためのメソッドってありますっけ? enumerated (オフセットしか返してくれない)ではなく。見たところ見当たらない。 @swift-5.3.3 let a: ArraySlice<Int> = [0, 1, 2, 3].dropFirst(2) for (i, x) in a.enumerated() { print(i, x) } for i in a.indices { print(i) }
Avatar
0 2 1 3 2 3
Avatar
0 2, 1 3 ではなく 2 2, 3 3 を得たい。
Avatar
Swift Algorithms is an open-source package of sequence and collection algorithms, along with their related types. - apple/swift-algorithms
10:52 AM
これですかね?
Avatar
お、これっぽいです!ありがとうございます。 (edited)
10:59 AM
Swift Algorithms にあるのかぁ。
11:00 AM
This is essentially equivalent to zip(x.indices, x)
なるほど。
Avatar
omochimetaru 4/6/2021 11:06 AM
enumeratedはそうか、元のコンテナに渡せるIndexじゃあないんですね
Avatar
そうなんです。 ArraySlice 使ってるときとか使いづらくて・・・。でも zip(x.indices, x) で良さそうですね。
Avatar
omochimetaru 4/7/2021 4:44 AM
.indexed() のほうがzipに同じx が2回書かれている事を読み取らなくていいので、filterでかけるときはreduceを使わなくて良いのと同じで、 indexedのほうが良いと思います 名前も自明だし。
Avatar
ああ、 indexed() がいいのはもちろんとして、わざわざそのために Swift Algorithms を入れたくないようなケースでは、ですね。
Avatar
omochimetaru 4/7/2021 6:37 AM
依存の追加はまあ微妙ですねえ・・・
6:37 AM
こういうのってほんの一箇所だけほしいみたいになりがちで
6:37 AM
パッケージでドカンと入れても5%も使わない
Avatar
Kishikawa Katsumi 4/7/2021 6:38 AM
CocoaPodsでいうサブモジュールみたいな概念が入ってくるかな。今でもSPMにあるような気もするけど。
Avatar
omochimetaru 4/7/2021 6:38 AM
swift-collectionsとかswift-numericは、中でさらにわけてありますね。
6:38 AM
パッケージの中からライブラリを選んで入れるような感じになっている
Avatar
Kishikawa Katsumi 4/7/2021 6:38 AM
あ、それはいいですね。
6:39 AM
最終的にはまとめてドンっと入れてリンクするときに使ってるものだけってやってくれると理想的かなあ。
6:40 AM
あ、それが家庭さんがWASMでやってたLTOってやつか。
Avatar
omochimetaru 4/7/2021 6:40 AM
そうですね。バイナリサイズ的にはそうなんですが、
6:41 AM
実践的には、バージョンアップ時に使ってないところの影響を確認するとかも必要な気がする
6:41 AM
ライブラリのバージョンアップでXXの仕様が代わりました〜ってのが使ってない95%のところで起きてても
6:41 AM
使ってない95%のところであることを確認したりしないといけない
Avatar
Kishikawa Katsumi 4/7/2021 6:43 AM
確かに、その観点だと細かく導入できるのはメリットがありますね。
Avatar
omochimetaru 4/7/2021 6:44 AM
そういうのまで自動だったら、とりあえずドンしても気にならなそうかな・・・
6:45 AM
semverを信じられれば楽になりますね。
Avatar
Kishikawa Katsumi 4/7/2021 6:47 AM
SemVerはまあ無理ですよね。ソフトウェアがうまくやってくれる仕組みはそんな遠くない将来できると思う。
Avatar
ライブラリオーサーとしては semver 厳しい
7:16 AM
major だけぽんぽんあげると楽っていう抜け道もあるし...
7:17 AM
ユーザーとしては信じられるならラクですよね。
7:17 AM
Goのmoduleがその辺かしこく解決してて、
7:17 AM
結果すさまじく複雑になってます
Avatar
omochimetaru 4/7/2021 7:17 AM
majorポンアゲされたら振り出しに戻る
Avatar
Hello Swift community, The review of SE-0310 "Effectful Read-only Properties"" begins now and runs through April 27, 2021. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager. When emailing the...
Avatar
-> の前に async が要りそう。 extension BankAccount { func meetsTransactionLimit(_ limit: Amount) -> Bool { return try! await self.lastTransaction.amount < limit // ^~~~~~~~~~~~~~~~ // this access is async & throws } }
Avatar
omochimetaru 4/20/2021 2:14 PM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
2:14 PM
unsafelyUnwrapped の利用例こんなところで見つけた
2:15 PM
However, in optimized builds (-O), no check is performed to ensure that the current instance actually has a value.
-O でさえチェックコストが消えるらしい。
Avatar
最近よく↓みたいなのほしいなぁと思うんですが、便利そうじゃないですか? extension Sequence { func sorted<T>(by keyPath: KeyPath<Element, T>) -> [Element] where T: Comparable { sorted(by: { $0[keyPath: keyPath] < $1[keyPath: keyPath] }) } } // ↓みたいにして使う users.sorted(by: \.age)
Avatar
omochimetaru 4/28/2021 8:57 AM
Foundationにあった気がする。Rubyにもありますね。
8:59 AM
SQL文のORDER句みたいに第二、第三キーも指定していける(asc/descもある)
Avatar
NSSortDescriptorだ、懐かしい
9:00 AM
そういえばkeyPathからstring取れるようにしろ!はどうなったんだろ
Avatar
なるほど。 keyPaths: KeyPath<Element, T>... を受け取るようにしようとしたけど、 Swift の Comparable は同値判定がないから Equatable もないとだめだな。
9:08 AM
あれ? Comparable は Equatable ?
Avatar
omochimetaru 4/28/2021 9:08 AM
a == b!(a < b) && !(b<a) ですよ
Avatar
Comparable: Equatable だった。これは知らなかった。
Avatar
omochimetaru 4/28/2021 9:09 AM
< だけあれば == を含む 5種類の比較は全部構成できます (edited)
👍 1
Avatar
extension Sequence { func sorted<T>(by keyPaths: KeyPath<Element, T>...) -> [Element] where T: Comparable { sorted(by: { for keyPath in keyPaths { let l = $0[keyPath: keyPath] let r = $1[keyPath: keyPath] if l < r { return true } else if l > r { return false } } return false }) } }
9:12 AM
asc, desc は reversed あるからなくてもいい気がする。
Avatar
omochimetaru 4/28/2021 9:13 AM
第二キーがdescとかは、reversedにはエンコードできないと思う
9:13 AM
第1キーが同一なグループの中での話になるので。
Avatar
これだとTが異なるときに複数keypathで使えなさそう?
Avatar
あ、ほんとだ。
9:14 AM
うーん、可変長ジェネリクスが待たれる・・・。
9:14 AM
N個オーバーロードするのは萎えるな。だから標準にないのか。
Avatar
Avatar
omochimetaru
第二キーがdescとかは、reversedにはエンコードできないと思う
たしかに。
Avatar
omochimetaru 4/28/2021 9:15 AM
Comparatorを受け取るComparatorとして抽象化すれば
9:15 AM
第一キーでソートするComparatorが
9:15 AM
第二キーでソートするComparatorを
9:15 AM
型パラメータとして保持する構造にできそう。
9:15 AM
雪だるまジェネリクスでいける気がする。
Avatar
Avatar
omochimetaru
雪だるまジェネリクスでいける気がする。
実現はできそうだけど使い勝手変わらない?
Avatar
omochimetaru 4/28/2021 9:17 AM
メソッドチェーンしていくような感じになりそう。
Avatar
雪だるま型パラ+書き味ならResultBuilder使いどころだけど微妙な気もするな
9:18 AM
AnyKeyPath配列で良い気もするよ
Avatar
omochimetaru 4/28/2021 9:18 AM
array.sort(Comparators.key(\.a).key(\.b, .desc))
Avatar
chainingでもいいか
9:19 AM
たしかに
Avatar
可変長ジェネリクスあっても T...KeyPath<Element, T>...... が対応することを示さないといけなくて構文上きついなぁ。 extension Sequence { func sorted<T...>(by keyPaths: KeyPath<Element, T>...) -> [Element] where T: Comparable { // 省略 } }
Avatar
private func _cmp<Value: Comparable>(_ lhs: Value, _ rhs: Value) -> Bool? { lhs == rhs ? nil : lhs < rhs } private func _cmp<Root, Value: Comparable>( _ lhs: Root, _ rhs: Root, on keyPath: KeyPath<Root, Value> ) -> Bool? { _cmp(lhs[keyPath: keyPath], rhs[keyPath: keyPath]) } こういうの用意しておいて array.sorted { _cmp($0, $1, on: \.prop1) ?? _cmp($0, $1, on: \.prop2.other) ?? false } でいいや、って最近なりました。
Avatar
なるほど・・・。
4:42 AM
実用上 80% くらいは単一のキーで済むから、 func sorted<T>(by keyPath: KeyPath<Element, T>) と、複数のキーの場合は都度クロージャ式を実装でもいい気も・・・。 3 キーくらいまで extension 用意しておけば 98% くらいカバーできそう。
Avatar
omochimetaru 4/29/2021 4:43 AM
Bool?にして??で合成するの面白い
Avatar
struct Foo<Bar> { struct Baz {} } があるときに、 Foo<Bar>.Baz であってほしいときと Foo.Baz であってほしいときないですか?単に Foo に関連する型をネームスペースとして Foo. にまとめたいときに Foo<Bar>.Baz になると鬱陶しいことが。
Avatar
そういう場合はProtocol以下にNamespace作りたい時と同じように、Foos を作って解消するのが良さそう
Avatar
Kishikawa Katsumi 4/30/2021 10:06 AM
ほとんど Foo.Baz の方がほしいかなあ。
Avatar
Avatar
Kishikawa Katsumi
ほとんど Foo.Baz の方がほしいかなあ。
いやそうなんですよね。8割くらいそっちがほしいから鬱陶しいなってなる。
Avatar
インナータイプがアウタータイプのコンクリートな型パラメータに束縛されてるの
10:08 AM
Javaの感覚があったから最初は違和感あったけど、
10:08 AM
このswiftのルールの方が綺麗に感じるようになった
Avatar
実際はBarにアクセス出来ちゃいますもんね
Avatar
BarがBazの定義の中で使われてないときだけ、Foo.Bazを書けるようにする、みたいな議論あるのかな (edited)
Avatar
Avatar
omochimetaru
このswiftのルールの方が綺麗に感じるようになった
理論上は正しいと思うんだけど、ネームスペースとして型を使うのと相性が良くない。
Avatar
とはいえ分離されていて欲しい時もあるのはそうなので、複数形ネームスペースに逃してる
Avatar
書けるようにする
使われてないことを保証するのがしんどいと思う
Avatar
型はネームスペースじゃないからしょうがない
Avatar
実装も含めて全部見ないといけない
Avatar
そうなんですよね、declだけみるだと足りない
Avatar
途中の実装に一瞬Barが出てきて、型として露出してないとか普通に成り立つんで
Avatar
Avatar
Yuta Saito
BarがBazの定義の中で使われてないときだけ、Foo.Bazを書けるようにする、みたいな議論あるのかな (edited)
それはStructural SubtypingっぽくてSwiftらしくないような。この場合はサブタイピングじゃないけど構造から型を決めるという点が。
Avatar
無理ですね
Avatar
typescriptは、同じ名前のネームスペースと型を定義できた気がする
Avatar
BazがBarを使っていないのがたまたまか判断できないから、ちょっと実装を変えるだけで型が変わってしまう可能性があって厳しそう。
Avatar
Avatar
omochimetaru
typescriptは、同じ名前のネームスペースと型を定義できた気がする
そうすると正攻法はこれかなぁ
Avatar
Swiftもネームスペース構文を別に用意するのが綺麗な気はする
Avatar
そうだね。 enum でネームスペースにしてるのとか微妙だし。
Avatar
だいたい型でできるからこれでよくね?のままになってる感じがする
10:15 AM
ただまあ同名の型とネームスペースを許すと推論器の負担がまた増えそうだけどw
Avatar
Swiftが発表されたときの、Swiftの機能が羅列されたスライドで "Namespaces" って書かれてたのに・・・。あれはモジュールの意味だったんだろうけど。
Avatar
あれはモジュールでしたね。
Avatar
Kishikawa Katsumi 4/30/2021 10:15 AM
struct Foo<Bar> { } struct Foo.Baz { } こういうふうに書けたらいいんちゃうかと思ったことある。
Avatar
なるほど。
Avatar
モジュールも本来入れ子を作れる仕組みだからそっちを進めるのもありえるのかな
Avatar
たしかに extension はそうですしね。
10:16 AM
Foo<Bar>.BazFoo.Baz の共存とかあり得る?もっと言えば nested type と namespace で名前が被るとどうなる??
Avatar
Avatar
Kishikawa Katsumi
struct Foo<Bar> { } struct Foo.Baz { } こういうふうに書けたらいいんちゃうかと思ったことある。
これはわかりやすいですね。
Avatar
xcworkspace/xcodeprojの中でモジュールがシュッと宣言できてライトウェイトな感じになるのが一番良い解決な気はしますね
Avatar
Hello everyone, We separated out and updated the async let proposal with the latest semantics and spelling details. This is the first pitch of the feature as a stand-alone thing, it was previously pitched as part of structured concurrency pitch #1, and pitch #2 and was separated out later on as it's a feature large enough to deserve it's own d...
12:00 AM
async let 単体のピッチが立った。ちゃんとした提案書もついてる。 提案書の中で、 TaskGroup.spawnTaskGroup.async に変更されていて、 spawn let ではなく async let なのはそれに揃ってるという事になっている。
Avatar
await しなければ静的エラーだろうって話を以前したけど、 この文書だと、スコープ脱出時にキャンセルしてキャンセル完了を待機するって仕様になっている。 1つ目のタスクの結果を見て2つ目のタスクの結果を捨てるみたいなフローを考慮したっぽい。 (edited)
Avatar
omochimetaru 5/14/2021 2:09 AM
spawn の方がいいんじゃないかって意見を書き込んだら、 async let になった経緯として、 複数のAPIを async に統一するって方針の議論がある事を教えてもらった。
Avatar
↓みたいなパターン書くことになるケース結構多くないですか? let foo: Foo if let f = self.foo { foo = f } else { foo = Foo(...) self.foo = foo }
Avatar
まあまあ多い
Avatar
↓こういうのあると良さそう? let foo: Foo = self.foo.value(default: Foo(...))
10:48 AM
Dictionarydictionary[key, default: value] += 1 みたいなノリで。
Avatar
僕はこう書いてます let foo = self.foo.ensure { Foo(...) } @discardableResult public mutating func ensure(_ f: () throws -> Wrapped) rethrows -> Wrapped { if let x = self { return x } let x = try f() self = x return x }
Avatar
そこのクロージャは @autoclosure でいい気がする。 (edited)
10:50 AM
↑ koherさん欲しいって言ってますね。
Avatar
この会話まったく覚えてないなw
Avatar
いや、普通にFooの初期化に数行かかることもあるので、クロージャで便利ですよ
Avatar
初期化数段は前の行でもいいかと思ったけど、 nil のときだけ初期化だからやっぱクロージャがいいか。
10:53 AM
昔は思い付かなかったみたいなのに今は近い案を思いついたから成長してるな🙂
10:53 AM
この ensure 普通に標準ライブラリにほしいね。
Avatar
Contribute to omochi/WeaselRoll development by creating an account on GitHub.
Avatar
toggle, subscript[_:default:], reduce(into:_) とかの仲間としていけるんじゃないかなぁ。
Avatar
自分はライブラリにして使ってます
10:55 AM
public mutating func consume<R>(_ f: (Wrapped) throws -> R) rethrows -> R? { guard let x = self else { return nil } self = nil return try f(x) }
10:55 AM
対のconsumeとセットできれいに収まることがまあまあある
10:55 AM
self.foo.consume { $0.shutdown() }
Avatar
なるほど。
10:56 AM
まあ、そっちは分岐で普通に書けるんよね。 if let foo = self.foo { foo.shutdown() self.foo = nil }
10:59 AM
3 年前も同じこと言ってた。成長してなかった。
Booltoggle が通ったことを考えるとこれもいけるのでは?
https://discord.com/channels/291054398077927425/306995750418513920/460706985222995979
11:00 AM
↓これも。
Dictionarysubscript(_:default:) は同じじゃないですか?
11:00 AM
rintaroさん、Proposal出してみてほしいなぁ。
Avatar
まあconsumeはフローは簡単だからそんなに大変ではないけど foo って4回書くのが1回で済むので結構使ってます。
Avatar
struct で不必要に let つかうのやめようぜっていったら猛攻をくらった...
Avatar
記事について この記事は potatotips#39 という勉強会で発表した内容を再掲したものです。スライドの画像と、喋った言葉を載せました。 以下スライド それではこれから、Swift の struct の st...
Avatar
おもちさんのかな
7:28 PM
それです
7:28 PM
とりあえず let 原理主義ってのがあるのがわかった気がする
Avatar
手軽に変えられたくないプロパティに let を使いたくなる気持ちはわからんでもないですけどね。原理的に変えられることと、変えるための手軽な手段が存在することは異なるので。ただ、境界があいまいになるので、突き詰めると↑になっちゃうんですよね・・・。
7:31 PM
利用時に let にすれば十分なケースまでプロパティ側を全部 let にするのは許容しづらいですが。
Avatar
JSONレスポンスを表現するstructのプロパティが変わってしまうのは危険だからletがいい
7:33 PM
という意見があったんだけどそれは... 利用側の問題では...
7:33 PM
なんかちょっと責任逃れしたいてきな気持ちもあるのかも
7:33 PM
(自分の書いた struct は変えられないから安心、的な) (edited)
Avatar
Kishikawa Katsumi 6/4/2021 7:35 PM
レスポンスのStructはPOSTにも使うことあるからvarにしてくれた方が便利とか思いますね。
Avatar
あと聞いたのは、letじゃダメな理由は何か、ってやつですね
Avatar
JSONレスポンスを表現するstructのプロパティが変わってしまうのは危険だからletがいい という意見があったんだけどそれは... 利用側の問題では...
これは利用側が let で宣言してれば問題ないと思いますね。
Avatar
ですね。
Avatar
それに [User] がレスポンスで返ってくるようなケースを考えると、 Arraymutaing func を持つので、それは問題にならないの?って話になりますしね。それが許容できるなら(利用側で let users: [User] で問題ないなら) struct のプロパティも var でいいでしょという。
Avatar
あー、それはいいポイント
7:56 PM
[]がルートであることは少なそうだけど。
7:56 PM
一貫性はかける。
Avatar
Userが例えばDB由来の値として仮定するなら、user_idはどんな状況でも可変にしたら変なので、そこだけletにするというのは頷けます。
11:46 PM
それ以外はvarにしないことのデメリットが大きすぎる
Avatar
omochimetaru 6/4/2021 11:48 PM
structのletを許容できる状況は、他のプロパティから依存して決まるプロパティだけだと思ってます
11:48 PM
プロパティ一個だけ書き換えた時にその型が持つ制約をやぶるのをletプロパティで防ぐ。 (edited)
11:48 PM
それ以外は、型全体をletで使えば変更できない版として使えるので元定義はvarだけでオッケー
Avatar
なんか、やっぱり var で使われる恐怖みたいなのを言う人が多かったかな
Avatar
主なデメリットは、 1. letはトップレベルに置くだけでその役割を果たせる 2. フィールドを変更するときの手間が大きくなる(swiftにおいてmutatingは値型の性質によりselfを返す関数と同等と見なせる) (edited)
Avatar
その制約を破る、かどうかを判断するのが面倒
11:50 PM
みたいな意見もあった
11:51 PM
(まあ面倒とは言わないけれど(安全じゃないとか)、まあ面倒ってことだと思う)
Avatar
omochimetaru 6/4/2021 11:52 PM
JSONで帰って来た値を表示する状況で、プロパティがvarだったからって書き換えて違うもの表示する人間を想定するの、何も作れなくないか?
11:52 PM
そんなことしないだろ。
😂 1
Avatar
そういうことする人は、別にletにしたとしてもinitしなおすと思うけど
😂 1
Avatar
Avatar
niw
みたいな意見もあった
omochimetaru 6/4/2021 11:53 PM
判断保留で安全側に倒すのは、一理ありますね。不便だけどレスポンスにしか絶対使わない型とかわかってるならアリかもしれない。
Avatar
Avatar
tarunon
そういうことする人は、別にletにしたとしてもinitしなおすと思うけど
omochimetaru 6/4/2021 11:54 PM
そうなんだよね。init越しのセッター解放が可能なんだよね。
11:54 PM
あ、だから、全部のフィールドを渡すタイプのinitが見えてるかどうか、で判断できるな・・・
11:55 PM
制約されたフィールドをもつ特殊なケースでは、initでそれが渡せないようになってるか、init本文に検査がついてるはず。 (edited)
Avatar
例えば全部letでもsetName(String)->Selfな関数が生えてたらそれはvarを凄く遠回りに表現してるだけなのでやるべきじゃないし
11:56 PM
同様にinitが解放されていて、ユーザによる変更結果をinit使って格納してたらそれも同じ。varを遠回りして書いてるだけ
11:58 PM
違反mutableはコードレビューで var mUser = user の一行を👮‍♀️するだけだから、これもそこまで難しいとは思えないが…
11:58 PM
うーーーん?
12:00 AM
むしろ遠回りなコードは外れた違反コードを招いてコードレビューの難易度を上げるまである。素直にvarで置き直してたら変更が発生してると判断できた方が楽。
Avatar
先も言ったけど自分の責任じゃなくなる、がそうしたくなる大きな要因にも思える
12:07 AM
varで使えるようになるのは自分の責任、 (edited)
12:08 AM
letで書いておけばそれは防げる、みたいな。
Avatar
omochimetaru 6/5/2021 12:09 AM
なるほど。
12:09 AM
その間違ったコードが発生してもどう考えても型を作った人の責任じゃないと思うけど
12:11 AM
そこで責任逃れを事前に備えておかなきゃいけない環境はつらそうだな。
Avatar
「init越しのセッター解放」ってたとえば struct Point { let x: Int let y: Int init(x: Int, y: Int) { self.x = x; self.y = y } } extension Point { mutating func setX(_ x: Int) { self = .init(x: x, y: self.y) } } という理解でいいですか?
Avatar
Avatar
rintaro
「init越しのセッター解放」ってたとえば struct Point { let x: Int let y: Int init(x: Int, y: Int) { self.x = x; self.y = y } } extension Point { mutating func setX(_ x: Int) { self = .init(x: x, y: self.y) } } という理解でいいですか?
omochimetaru 6/5/2021 12:12 AM
まさにそれを想定しています。
👍 1
Avatar
「トップレベルがvarになっても安心じゃん」はinitで破壊されるわけだから、トップレベルをletで守るということを徹底するべき で、この前提が守られているなら途中のプロパティはvarでも何も問題が無いし、本当に変更したいときのコードはトップレベルをvarにするだけな簡素なものになる (edited)
12:14 AM
前提のトップレベルがletであるべきを守れない環境はもう色々仕方ない
12:15 AM
何も守れてないけどかりそめの安心に縋るしかないのかな
Avatar
Avatar
tarunon
「トップレベルがvarになっても安心じゃん」はinitで破壊されるわけだから、トップレベルをletで守るということを徹底するべき で、この前提が守られているなら途中のプロパティはvarでも何も問題が無いし、本当に変更したいときのコードはトップレベルをvarにするだけな簡素なものになる (edited)
omochimetaru 6/5/2021 12:15 AM
前提として原則letで済ませることで、varを使うのは限られた状況なわけだから、それが目印になってレビューの起点になるよね。 (edited)
Avatar
そうなんだよ。それが型定義の側じゃなくて利用側にあることがレビューを楽にするんだよな
Avatar
omochimetaru 6/5/2021 12:18 AM
うーんやっぱ逃れようとしてるシチュエーションの発生の想定があることにかなり違和感がある・・・ (edited)
Avatar
実際そんな状況があるとは思えなんだけど
12:19 AM
たとえば過去の職場での経験とか、過剰なlet信仰とかそんな感じにも思えた
Avatar
omochimetaru 6/5/2021 12:19 AM
過剰なlet進行は、Java系出身だとありえると思います。
Avatar
値型のコピー特性を理解したら信仰から解放されそう
Avatar
omochimetaru 6/5/2021 12:20 AM
Swiftのstructだと理屈が違ってるんで破綻してるんですけど、あんまりわかってないままSwift書いてるとそうなると思う。
Avatar
実際class/structの混同というのも見られたけどそれはまあちょっとそもそもスタート地点に立っていないから実はまだlet信仰を改善できる感じがした
Avatar
omochimetaru 6/5/2021 12:21 AM
Swiftでvar propertyを書き換えることとJavaのimmutable objectで新しいインスタンスを作ることが等価な事に気づいて欲しい。
Avatar
structをわかってなおかつlet信仰なのがでも実はswift好き組に結構いた感じがする
12:22 AM
なんか直感的にはわからないのがなあ。
Avatar
omochimetaru 6/5/2021 12:22 AM
その派は他人が作ったstructのpropertyがletで躓いた時にどうなるんだろう・・・
Avatar
あんまり考えてないかも。
12:23 AM
「チームごとにルール作ればいいじゃん派」もいた
Avatar
omochimetaru 6/5/2021 12:24 AM
varを間違って使う不毛な心配をするより、 letで不便が生じる心配をしたほうが良いはず。
Avatar
letをstructで使えるようにしたのが間違いだ派もいた
12:25 AM
まあちょっとわからんでもない
Avatar
どういうことですか?propertyにletが置けるのがダメと
Avatar
それはvar推奨派でという意味
Avatar
理解。過激派ですねw
Avatar
なんか全体として、長くコードベースに関わってきた人はよりvar推奨で
12:27 AM
年数の浅い方にlet推奨が多い感じだったかなあ
Avatar
omochimetaru 6/5/2021 12:27 AM
まあ let なくても private(set) var で同じ事が起きますよ (edited)
Avatar
関係あるのかわからんけど、いろいろ触るとうわなんでこいつletやねんでつまづくから
Avatar
omochimetaru 6/5/2021 12:28 AM
やっぱ経験が長いとletの不便を踏むのでは。
👆 2
Avatar
var推奨派が増えるのかもしれない
Avatar
あとは値型のコピー特性がSwift特有のものなので
Avatar
omochimetaru 6/5/2021 12:28 AM
varの問題は大本letで解決するけどそっちはinit越しsetterとかいうハゲでしか回避できないですからね
Avatar
そこに対する理解を得るのに一定の時間が必要というのはあるかもですね
Avatar
immutable/mutableのNSObjetのペアをObjective-Cで書いたことあれば
12:30 AM
varの利益がわかるはずという説明もあったけど共感できるんだけど
12:31 AM
Objective-Cの経験年数が多い人がswift的には少ないという点共感がえられたか怪しい (edited)
Avatar
omochimetaru 6/5/2021 12:31 AM
その経験がある時点でSwift歴も長くなってそう
Avatar
どんな言語でもstdlibのお作法に従うというのは鉄則なので、Array Dictionaryがそうしてるんだから俺達もそうするんだ
12:32 AM
でも良い気はしますけどね
Avatar
swiftが初期にlet(というかimmutability)を宣伝しすぎたのはちょっと問題なのかも (edited)
Avatar
ずいぶん話が進んでた。「init越しのセッター解放」の最たる例が Booltoggle() で、 var 使ってる以上プロパティをどれだけ守っても可変だし、可変であっても共有されないから本質的にイミュータブルと同じなんだよなぁ。
1:14 AM
参照型中心のオブジェクト指向言語から来ると、これに慣れるのにtarunonさんの言うようにある程度の時間がかかる。
Avatar
omochimetaru 6/5/2021 1:14 AM
Boolはpropertyを持たないけどどういう意味ですか?
Avatar
一部のプロパティを let にして守った気になってるけど self 書き換えを extension で生やせるから守れてなくて、一部どころか全体すら書き換えられるから、イミュータブルに見える Bool ですらイミュータブルでないし、それで問題ないって意味。
Avatar
omochimetaru 6/5/2021 1:16 AM
全体すら書き換えられる例ということか。
Avatar
toggle って参照型中心の世界の考え方に浸かってるとぶったまげると思うんよね。
1:17 AM
BoolString がミュータブルってだけで泣いちゃいそう。
Avatar
extension Bool { var negate: Bool { !self } } の方があり得る。けどこれは!を使えで蹴散らされる
Avatar
これが(他の言語での)普通の感覚ですよね。
Avatar
話を戻しちゃうけど 僕は個人開発者なので(?)初めは全部letにして必要になった時にvarにしてますね 自分が変えようと思た時にお気軽に変えられるので アクセス修飾 private/public の延長みたいな感覚 本当に必要になるまで public (var)にしない var絶対許さないマンもこの感覚かな?と思う
Avatar
omochimetaru 6/5/2021 1:23 AM
toggled() は無いのか。
Avatar
共同開発の場合新しい型を作るより既存の型を変更する方が100万倍面倒くさいはずなので全部varにしておくほうがいいと思うけど、共同開発したことないので分からない
Avatar
struct A { let i: Int } struct B { let a: A? = nil } //let _: [Any] = [B()].compactMap { $0[keyPath: \B.a?.i] } // OK let _: [Any] = [B()].compactMap(\.a?.i)
9:53 PM
segvする
Avatar
ふと思いついてやってみたんですけど、↓で JSON の encode / decode で元通り復元できないのって既知ですか? @swift-5.4.3 import Foundation struct Foo: Codable { var value: Int?? } let foo: Foo = .init(value: .some(.none)) print(foo) let data = try! JSONEncoder().encode(foo) print(String(data: data, encoding: .utf8)!) let decoded = try! JSONDecoder().decode(Foo.self, from: data) print(decoded)
Avatar
Foo(value: Optional(nil)) {"value":null} Foo(value: nil)
Avatar
JSONでOptional<Optional<T>>が表現できないのにエンコードできちゃうのが間違えてると思う
Avatar
Avatar
koher
ふと思いついてやってみたんですけど、↓で JSON の encode / decode で元通り復元できないのって既知ですか? @swift-5.4.3 import Foundation struct Foo: Codable { var value: Int?? } let foo: Foo = .init(value: .some(.none)) print(foo) let data = try! JSONEncoder().encode(foo) print(String(data: data, encoding: .utf8)!) let decoded = try! JSONDecoder().decode(Foo.self, from: data) print(decoded)
Avatar
めっちゃ最近話されてたw
Avatar
キー無しとキー有りnullとで2重までは表現できるから
Avatar
enumCodable の話の文脈で話されてるっぽいけど、そもそも単体でこれまでに起こってた話なんですよね。
Avatar
正しく元に戻ってくれると嬉しいですね
Avatar
Avatar
masakihori
JSONでOptional<Optional<T>>が表現できないのにエンコードできちゃうのが間違えてると思う
tagged union を untagged union にマッピングしてるのでできなくて当たり前ですよね。ただ、 String? とかが Codable でないのはそれはそれで辛いですね。うーん。
Avatar
Avatar
tarunon
正しく元に戻ってくれると嬉しいですね
そこの区別は地獄の入口になりそう😅
Avatar
enumの自動Codableと同じように "some": { "_0": { "some": { "_0": {...} } } } } とかで表現すればいいわけだ。
Avatar
Avatar
rintaro
enumの自動Codableと同じように "some": { "_0": { "some": { "_0": {...} } } } } とかで表現すればいいわけだ。
そう、それを考えてて、ネストした Optional って今どうなってるんだ?と思ってやってみたら↑みたいになってたという・・・。でも、 98% くらいの用途である Foo? が自動 Codable 形式になるのは辛いですよね・・・。 (edited)
Avatar
T? だけ特別扱いは出来なくはなさそうですよね。
Avatar
そもそもjsonのoptionalはjsのoptional型相当なので、ちゃんとやるならCodable用のOptionalを作ってそこにマッピングする、ということになりそう
3:39 AM
undefined(キー無し), null, someがある型
Avatar
Avatar
tarunon
そもそもjsonのoptionalはjsのoptional型相当なので、ちゃんとやるならCodable用のOptionalを作ってそこにマッピングする、ということになりそう
これもネストできるからダメそうな気が。
Avatar
CondConfにNot制約が必要ですねぇ
Avatar
ですね。
Avatar
それがあれば2重Optionalまで許可、と言う解決でシンプルになりそう
3:46 AM
或いは、untagged unionを導入したら解決しますね
Avatar
Avatar
rintaro
T? だけ特別扱いは出来なくはなさそうですよね。
T?TOptional でないときみたいな条件書けますっけ?
Avatar
Avatar
tarunon
或いは、untagged unionを導入したら解決しますね
Swiftの世界観崩壊しそう😂
Avatar
ので、違う型システムに変換してる以上、100%の保証をするのは無理筋なのである程度の妥協があった方が良いとは思います (edited)
Avatar
Avatar
koher
T?TOptional でないときみたいな条件書けますっけ?
制約としては書けないと思いますけど、Optional.init(from:)/Optional.encode(to:) のstdlib実装なら可能だと思います。という意図でした。 (edited)
3:53 AM
https://github.com/apple/swift/blob/038af80a880ce8581631f7c695f82dc20914f1d9/stdlib/public/core/Codable.swift#L5372-L5405 この辺の内部実装を WrappedOptional なら分岐させるっていう意味です。もちろん evolution proposal 必要ですけど。
Avatar
omochimetaru 6/10/2021 4:08 AM
enumのcodableができたからoptionalもenumなので特別扱いは要らなくなりましたよね
Avatar
Kishikawa Katsumi 6/10/2021 4:11 AM
なるほど。OptionalもEnumのAssociate value扱いでいいのか。
4:13 AM
まあJSONに限るとJSONにない二重以上のオプショナルはそう扱っていい気もしますね。
Avatar
Actor 、↓のように書いたら actor Counter { private(set) var count: Int = 0 func countUp(_ amount: Int) -> Int { count += amound return count } func countUp() -> Int { countUp(1) } } (edited)
8:54 AM
概念的には↓のように考えれば合ってる? final class Counter { private let queue: DiqpatchQueue = ... // Serial Queue private var _count: Int = 0 var count: Int { get async { withCheckedContinuation { continuation in queue.async { continuation.resume(returning: _count) } } } } private func _countUp(_ amount: Int) -> Int { count += amound return count } func countUp(_ amount: Int) async -> Int { withCheckedContinuation { continuation in queue.async { continuation.returning(returning: _countUp(amount)) } } } private func _countUp() -> Int { _countUp(1) } func countUp() async -> Int { withCheckedContinuation { continuation in queue.async { continuation.resume(returning: _countUp()) } } } } (edited)
8:55 AM
あ、 increment の結果返さないと。 修正 done 。 (edited)
Avatar
あってるとおもいます
10:38 AM
外から呼ぶときにqueue.async越しになる。
👌 1
Avatar
f (_ a: @escaping () async -> Void) { let s = DispatchSemaphore(value: 0) async { await a() s.signal() } s.wait() }
10:19 PM
これやっちゃダメらしんですが、これでデッドロックとかするケースってあるんですかね。 (edited)
Avatar
a が元のスレッドに突入しようとしたらダメじゃないでしょうか?
12:53 AM
f をメインスレッドで呼び出して aDispatchQueue.main.asyncasync/await 版を渡すとか。
Avatar
Avatar
niw
f (_ a: @escaping () async -> Void) { let s = DispatchSemaphore(value: 0) async { await a() s.signal() } s.wait() }
omochimetaru 6/14/2021 3:36 AM
asnyc の中身が f を実行してる スレッドに投入される可能性がありますね。 async/awaitではブロッキングが起きないことを前提にスケジューラが構成されているらしいので、 他のTaskの処理がそのwaitしてるスレッドに投入されて複雑に噛み合った結果止まる可能性もあります。
Avatar
``` @MainActor func a() async { } func f() { let s = DispatchSemaphore(value: 0) async { await a() s.signal() } s.wait() } f() ```
4:07 AM
これかー。
4:07 AM
けっこう厳しいな、これ。libdispatch多用してる既存の世界でつかったら摩訶不思議なdeadlock起きそう。main threadならまだわかるけど。 (edited)
Avatar
omochimetaru 6/14/2021 4:08 AM
そうですね。MainActorの場合は、必ずメインスレッドに再投入するので、さっきの話が100%発生します
Avatar
LIBDISPATCH_COOPERATIVE_POOL_STRICT で実行時に死ぬか確かめるしかないのか... わかるけど...
4:09 AM
@MainActor 以外に thread 特定されるような要素ってなにがあるかな
4:10 AM
簡単に試した限り async/await 系のAPIでcooperative threadつかってる範囲ではdeadlockできなかった
Avatar
omochimetaru 6/14/2021 4:10 AM
ほかは無いはずですね。同じActorのpartial taskは別のスレッドで実行することもあるようなので。
4:11 AM
Actorの内部にあるExecutorってやつがそのへんと関係してたはず。
4:12 AM
ただ、Actor runtimeは(Montreyだと)スレッドプールが変動しないので、
4:12 AM
そのようなwaitをしてるスレッドがコア数分発生したら
4:12 AM
どのスレッドもpartial taskを実行しなくなって世界が止まりますね
Avatar
それ確認したいんだよなあ。Montereyいれるしかないのか...
Avatar
Avatar
niw
けっこう厳しいな、これ。libdispatch多用してる既存の世界でつかったら摩訶不思議なdeadlock起きそう。main threadならまだわかるけど。 (edited)
omochimetaru 6/14/2021 4:14 AM
既存コードでは、上記パターンは asnyc ではなく DispatchQueue.asnyc で書いているはずで、
4:14 AM
DispatchQueue.asyncはスレッドを作るので、signalまで到達しますね。
4:15 AM
案外大丈夫なパターンが多いかもしれないです。 async/awaitスケジューラに負担はかかるので性能は低下するけど。
Avatar
部分的に async await を誰かが書いて semaphore を使ったAPIが離れた場所で残ってるで無事deadlockはありそう (edited)
4:19 AM
semaphoreを遠距離で使うことは少ないはずだけど。
4:21 AM
逆に言うと、実は全ての Task が完了するまで待つ、みたいなのって書けない?
Avatar
omochimetaru 6/14/2021 4:25 AM
書けないと思います。
4:25 AM
そもそも Task を作ったところで Task オブジェクトを引き回しておかないと
4:25 AM
後で触りようもないので。
Avatar
トップレベルでタスクつくって終わるまでまっておわったら終了、が書けなかった。
4:25 AM
十分な長さsleepするしかない
Avatar
omochimetaru 6/14/2021 4:25 AM
それはかけないですね、Taskをまつのもawaitなので。
4:25 AM
TaskはTaskの中でなければ待てない
Avatar
しかも十分な長さsleepしないとsegvする
4:28 AM
並列 curl みたいな CLI を URLSession の async でつくるってできないのかも。
Avatar
omochimetaru 6/14/2021 4:29 AM
一番根っこで
4:30 AM
DispatchQueue.asnycで専用にスレッドを立ててsemaphoreを待って メインスレッドはその後 dispatchMain に入る (edited)
4:30 AM
みたいな。あれ、でもCLIの場合asyncの世界の入り口ってどうやって書くんだったっけ。 (edited)
4:31 AM
メインスレッドで最初からawait可能?
Avatar
それは無理
4:31 AM
async {} aka Task.init {} か何かが必要 (edited)
Avatar
Avatar
omochimetaru
DispatchQueue.asnycで専用にスレッドを立ててsemaphoreを待って メインスレッドはその後 dispatchMain に入る (edited)
それはつまり semaphore.signal()/semaphore.wait()👆 みたいな安全ではないコードがどこかに必要になってしまう... (edited)
Avatar
omochimetaru 6/14/2021 4:33 AM
あーじゃあ Task.init で起動するけど wait できないって状態か
Avatar
ですです
Avatar
omochimetaru 6/14/2021 4:33 AM
最初に開いたTaskの末尾でsignal() しておいて
4:34 AM
waitするのは専用のDispatchQueue.asyncの中
Avatar
さっきの f() がトップレベルで必要、ってことですよねえ。
Avatar
omochimetaru 6/14/2021 4:34 AM
そのDispatchQueueに5.5 Concurrencyが絡んだら終わり
4:34 AM
気をつける
Avatar
omochimetaru 6/14/2021 4:34 AM
まあCLIの一番上だけならいいんじゃないだろうか・・・一回ユーティリティ関数書けば大丈夫ですよ
4:35 AM
なんか途中までそんな感じの関数があったけど途中で消えたんですよね。
Avatar
多分だけど、@MainActor 以外、cooperative thread pool の thread 以外は使われないから、さっきの f() が Task から呼ばれないことが保証されていれば絶対安全なんじゃないかなあ。
4:36 AM
なるほど。
Avatar
omochimetaru 6/14/2021 4:38 AM
さっきの f() が Task から呼ばれないことが保証されていれば
わかった、fの頭に Task.unsafeCurrentTask をチェックするassertionをいれとこう
Avatar
omochimetaru 6/14/2021 4:38 AM
「Taskの中でない」ことは調べられるんですよ。
4:39 AM
実行時検査なのは微妙だけど、ピタゴラスイッチデッドロックよりははるかに良い。
Avatar
Taskの中ではないを強制できないのかな?
4:39 AM
notTask(_ t: @escaping () -> Void) みたいな (edited)
Avatar
Avatar
omochimetaru
みたいな。あれ、でもCLIの場合asyncの世界の入り口ってどうやって書くんだったっけ。 (edited)
↓これは? @main struct MyProgram { static func main() async { ... } } https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md#launching-async-tasks
Avatar
なんと
Avatar
Avatar
koher
↓これは? @main struct MyProgram { static func main() async { ... } } https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md#launching-async-tasks
omochimetaru 6/14/2021 5:50 AM
それだ〜!
5:51 AM
一回ユーティリティ関数書けば大丈夫ですよ
↑これがコンパイラ機能だった〜
Avatar
Additionally, top-level code is not considered an asynchronous context in this proposal, so the following program is ill-formed: ```swift func f() async -> String { "hello, asynchronously" } print(await f()) // error: cannot call asynchronous function in top-level code ``` This, too, will be addressed in a subsequent proposal that properly accounts for top-level variables.
5:54 AM
トップレベルについての議論の最新状態がどうなってるのかは知らない。
Avatar
@main じゃないと使えないのかなあ
Avatar
前はトップレベルで使えるようにする話があったはずなので、その後どうなったのか。
Avatar
--parse-as-library つけないと @main つかえない… (別の話ですが) (edited)
Avatar
現状 top-level は無理っぽい
6:25 AM
@main 必須かなあ
Avatar
スクリプトモードでのトップレベルawaitは実装予定って最近もどっかで言ってたはず (edited)
Avatar
@MainActor @Sendable func _doMain(_ asyncFun: @escaping () async throws -> ()) async { do { try await asyncFun() } catch { _errorInMain(error) } } Task.detached { await _doMain(asyncFun) exit(0) } _asyncMainDrainQueue() これが実装で、Task.detached して exit(0), main は CFRunLoopRun() ということらしい。 (edited)
Avatar
Avatar
Yuta Saito
スクリプトモードでのトップレベルawaitは実装予定って最近もどっかで言ってたはず (edited)
なるほど
Avatar
なるほどな〜、これなら全てが Task の世界に。
Avatar
actor A { var c = 0 func inc() -> Int { c += 1 return c } func f() { async { print(inc()) } } } @main struct Main { static func main() async { let a = A() await a.f() print(await a.c) } }
7:34 AM
これ f に async つけないと終了しない
Avatar
omochimetaru 6/14/2021 7:36 AM
それはなんか変ですね。
Avatar
Taskが漏れてる?
Avatar
@swift-main actor A { var c = 0 func inc() -> Int { c += 1 return c } func f() { async { print(inc()) } } } _runAsyncMain { let a = A() await a.f() print(await a.c) }
Avatar
swiftNightly BOT 6/14/2021 9:19 AM
1 1stderr:<stdin>:10:9: warning: 'async(priority:operation:)' is deprecated: `async` was replaced by `Task.init` and will be removed shortly. async { ^
Avatar
Avatar
niw
これ f に async つけないと終了しない
ここで付けないといけなかったasyncって func f() async ですか?それともbodyの async { .. } ですか?
9:22 AM
手元で動かしたんですが、 main側のprintが実行されたり、されなかったりしててかなり怪しい… (edited)
9:23 AM
bodyの async { .. } を外すと(今の所)必ず実行されてるように見える (edited)
Avatar
Avatar
Yuta Saito
ここで付けないといけなかったasyncって func f() async ですか?それともbodyの async { .. } ですか?
f() async ですね。
Avatar
Avatar
Yuta Saito
手元で動かしたんですが、 main側のprintが実行されたり、されなかったりしててかなり怪しい… (edited)
main で、actor の c にアクセスしてブロックしないと、taskの待ち合わせを誰もしないので print されないで終了するパターンは納得がいくんだけど (Taskを待ち合わせる方法がないという点で)、f()がasyncかそうでないかで、デッドロック?するかしないかが変わるにはとても怪しいんですよね。 (edited)
2:53 PM
Actor の実装の問題かなあ。どっちもコンパイルはできてしまう。あるいは、手元は big sur だから、runtimeの問題かもしれない。 (edited)
Avatar
f() async してもデッドロックしてるっぽいんですよね
3:05 PM
いや、viewDidLoadでasyncに包んでるのがマズイっぽいな
3:09 PM
トップを_runAsyncMainして、 func f() async にするとデッドロックしなくなった。これでniwさんの環境を再現できた気がする
3:14 PM
fにasyncを付けるとmainの await a.f() 以下と fの async { .. } ブロックの中が同じスレッドで実行されるようになるっぽい…
🤔 1
3:16 PM
@swift-main import Foundation actor A { var c = 0 func inc() -> Int { c += 1 return c } func f() async { async { print("begin f") print(Thread.current) print(inc()) print("end f") } } } _runAsyncMain { print(Thread.current) let a = A() await a.f() print("begin main") print(Thread.current) print(await a.c) print("end main") }
Avatar
swiftNightly BOT 6/14/2021 3:16 PM
<Thread: 0x00007fd110000c60> begin main <Thread: 0x00007fd114002dd0> 0 end main begin f <Thread: 0x00007fd114002dd0> 1 end fstderr:<stdin>:13:9: warning: 'async(priority:operation:)' is deprecated: `async` was replaced by `Task.init` and will be removed shortly. async { ^
Avatar
@swift-main import Foundation actor A { var c = 0 func inc() -> Int { c += 1 return c } func f() { async { print("begin f") print(Thread.current) print(inc()) print("end f") } } } _runAsyncMain { print(Thread.current) let a = A() await a.f() print("begin main") print(Thread.current) print(await a.c) print("end main") }
Avatar
swiftNightly BOT 6/14/2021 3:16 PM
<Thread: 0x00007f3114000c60> begin f <Thread: 0x00007f3118003360> 1 end f begin main <Thread: 0x00007f3114000c60> 1 end mainstderr:<stdin>:13:9: warning: 'async(priority:operation:)' is deprecated: `async` was replaced by `Task.init` and will be removed shortly. async { ^
Avatar
なる... ほど...?
4:23 PM
func msg(f: String = #function, _ s: Any) { print("\(Thread.current): \(f): \(s)") } actor A { var c = 0 func inc() -> Int { c += 1 return c } func f() { msg("3") async { msg("4") print(inc()) } } } @main struct Main { static func main() async { msg("1") let a = A() await a.f() msg("2") print(await a.c) } } (edited)
4:23 PM
これで
4:24 PM
<NSThread: 0x7fa109c0bfd0>{number = 1, name = main}: main(): 1 <NSThread: 0x7fa109d05540>{number = 2, name = (null)}: f(): 3 <NSThread: 0x7fa109d05540>{number = 2, name = (null)}: f(): 4 1 <NSThread: 0x7fa109c0bfd0>{number = 1, name = main}: main(): 2 ^Cmake: *** [run] Interrupt: 2 deadlockした場合
4:24 PM
<NSThread: 0x7f9250d0bfb0>{number = 1, name = main}: main(): 1 <NSThread: 0x7f9250e05b80>{number = 2, name = (null)}: f(): 3 <NSThread: 0x7f9250e05b80>{number = 2, name = (null)}: f(): 4 1 <NSThread: 0x7f9250d0bfb0>{number = 1, name = main}: main(): 2 1 deadlockしなかった場合
4:24 PM
🤔
4:27 PM
なんか、deadlockしない場合もあることがわかったけど、タイミング次第なのか... (edited)
Avatar
こういうのを静的にガードするためのactorだったはずなのに… (edited)
Avatar
f()にasyncつけるかつけないかで挙動が変わるのもあやしい
4:29 PM
actorむずい
😢 1
Avatar
actorがexecutorにタスクを投入するところのコード生成実装を追ったら分かりそう
Avatar
inc()でthreadをprintするようにしたらdealockしないケースが発生しなくなった...
4:30 PM
IO関係か?
Avatar
🤔
Avatar
actor A { func g() { } func f() { async { g() } } } @main struct Main { static func main() async { let a = A() await a.f() await a.f() // ここでdeadlock.. したりしなかった } } (edited)
8:04 PM
これでだめだ。 (edited)
Avatar
async(priority: .background) { などpriority変えても起きますか?
Avatar
backgroundにするとdeadlockしないですね
10:41 PM
あれ、でもg()が呼ばれないケースが...
10:41 PM
あー。それはいいのか。
10:41 PM
いいのか...?
🤔 1
Avatar
actorがどうやってsyncしてるのかと、asyncしたときのcontextの問題か...
Avatar
はい、priorityに応じて処理をどういう順番で実行するのかを決める所で何か起きているのかなあとふと思いました🤔 (edited)
Avatar
全然中身追えてませんがやはりpriority何か問題あるのかもしれませんね…🤔 https://github.com/apple/swift/pull/37939
Avatar
おお。
Avatar
AsyncSequencePublisher の代わりをさせるとして、 combineLatestmerge 相当のことを簡潔に実現するのは難しいでしょうか? AsyncSequencecombineLatestmerge が生えれば解決?
Avatar
今だと自前のオペレーターを作れば良いと思いますが、制約が結構あるので大変そう。 AsyncStream が出てきたら割と何でも出来るようになると思います。
Avatar
omochimetaru 6/24/2021 2:36 AM
combineLatest難しいかな?
Avatar
たとえば自前で combineLatest 作るとしたら↓みたいに並行でループ回してとかでしょうか? var values: (S1.Element?, S2.Element?) = (nil, nil) { didSet { switch values { case (let e1?, let e2?): // (e1, e2) をイテレータに流す case (.nil, nil): // nil をイテレータに流す default: break } } } async { for await e in s1 { values = (e, values.1) } } async { for await e in s2 { values = (values.0, e) } }
Avatar
難しいじゃなくて大変だという話ね
2:38 AM
AsyncSequenceの実装を一から作らなきゃいけないから面倒
Avatar
omochimetaru 6/24/2021 2:38 AM
AsyncStream { (cont) in var a: A! var b: B! async { for await x in a_s { a = x cont.yield(a, b) } } async { for await x in b_s { b = x cont.yield(a, b) } } } (edited)
2:38 AM
雰囲気はこんなかんじだよね
2:39 AM
asyncの返り値のTaskをまとめて onTermination で cancel するとか、なんかあといろいろあるけど。
2:39 AM
少なくとも、RxSwiftで自分でカスタムオペレータを書くよりは、
Avatar
やっぱそういう形になるよね。都度実装は面倒そうだから AsyncSequencecombineLatest はほしいな。
Avatar
omochimetaru 6/24/2021 2:40 AM
AsnycSequence上のカスタムオペレータのコードのほうが簡単に書けそうと思ってる
2:40 AM
まあ基本的なものは提供されてほしいですね。ArrayとかOptionalにflatMapがあるのと同じで。
Avatar
combineLatest とかはサードパーティ提供になりそうな気がするなぁ。
Avatar
flatMapはあるんだよね
Avatar
omochimetaru 6/24/2021 2:42 AM
Sequenceにあるものはとりあえずあるんだっけ
2:42 AM
combineLatestはSequenceには無いけどAsyncSequenceだとほしいね。
Avatar
基本 Sequence と同じのしかないですよねー。
Avatar
omochimetaru 6/24/2021 2:43 AM
ただ、実装がしやすいってのは重要だと思ってて、ライブラリも出てきやすいと思う。
Avatar
サードパーティライブラリはたくさん出てくると思う。
Avatar
omochimetaru 6/24/2021 2:43 AM
Rxとかだと、思いついても実装が難しいから、もりあがりにくい
Avatar
asyncなflatMap書きやすそう。Combineで起きたeraseToAnyPublisher問題も解決するし。
Avatar
Avatar
koher
サードパーティライブラリはたくさん出てくると思う。
omochimetaru 6/24/2021 2:46 AM
しばらく様子見てから標準に追加するものを議論する流れになる気がします
Avatar
有用なものが標準に追加されるといいなぁ。結構標準ライブラリは保守的だと思うから。 (edited)
Avatar
omochimetaru 6/24/2021 2:50 AM
swift-collectionsみたいに外部化されるかもしれないですね
2:50 AM
swift-streamsみたいな。
Avatar
Apple製の準標準なら外部でもいいね。メンテの継続が期待できるから。 (edited)
Avatar
omochimetaru 6/24/2021 2:57 AM
確かにそこが結構違いますね。一瞬流行ったライブラリでもメンテが止まるのがワリとある
Avatar
Avatar
Yuta Saito
asyncなflatMap書きやすそう。Combineで起きたeraseToAnyPublisher問題も解決するし。
これは怪しい予感がする…
4:02 AM
型は雪だるまなんだよな (edited)
Avatar
だめじゃん…
4:03 AM
そっかストリーム自体は言語機能として表現できないからダメか
Avatar
いうてSequence.flatMapがArrayなのはズルしてるだけですからね
4:03 AM
事実上のTypeErasure (edited)
Avatar
AnyAsyncSequeceがひつよう
Avatar
↓みたいなこと書こうとしたらコンパイルエラーになった。 guard let でシャドーイングすると、 { } の中では(バインド先の変数にアクセスできないのは当たり前として)元の変数にもアクセスできなくなる。コードリーディング時の勘違いを減らすにはこれでいいのかもしれないけど・・・。 guard let response = response as? HTTPURLResponse else { assertionFailure("Never reaches here.") print(type(of: response)) return } (edited)
Avatar
Kishikawa Katsumi 7/2/2021 10:17 AM
guard letのこれは私もちょくちょく不便だなと思っています。
😢 1
Avatar
omochimetaru 7/2/2021 11:31 AM
あーそうか。元は見えて良いですねこれ。
Avatar
理論上はそうなんだけど、↑のコードをぱっと見で print(type(of: response))response がシャドーイング前のものって読み取りづらい気もするから、まあ妥当な制約かもなぁと。これまで遭遇したことなかったからこんなケースあったのかと思って。↑のケースでは結局 guard let httpResponse = response as? ... にした。
Avatar
omochimetaru 7/7/2021 3:06 AM
I am sorry if I missed this (I haven't had a chance to read through all the posts above, so maybe this is out of scope or unsupported) but I was wondering if it would be possible to assign a shared value to all instances declared in a given type? For example, I might have a @Preference property wrapper and I want to inject an instance of some ty...
3:06 AM
このスレちまちま読み進めてやっと追いついた
3:08 AM
static function parameter はなんか不思議な機能だけど便利そうな気もする
Avatar
言語機能としてサポートされると、Reactだとreducerやstoreの宣言がstaticに出来ていてhookを使うのが楽、みたいなのが、SwiftUIでも再現できるようになるかもしれないみたいなことをぼんやり考えていた
Avatar
omochimetaru 7/7/2021 3:15 AM
Reactの件がどういう話かわからないけど、これは指定はしないといけないから、ユーザー側の楽さは変わらない話だと思うよ
3:15 AM
実行時の値が静的に定義されてポインタ渡しになるという話
Avatar
議論が2,3段あるので説明が面倒いのだけどwebアプリだとブラウザのbackForardListがあるお陰でstatic宣言されたものも事実上インスタンス化されている、みたいなところがあってiOSだとそれは出来ないが、shared storageが解決しそうだねって話。 static function parameterは言及先ではなかった
Avatar
omochimetaru 7/7/2021 3:29 AM
インスタンス間で同じものを参照してる構造にマッチするということかな
Avatar
そうそう
3:42 AM
枝葉のコンポーネントはhookで親のコンポーネントが持つリソースにアクセスしたいが、親が異なる場合は異なるリソースになる。 ブラウザだとここにbackForardListが挟まるのでstatic宣言でも成り立つ(まあ色々あるけど省略する)が、iOSだとNavigationStackに詰まれてるからそういう飛び道具にstatic変数は使いにくかった
Avatar
Swiftのdefer、いつから変数宣言前から使えるようになったっけ…? do { defer { print(a) } // ←まだaが宣言されてないよ…? let a = 0 }
Avatar
omochimetaru 8/2/2021 8:02 AM
バグだと思う 名前解決がそうなる状況他にないし
Avatar
Avatar
lovee
Swiftのdefer、いつから変数宣言前から使えるようになったっけ…? do { defer { print(a) } // ←まだaが宣言されてないよ…? let a = 0 }
便利。。
Avatar
Avatar
lovee
Swiftのdefer、いつから変数宣言前から使えるようになったっけ…? do { defer { print(a) } // ←まだaが宣言されてないよ…? let a = 0 }
Swift 5.5 で殺されてますね https://github.com/apple/swift/pull/36441 @swift-main do { defer { print(a) } // ←まだaが宣言されてないよ…? let a = 0 } ... お、swiftbot-sandbox でさんざん実験済みだったのか笑 (edited)
While &#39;defer&#39; is implemented as a local function, it doesn&#39;t behave as one. In particular, since SILGen runs it after destroying all local bindings that appear after the &am...
Avatar
swiftNightly BOT 8/2/2021 4:29 PM
exit status: 1 with stderr:<stdin>:2:19: error: use of local variable 'a' before its declaration defer { print(a) } // ←まだaが宣言されてないよ…? <stdin>:3:9: note: 'a' declared here let a = 0 ^
Avatar
Swift Forumsに上げたらChris Lattner氏にコメントもらった 🤪 https://forums.swift.org/t/defer-can-take-variables-declared-after-itself-bug-or-feature/50821/8 (edited)
Yeah, I agree -- this seems like a compiler bug to me.
Avatar
omochimetaru 8/3/2021 7:40 AM
おお、SE登録された。あれ、でももうnightlyでバグとして検出されるようになっているのに? (edited)
Avatar
Currently, we only support opaque result types as top level level types, e.g. some P is allowed but not (some P)?. This branch adds support for opaque result types in structural type positions.
3:46 PM
(some P)? みたいなのができるようになるっぽい?
🙌 1
Avatar
omochimetaru 8/4/2021 4:17 PM
見かけないアイコンだ
Avatar
少し前にリバースジェネリクスのPR出してた人ですね
Avatar
omochimetaru 8/4/2021 4:20 PM
ほおー
4:20 PM
func twoOpaqueTypes() -> (some P, some P) { return (1, 2) } // expected-error{{only one 'opaque' type is supported}}
4:20 PM
2つはだめらしい?
4:20 PM
それは続きなのかな。
Avatar
ジェネリック型全般で使えるのはかなり楽になりそう
4:24 PM
// ERROR: function declares an opaque return type, but has no return statements in its body from which to infer an underlying type // func asHOFRetArg() -> (some P) -> () { return { (x: String) -> () in } } // これなんでinferできないんだろう (edited)
Avatar
omochimetaru 8/4/2021 5:30 PM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
5:30 PM
↑裏技集が出た
Avatar
知らないのめっちゃある・・・。
Avatar
裏技集w
Avatar
Kishikawa Katsumi 8/5/2021 4:07 AM
@_optimize([none|size|speed]) これおもしろい。 関数ごとに最適化モード変えられるんだ。
4:08 AM
リリースモード(最適化あり)だと不具合があるパターンのときに、全体をデバッグモードでビルドしなくても回避できたりする?のかな?
Avatar
その目的でたまに使いますね
Avatar
Kishikawa Katsumi 8/5/2021 4:12 AM
使えるんだ!いいことを聞いた。
Avatar
omochimetaru 8/5/2021 4:12 AM
opt noneそれいいですよね。 コード生成を観察する時にも便利。
Avatar
Kishikawa Katsumi 8/5/2021 4:13 AM
へえ〜
4:14 AM
というか眺めてるとほとんどの最適化というかコンパイラの挙動は関数単位で制御できてなんか困った場合は関数単位でいろいろやったらいいということか。
Avatar
え、これ逆に普段デバッグモードで作業しつつ特定の高負荷な関数だけ最適化するとかもできるんですか?
Avatar
Kishikawa Katsumi 8/5/2021 4:14 AM
できそう。
Avatar
そっちはできるのかな
Avatar
omochimetaru 8/5/2021 4:15 AM
下げ方向にしか効かないのか、それとも、関数指定が絶対優先するのか (edited)
4:16 AM
たしかにデバッグで作業したいけど特定箇所の性能が落ちて全体がどうしようもないみたいな事あるな
Avatar
Kishikawa Katsumi 8/5/2021 4:16 AM
@_optimize(none) func fib1() {...} @_optimize(speed) func fib2() {...} こういうのを用意したら確かめられるかな?
Avatar
多分sizeとspeedは最適化パス内での挙動を操作するやつで、最適化パス列自体のプランニングは変わらない気がする (edited)
Avatar
Kishikawa Katsumi 8/5/2021 4:16 AM
なるほど。
Avatar
omochimetaru 8/5/2021 4:16 AM
ああそっか、例のパイプライン構築は別であるからか
Avatar
逆はだめか〜
Avatar
Kishikawa Katsumi 8/6/2021 12:45 AM
@_private(sourceFile: "FileName.swift")
Fully bypasses access control, allowing access to private declarations in the imported module. The imported module needs to be compiled with -Xfrontend -enable-private-imports for this to work.
これも便利そうだ
Avatar
SwiftUIのプレビューに使われてるやつですね
Avatar
Kishikawa Katsumi 8/6/2021 12:48 AM
おお、そういうことか!
Avatar
@_spi import でも似たようなことができますね(こっちはパッケージ単位だけど)
Avatar
Kishikawa Katsumi 8/6/2021 12:22 PM
Marks a declaration as SPI (System Programming Interface), instead of API. Modules exposing SPI and using library evolution generate an additional .private.swiftinterface file (with -emit-private-module-interface-path) in addition to the usual .swiftinterface file. This private interface exposes both API and SPI. Clients can access SPI by marking the import as @_spi(spiName) import Module. This design makes it easy to find out which clients are using certain SPIs by doing a textual search.
なるほどねえ。 SPI(System Programming Interface)というのはなんなのですか?
Avatar
omochimetaru 8/6/2021 1:41 PM
それよく知らないままだ
3:45 AM
マージされてたけど、さっきリバートされてた
Avatar
omochimetaru 8/27/2021 3:45 AM
え〜。
3:45 AM
これあればうれしい場面に遭遇しているのではやくほしい。
Avatar
revert...
Avatar
まー壊したテスト直せば再上陸できそう
Avatar
URLSession の新しい data(from:) メソッドを Taskcancel メソッドでキャンセルしたら、 CancellationError じゃなくて code == NSURLErrorCancelledNSErrorthrow される😂
10:34 AM
Version 13.0 beta 5 (13A5212g)
Avatar
あ~ それはそうなりそう・・・
10:35 AM
NSErrorから URLError
10:35 AM
as でキャストできますよ
10:35 AM
そのあと e.code == .cancelled かな
Avatar
これは data(from:) メソッドの実装で code をチェックして CancellationError を投げるべきでは?
10:36 AM
というか、 Task がキャンセルされているかをチェックして URLSessionDataTask をキャンセルしてるコードがあるはずで、そこで管理すべき?
Avatar
checkCancellation が投げるデフォルトのエラーとして CancellationError は定義されてるけど、Concurrencyのキャンセル機構としてそこは実装依存か
10:38 AM
例えば、キャンセルまでに得られた途中のデータを伝えるためにエラーオブジェクトにデータを入れる、みたいなケースは結構あると思うので CancellationError に寄せるのは難しいと思います (edited)
Avatar
CancellationErrorvar source: Error? を持つようにすれば解決できそうな?
Avatar
そうですねー。1つの解決策だと思います
10:43 AM
もしくはプロトコルになってたら良かったんですかね。
Avatar
うーん、 CancellationErrorisCancelled == true のときに Task.checkCancellation が投げるエラーというだけで、キャンセルされたときに throw されるエラーは CancellationError とは限らないという仕様なのかな? catch let error as CancellationError でキャンセルをチェックするのではなく、 catch 節の中で Task.isCancelled でチェックするのが正しい? (edited)
10:49 AM
URLSessiondata(from:) がどこで実装されてるのか見つからない・・・。
10:56 AM
Conventionally, most functions that check for cancellation report it by throwing CancellationError()
だから必ずしも CancellationErrorthrow しなくても良い?でも
Operations running synchronously as part of the task can check this flag and are conventionally expected to throw a CancellationError
とあるので、 CancellationErrorthrow することが期待されている? URLSession.data(from:)cancel 時に CancellationErrorthrow しないのはお行儀が悪い? https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md#cancellation
(edited)
11:00 AM
For tasks that would prefer to immediately exit with a thrown error on cancellation, the task API provides a common error type, CancellationError, to communicate that the task was cancelled.
この communicate の温度感もわからないな。キャンセルされたことを CancellationError として検出できるように、くらいの意味まで持つならキャンセル時に独自のエラーを throw するのではなく CancellationErrorthrow すべきとなりそうだけど。
11:02 AM
いずれにせよ、キャンセル時にどんなエラーが投げられるかは実装依存だから、 API 利用側でキャンセルされたかを区別する必要がある場合、 do { try await foo() } catch let error as CancellationError { // キャンセル時の処理 } catch { // エラーハンドリング } とするよりも do { try await foo() } catch { if Task.isCancelled { // キャンセル時の処理 } else { // エラーハンドリング } } がベストプラクティス? (edited)
Avatar
キャンセルされたかどうかはthrowされたエラーで決められるのではなく、 cancel メソッドを呼んだレシーバのTaskに対してキャンセルフラグが立つ実装になっています。
Avatar
Avatar
Yuta Saito
キャンセルされたかどうかはthrowされたエラーで決められるのではなく、 cancel メソッドを呼んだレシーバのTaskに対してキャンセルフラグが立つ実装になっています。
cancel メソッドを呼んだレシーバのTaskに対してキャンセルフラグが立つ実装
それを受けて、非同期 API 実装側は Task.checkCancellation() を呼ぶか、 Task.isCancelled をチェックして適切な処理を行った後に CancellationErrorthrow するというルールなのかと思っていました。
Avatar
なるほど。
11:09 AM
そういう意味だと、 CancellationErrorはlightweightなキャンセル通知を意図したもので、キャンセル時にはCEを使うのがルール、ということはないと思います。 (edited)
11:10 AM
It is intentional that no information is passed to the task about why it was cancelled. A task may be cancelled for many reasons, and additional reasons may accrue / after the initial cancellation (for example, if the task fails to immediately exit, it may pass a deadline). The goal of cancellation is to allow tasks to be cancelled in a lightweight way, not to be a secondary method of inter-task communication.
(edited)
Avatar
なるほど。じゃあやっぱり API 利用側がキャンセルをハンドリングする必要がある場合は catch 節で Task.isCancelled でチェックするのが良さそうですね。 (edited)
11:15 AM
たとえば、 func download(...) async throws -> Data を呼び出して、自分がキャンセルボタンを押した場合と何かしらエラーが発生した場合のどちらもエラーが throw されるけど、前者では何もしないけど後者ではアラートを出したいみたいなケースを想定しています。 (edited)
Avatar
となると try { await download() } catch { if Task.isCancelled { throw error // or return } switch error { case let error as HogeError: // ... } } みたいな感じになるんですかね? (edited)
Avatar
Avatar
rinsuki
となると try { await download() } catch { if Task.isCancelled { throw error // or return } switch error { case let error as HogeError: // ... } } みたいな感じになるんですかね? (edited)
そうなのかなぁとイメージしてます。
Avatar
Task.isCancelled だと
Avatar
その場合は、downloadするTaskはUnstructuredな Task インスタンスとしてどこかに保持されていると思うので、 そのTaskに対して task.isCancelled するのが良いと思います。
Avatar
Task APIでキャンセルした場合しかtrueにならないですよね
11:19 AM
URLSessionのcancelメソッドを直接呼んだ場合とかが逆に漏れる
Avatar
Avatar
omochimetaru
Task APIでキャンセルした場合しかtrueにならないですよね
API 利用側はどのような手段でキャンセルしたかは知っているからいいんじゃないかな?キャンセルするのも、キャンセルをハンドリングする(アプリの挙動を変える)のも利用側なので。 (edited)
Avatar
なるほど
Avatar
Avatar
Yuta Saito
その場合は、downloadするTaskはUnstructuredな Task インスタンスとしてどこかに保持されていると思うので、 そのTaskに対して task.isCancelled するのが良いと思います。
catch でエラーが飛んできたところで分岐しないといけなくないですか?それとも Task { } の中で catch せずに task.result で結果を受け取った方が良い?
Avatar
var downloadTask: Task<Data, Error>? func didTapDownload() { let task = Task { try await download(...) } self.downloadTask = task do { let result = try await task.value } catch { if task.isCancelled { ... } } } func didTapCancell() { self.downloadTask?.cancel() } こういうのを想像してました。 (edited)
👍 1
Avatar
Avatar
Yuta Saito
var downloadTask: Task<Data, Error>? func didTapDownload() { let task = Task { try await download(...) } self.downloadTask = task do { let result = try await task.value } catch { if task.isCancelled { ... } } } func didTapCancell() { self.downloadTask?.cancel() } こういうのを想像してました。 (edited)
これdidTapDownloadがasyncじゃないから、やっぱりTask { }のクロージャ式の中でハンドリングした方が良さそうな?
Avatar
あー、そういうことでしたか。
11:40 AM
たしかに didTapXX はasyncにできないからStructuredにしちゃいけないですね
11:42 AM
そうするとTask { } クロージャの中でcatchするのか…
Avatar
そうなるとやっぱりTask.isCancelledでチェックかなぁ。
Avatar
そうですねえ。 URLSessionがcancelをハンドリングして大域脱出してるところを、同じタスク内で途中で掴むのは若干気持ち悪いんですが、これは感覚の問題なのかな。
Avatar
Avatar
Yuta Saito
そうですねえ。 URLSessionがcancelをハンドリングして大域脱出してるところを、同じタスク内で途中で掴むのは若干気持ち悪いんですが、これは感覚の問題なのかな。
うーん、そう言われると確かに若干気持ち悪い気も。ただ、 download の戻り値をわざわざ Task の外側でハンドリングするのも若干気持ち悪い気もするし、 task.valueasync の中に入れるためにもう一つ Task 作るとかはもっと気持ち悪いので仕方なさそうですね。 (edited)
Avatar
そうなんですよ。仕方ない 😢
Avatar
昨日、ちょうど同じようなところを見ていて、メソッド内でCancellationErrorをスローしたい場合は https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md#cancellation-handlers のソースコード例に書いてあるように(urlSessionTask captureしないとコンパイルできない) func download(url: URL) async throws -> Data? { var urlSessionTask: URLSessionTask? return try withTaskCancellationHandler { return try await withUnsafeThrowingContinuation { continuation in urlSessionTask = URLSession.shared.dataTask(with: url) { data, _, error in if let error = error {     ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ // Ideally translate NSURLErrorCancelled to CancellationError here continuation.resume(throwing: error) } else { continuation.resume(returning: data) } } urlSessionTask?.resume() } } onCancel: { urlSessionTask?.cancel() // runs immediately when cancelled } } withTaskCancellationHandler使って手動でチェックするのがいいんですかね?(結局呼び出し側でError Typeチェックしなければいけないので、あまり意味ない気もしますが...)🤔 (edited)
Avatar
おおお、ここ完全に見逃してました。
1:18 AM
あー、これは非同期 API 利用側がキャンセルをハンドリングするためのものではなくて、実装側がキャンセルをハンドリングするためのものか。
1:19 AM
task.cancel が呼び出されたときに、 download 関数の実装者は URLSessionTask を即時 cancel したいけど、それを実現するために使えるという。
1:21 AM
Ideally translate NSURLErrorCancelled to CancellationError here
については、やっぱり Convention 上はキャンセル時は CancellationErrorthrow されるようにしたいという意識なのかな。ただ、 100% 保証は無理だから、やっぱり呼び出し側では as CancellationError で判別するのではなく Task.isCancelled が良さそう。
Avatar
一体どうすれば?(そして Proposal のコードに await が抜けてることに気付いた)
1:46 AM
↓なら通ったけど、ちょっと・・・。そして onCancelSendable でない Box を渡せてしまってるのはなぜ??? func download(url: URL) async throws -> Data? { let urlSessionTask: Box<URLSessionTask> = .init() return try await withTaskCancellationHandler { return try await withUnsafeThrowingContinuation { continuation in let task = URLSession.shared.dataTask(with: url) { data, _, error in if let error = error { // Ideally translate NSURLErrorCancelled to CancellationError here continuation.resume(throwing: error) } else { continuation.resume(returning: data) } } task.resume() urlSessionTask.value = task } } onCancel: { urlSessionTask.value?.cancel() // runs immediately when cancelled } } final class Box<Value> { var value: Value? }
Avatar
onCancelのクロージャで[urlSessionTask]をcapture listに入れる必要がありますかね?🤔 onCancel: { [urlSessionTask] in urlSessionTask?.cancel() // runs immediately when cancelled } Sendableチェックはmainでも起きませんか?おそらくこのPRがrelease/5.5に入ってないからチェックされてないんじゃないかなーと思いました。 https://github.com/apple/swift/pull/38866 SwiftFiddleでやってみたらmainの場合warningが出ました。 /main.swift:21:7: warning: cannot use let 'urlSessionTask' with a non-sendable type 'Box<URLSessionTask>' from concurrently-executed code urlSessionTask.value?.cancel() // runs immediately when cancelled ^ /main.swift:25:13: note: generic class 'Box' does not conform to the `Sendable` protocol final class Box<Value> { (edited)
Rework Sendable checking to be completely based on &quot;missing&quot; conformances, so that we can individually diagnose missing Sendable conformances based on both the module in which the...
Avatar
onCancelのクロージャで[urlSessionTask]をcapture listに入れる必要がありますかね?
capture list に入れても nil の状態で capture されるだけで変更が反映されなくないでしょうか?
7:28 PM
おそらくこのPRがrelease/5.5に入ってないからチェックされてないんじゃないかな
なるほど。 Sendable のチェックはまだお預けなんですね・・・。
7:29 PM
7:30 PM
Structured Concurrency なんてまだ Active Review のまま😂 https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md
😂 1
Avatar
@MainActor も付けてないのに↓のコンパイルエラーになるのなぜ??そして Task.detached の代わりに Task.init を使うと起こらない・・・。 Version 13.0 beta 5 (13A5212g) final class UserViewController: UIViewController { let userID: User.ID var user: User? ... override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { [self] in do { let user = try await fetchUser(for: userID) self.user = user // ⛔ Property 'user' isolated to global actor 'MainActor' can not be mutated from a non-isolated context } catch { // エラーハンドリング } } } }
Avatar
UIViewController に付いてのか。 @MainActor class UIViewController : UIResponder https://developer.apple.com/documentation/uikit/uiviewcontroller
8:19 PM
Task.init だと MainActor 上で実行されるけど、 detached だとそうじゃないからエラーになってしまったと。
8:23 PM
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { [self] in do { let user = try await fetchUser(for: userID) DispatchQueue.main.async { [self] in self.user = user } } catch { // エラーハンドリング } } }
8:23 PM
↑で MainActor に戻したらいけたけど、 DispatchQueue.main よりもいい方法ないんだっけ?
8:25 PM
DispatchQueue.main って型じゃないけど、どうやって MainActor と紐付いてるの?( DispatchQueue.global() だとコンパイルエラー)
8:26 PM
よく考えたら Global Actor の Proposal ちゃんと読んでなかった。ここに答えがあるのかな・・・。 https://github.com/apple/swift-evolution/blob/main/proposals/0316-global-actors.md
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0316-global-actors.md at main · apple/swift-evolution
Avatar
extension UserViewController { func setUser(_ user: User?) { self.user = user } } 作っておいて await self.setUser(user) とか?
Avatar
お、↓でいけた。 override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { @MainActor [self] in do { let user = try await fetchUser(for: userID) self.user = user } catch { // エラーハンドリング } } }
Avatar
Avatar
rintaro
extension UserViewController { func setUser(_ user: User?) { self.user = user } } 作っておいて await self.setUser(user) とか?
それって setUser も actor-isolated でダメじゃないですか?
8:30 PM
await するのか。
Avatar
UserViewController のメソッドは暗黙で MainActor isolatedになるので、他の Actor コンテキストからは暗黙に async なので await で呼べると。
8:31 PM
プロパティのセッタも暗黙 async になれば await self.user = user とかできるんだけど、そうなってないし、そうなっていない理由があるんじゃないかと。
Avatar
プロパティの async は getter only ですもんね、今のところ。
Avatar
Task.detached(priority: .background) { @MainActor [self] in って Task.init と実質かわらなくないです?
Avatar
Avatar
rintaro
Task.detached(priority: .background) { @MainActor [self] in って Task.init と実質かわらなくないです?
MainActor だけど Taskpriority.background っていうのはあり得るのかと思いましたが、 priority は queue ごとに決まっていてそんなことはない? DispatchQueuepriority って queue を作るときに決めますもんね。
8:38 PM
うーん、 setUser を作るのもなぁ・・・。 DispatchQueue.main.async { self.user = user } か、そうでなければ↓? Task { @MainActor in self.user = user }
Avatar
とりあえず Task.init は現在の Actor コンテキストを引き継ぐと思うので 今回の場合は @MainActor in はいらないと思います。
8:40 PM
await { @MainActor in self.user = user }() 🤔
Avatar
Avatar
rintaro
とりあえず Task.init は現在の Actor コンテキストを引き継ぐと思うので 今回の場合は @MainActor in はいらないと思います。
Task.init は現在の Actor コンテキストを引き継ぐと思うので 今回の場合は @MainActor in はいらない
↓みたいに Task.init ではなく Task.detached を挟んで context を引き継がないときなので MainActor に戻す必要があるかと。 override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { [self] in do { let user = try await fetchUser(for: userID); Task { @MainActor in self.user = user } } catch { // エラーハンドリング } } }
Avatar
Avatar
koher
Task.init は現在の Actor コンテキストを引き継ぐと思うので 今回の場合は @MainActor in はいらない
↓みたいに Task.init ではなく Task.detached を挟んで context を引き継がないときなので MainActor に戻す必要があるかと。 override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { [self] in do { let user = try await fetchUser(for: userID); Task { @MainActor in self.user = user } } catch { // エラーハンドリング } } }
あああ、ごめんなさい、読み違えてました
Avatar
await { @MainActor in self.user = user }()
これさっき似たようなことを試したときに await 付けないといけないことに気付いてなかったんですけど、そしたらコンパイラがクラッシュしました😅
😂 1
8:45 PM
↓は通った。 override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { [self] in do { let user = try await fetchUser(for: userID); await { @MainActor in self.user = user }() } catch { // エラーハンドリング } } }
Avatar
Avatar
koher
await { @MainActor in self.user = user }()
これさっき似たようなことを試したときに await 付けないといけないことに気付いてなかったんですけど、そしたらコンパイラがクラッシュしました😅
func foo() async { { @MainActor in }() } でクラッシュ再現しました。報告しておきます
🙇‍♂️ 1
Avatar
この場合は Task.detached で作られた Task 上で実行されて、 Task { @MainActor in だと新しい Task 上で実行されるのが違いか。ただし、どちらでも main スレッド( DispatchQueue.main 上)で実行されると。
8:53 PM
なんかよくわからなくなってきた・・・。 DispatchQueue はキューが priority を持ってるけど、 Swift Concurrency では actor (キューの保持者)ではなく Taskpriority を持っている。 Task が suspend されたときに resume される優先度が Taskpriority で決まると思ってたけど、 actor は suspend した Taskpriority に関わらずキューに突っ込んだ順に resume する?それとも MainActorDispatchQueue.main を使っている関係で Taskpriority を無視して前から処理する? (edited)
Avatar
> capture list に入れても nil の状態で capture されるだけで変更が反映されなくないでしょうか?
ああ、そうですねwコンパイルできることしか考えてなかったです😅
(edited)
Avatar
actor は suspend した Task の priority に関わらずキューに突っ込んだ順に resume する?
WWDCのセッションでこのように言っていたので、優先順位に合わせて入れ替えるものだと思っていました🤔 Since actors are designed for reentrancy, the runtime may choose to move the higher-priority item to the front of the queue, ahead of the lower-priority items. This way, higher-priority work could be executed first, with lower-priority work following later. This directly addresses the problem of priority inversion, allowing for more effective scheduling and resource utilization. https://developer.apple.com/videos/play/wwdc2021/10254/?time=2160
それとも MainActor は DispatchQueue.main を使っている関係で Task の priority を無視して前から処理する?
DispatchQueue経由なので厳格に順番通りなんですかね...?🤔
(edited)
Dive into the details of Swift concurrency and discover how Swift provides greater safety from data races and thread explosion while...
Avatar
WWDCのセッションでこのように言っていたので、優先順位に合わせて入れ替えるものだと思っていました
なるほど、それなら普通の actor は入れ替えてくれそうな感じがしますね。
DispatchQueue経由なので厳格に順番通りなんですかね...?
DispatchQueueDispatchWorkItemqos を指定できるみたいですね。使ったことなかった。 https://developer.apple.com/documentation/dispatch/dispatchworkitem
3:48 AM
そうすると MainActor でも priority を考慮してくれそう。
3:50 AM
なら↓もありな可能性があるのかな? override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { @MainActor in do { let user = try await fetchUser(for: userID) self.user = user } catch { // エラーハンドリング } } } @MainActor のクロージャ式が丸ごと↓の block に突っ込まれるイメージ? DispatchQueue.main.async(DispatchWorkItem(qos: .background, block: /* ここ */)) (edited)
Avatar
勘違いしているかもしれませんが...💦 DispatchQueue.mainはSerial Queueなので、qosが高いDispatchWorkItemが追加されても、前のDispatchWorkItemqos上げて先に実行してしまわないんでしょうか?(priority inversionが起きる?)
Avatar
ちゃんと話終えてないかもしれないですが、この辺の話ですか? https://github.com/apple/swift/blob/068291cba7199051bcd9e19aa3c1268a3c6b1e4a/stdlib/public/Concurrency/GlobalExecutor.cpp#L319-L328
5:26 AM
We cannot safely elevate the priorities of work added to this queue using Dispatch's public API, but as discussed above, that is less important than avoiding performance problems.
Avatar
Avatar
shiz
勘違いしているかもしれませんが...💦 DispatchQueue.mainはSerial Queueなので、qosが高いDispatchWorkItemが追加されても、前のDispatchWorkItemqos上げて先に実行してしまわないんでしょうか?(priority inversionが起きる?)
omochimetaru 8/31/2021 5:26 AM
その話まさにWWDCでスライドを見た気がします
5:27 AM
後ろの高qosを消化するために前の待ちタスクが昇格する (edited)
Avatar
ちゃんと話終えてないかもしれないですが、この辺の話ですか?
あ、そうですね。このコメントの話だと思います(難しくて完全に理解できているわけではありませんがw)
その話まさにWWDCでスライドを見た気がします
はい、WWDCのこの辺りで話されていました。 https://developer.apple.com/videos/play/wwdc2021/10254/?time=1984
Dive into the details of Swift concurrency and discover how Swift provides greater safety from data races and thread explosion while...
Avatar
WWDCのセッションでこのように言っていたので、優先順位に合わせて入れ替えるものだと思っていました
そういえばactorでも実行中のTaskに関してはPriority Inversionが発生するとソースドキュメントに書いてありましたね https://github.com/apple/swift/blob/release/5.5-08092021/stdlib/public/Concurrency/Task.swift#L208 このテストがその挙動を表しているぽいですね👀 https://github.com/apple/swift/blob/main/test/Concurrency/Runtime/async_task_priority_current.swift#L11
(edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
そうか、ちょっと勘違いしてました。並行にキューに入れたときにどの順番で突っ込まれたかは重要ではないから、優先度の高いアイテムはプライオリティに基づいて(たとえばバブルソートの要領で末尾から舐めて)適切な位置に挿入すればいいんじゃないかと思ってましたが、同じスレッドから順番にキューに入れた場合は順番が保証されていないと困る場合もあるから、キューに入っているアイテムの順番は入れ替えることはできなですね。なので、優先度の高いアイテムより前にあるアイテムの優先度を高めるしかないと。
👍 1
Avatar
omochimetaru 9/7/2021 5:51 PM
The fourth review of SE-0304: Structured Concurrency has ended and the proposal has been accepted with modifications. Much of the fourth revision was about naming and the community was broadly positive about these changes, with discussion focused on a few specific points. The naming of the function suspend, that frees the task mid-function, wa...
🙌🏻 3
5:51 PM
APIついに固まった
Avatar
omochimetaru 9/13/2021 1:02 PM
Hey everyone! A few weeks ago I pitched Shared Storage for Property Wrappers, and TL;DR it was restructured into 3 other features. One of them, @expanded parameters, is what I'd like to get feedback on today. The updated proposal is on GitHub. Introduction Swift is a language that allows us to write expressive API interfaces. With features li...
1:03 PM
関数の仮引数に付けられる新しいアトリビュート @expanded を追加する提案 これがついている引数は、その型の init の引数を、直接その関数の引数として渡せる。 (edited)
1:10 PM
いいじゃんと思ったんだけど、フォーラム読んでたらjroseさんがstrongly againstしていて、書き込みを読んだらうーむ確かにと思えてきた
Avatar
Library evolutionの面で突っ込むの流石だなぁ
Avatar
omochimetaru 9/13/2021 1:19 PM
たしかに。
Avatar
associatedtypeのあるprotocolをORTにした場合に、associatedtypeの部分を指定する方法って無いですよね
11:40 AM
指定無しで推論もされない、つまりFoo<some Bar>みたいなことを実現する術が無いように見える (edited)
Avatar
protocol P { associatedtype Value } protocol Q: P where Value == Int {} このQ を作るのをサボりたいってことですか?
Avatar
Valueの型がややこしくなるからORTにしたい場合に、その外側にPがある場合に出来なくなるなという話です
Avatar
なるほど。これだと手で型を書かないといけないので複雑な型には使えないですね
Avatar
omochimetaru 9/24/2021 9:30 AM
@swift-5.5.3 protocol Base { func foo() func bar() } protocol Derived: Base { func foo() override func bar() }
Avatar
Avatar
omochimetaru
@swift-5.5.3 protocol Base { func foo() func bar() } protocol Derived: Base { func foo() override func bar() }
no output
Avatar
omochimetaru 9/24/2021 9:30 AM
@swift-5.5.3 -warn-implicit-overrides protocol Base { func foo() func bar() } protocol Derived: Base { func foo() override func bar() }
Avatar
Avatar
omochimetaru
@swift-5.5.3 -warn-implicit-overrides protocol Base { func foo() func bar() } protocol Derived: Base { func foo() override func bar() }
stderr:<stdin>:7:10: warning: implicit override should be marked with 'override' or suppressed with '@_nonoverride' func foo() ^ override <stdin>:2:10: note: overridden declaration is here func foo() ^
Avatar
https://github.com/apple/swift/commit/f8e53d912954e63f967fc6e0450731a40f4cc08b このコミットのためにつくられたっぽいですね
Add the -warn-implicit-overrides flag when building the standard library and overlays, so that each protocol member that overrides a member of an inherited protocol will produce a warning unless ...
5:23 PM
public protocol BaseP { func foo() func bar() } public protocol DerivedP: BaseP { override func foo() @_nonoverride func bar() } public struct Concrete: DerivedP { public func foo() {} public func bar() {} } のときの witness table が sil_witness_table Concrete: DerivedP module test { base_protocol BaseP: Concrete: BaseP module test method #DerivedP.bar: <Self where Self : DerivedP> (Self) -> () -> () : @$s4test8ConcreteVAA8DerivedPA2aDP3baryyFTW // protocol witness for DerivedP.bar() in conformance Concrete } sil_witness_table Concrete: BaseP module test { method #BaseP.foo: <Self where Self : BaseP> (Self) -> () -> () : @$s4test8ConcreteVAA5BasePA2aDP3fooyyFTW // protocol witness for BaseP.foo() in conformance Concrete method #BaseP.bar: <Self where Self : BaseP> (Self) -> () -> () : @$s4test8ConcreteVAA5BasePA2aDP3baryyFTW // protocol witness for BaseP.bar() in conformance Concrete }@_nonoverride と明示された requirement は別の witness になる。
Avatar
omochimetaru 9/24/2021 5:27 PM
ふむふむ、つまり、名前は同じだけど、名前が違うかのようにテーブルエントリが作られて
5:27 PM
conformするメソッドは両方に登録される
5:28 PM
nonoverrideの方はアンスコがついてるけど、overrideは普通のキーワードなのは、
5:28 PM
同じ名前ならオーバーライドになるのは従来の普通の挙動だから?
5:30 PM
A protocol requirement marked ‘override’ only makes sense when the declaration is needed to help associated type inference, which is why the ‘override’ annotations correlate so closely with ABI FIXMEs.
5:30 PM
associated typeの推論のヒントになる・・・?
Avatar
具体例がほしいですね。。。
Avatar
omochimetaru 9/24/2021 5:34 PM
BidirectionalCollection.index(_:offsetBy:) is the most obvious example, because the BidirectionalCollection ’s version of index(_:offsetBy:) allows negative indices. RandomAccessCollection ’s version is also marked @_nonoverride because it is required to be asymptotically faster than the Collection or BidirectionalCollection versions.
5:35 PM
nonoverrideの方は最も明らかな例としてなんか書いてあるけどわからねえ・・・
Avatar
@_nonoverride に関しては public protocol BaseP { func foo() func bar() } public extension BaseP { func foo() { print("BaseP.foo()") } func bar() { print("BaseP.bar()") } } public protocol DerivedP: BaseP { override func foo() @_nonoverride func bar() } public extension DerivedP { func foo() { print("DerivedP.foo()") } func bar() { print("DerivedP.bar()") } } public struct Concrete: DerivedP {}
Avatar
omochimetaru 9/24/2021 5:36 PM
テーブルエントリが別になる事はわかったけどそれにより何が嬉しいのかがわからない
Avatar
みたいなときに、 sil_witness_table Concrete: DerivedP module test { base_protocol BaseP: Concrete: BaseP module test method #DerivedP.bar: <Self where Self : DerivedP> (Self) -> () -> () : @$s4test8ConcreteVAA8DerivedPA2aDP3baryyFTW // protocol witness for DerivedP.bar() in conformance Concrete } sil_witness_table Concrete: BaseP module test { method #BaseP.foo: <Self where Self : BaseP> (Self) -> () -> () : @$s4test8ConcreteVAA5BasePA2aDP3fooyyFTW // protocol witness for BaseP.foo() in conformance Concrete method #BaseP.bar: <Self where Self : BaseP> (Self) -> () -> () : @$s4test8ConcreteVAA5BasePA2aDP3baryyFTW // protocol witness for BaseP.bar() in conformance Concrete } こうなるんだけど
Avatar
omochimetaru 9/24/2021 5:36 PM
はい
Avatar
この状態で 最後の protocol witness for BaseP.bar() を呼び出す方法がわからないので、
何が嬉しいのかがわからない
です笑
😆 1
Avatar
omochimetaru 9/24/2021 5:38 PM
<T: BaseP>で受け取った時はそっちが使われそうです。
Avatar
@swift-5.5.3 public protocol BaseP { func foo() func bar() } public extension BaseP { func foo() { print("BaseP.foo()") } func bar() { print("BaseP.bar()") } } public protocol DerivedP: BaseP { override func foo() @_nonoverride func bar() } public extension DerivedP { func foo() { print("DerivedP.foo()") } func bar() { print("DerivedP.bar()") } } public struct Concrete: DerivedP { } func testBase<T: BaseP>(x: T) { x.foo() x.bar() } func testDerived<T: DerivedP>(x: T) { x.foo() x.bar() } testBase(x: Concrete()) testDerived(x: Concrete())
Avatar
Avatar
rintaro
@swift-5.5.3 public protocol BaseP { func foo() func bar() } public extension BaseP { func foo() { print("BaseP.foo()") } func bar() { print("BaseP.bar()") } } public protocol DerivedP: BaseP { override func foo() @_nonoverride func bar() } public extension DerivedP { func foo() { print("DerivedP.foo()") } func bar() { print("DerivedP.bar()") } } public struct Concrete: DerivedP { } func testBase<T: BaseP>(x: T) { x.foo() x.bar() } func testDerived<T: DerivedP>(x: T) { x.foo() x.bar() } testBase(x: Concrete()) testDerived(x: Concrete())
DerivedP.foo() DerivedP.bar() DerivedP.foo() DerivedP.bar()
Avatar
omochimetaru 9/24/2021 5:45 PM
@swift-5.5.3 protocol Base { func foo() } protocol Derived: Base { @_nonoverride func foo() } struct Impl: Derived { @_implements(Base, foo()) func foo1() { print("Impl.foo1") } @_implements(Derived, foo()) func foo2() { print("Impl.foo2") } } func callBase<T: Base>(_ x: T) { x.foo() } func callDerived<T: Derived>(_ x: T) { x.foo() } callBase(Impl()) callDerived(Impl())
Avatar
Avatar
omochimetaru
@swift-5.5.3 protocol Base { func foo() } protocol Derived: Base { @_nonoverride func foo() } struct Impl: Derived { @_implements(Base, foo()) func foo1() { print("Impl.foo1") } @_implements(Derived, foo()) func foo2() { print("Impl.foo2") } } func callBase<T: Base>(_ x: T) { x.foo() } func callDerived<T: Derived>(_ x: T) { x.foo() } callBase(Impl()) callDerived(Impl())
Impl.foo1 Impl.foo2
Avatar
omochimetaru 9/24/2021 5:46 PM
呼び分けできた。
Avatar
これは嬉しい場面ありそう
Avatar
omochimetaru 9/24/2021 5:47 PM
BidirectionalCollection.index(_:offsetBy:) は、
5:48 PM
offsetとして与えられた回数だけ前(や後ろ)にオフセットをループしないといけないけど
5:49 PM
RandomAccessCollection.index(_:offetBy:) は、一気にオフセットしたインデックスを作ってアクセスできる
5:49 PM
けど・・・テーブルが別になっててほしい理由がわからん・・・
5:49 PM
BidirectionalCollectionとして見ているときであっても、実装がRandomAccessCollectionなのであれば、RandomAccessCollectionの早い実装を使いたいのだから、テーブルエントリは同一で良くないか??
Avatar
<C: BidirectionalCollection> に RandomAccessCollection が渡ってきたときに BidirectionalCollection の実装を呼びたい場面てなんだろう?
Avatar
Avatar
rintaro
<C: BidirectionalCollection> に RandomAccessCollection が渡ってきたときに BidirectionalCollection の実装を呼びたい場面てなんだろう?
omochimetaru 9/24/2021 5:50 PM
これがいま最大の謎ですね 全然obvious exampleじゃねえ・・・
5:51 PM
それとも、逆の方向で問題が起きるということか? RandomAccessCollectionなのに、BidirectionalCollectionのしょぼい実装が入ってしまうことがある? (edited)
Avatar
public protocol BaseP { func foo() func bar() } public extension BaseP { func foo() { print("BaseP.foo()") } func bar() { print("BaseP.bar()") } } public protocol DerivedP: BaseP { override func foo() @_nonoverride func bar() } public struct Concrete: DerivedP {} でエラーにならないのでそういうわけでもなさそう
Avatar
omochimetaru 9/24/2021 5:57 PM
うーむ。手元で試してみたけどそういう事も特に起こらなさそう。
5:58 PM
When a protocol restates a requirement from its inherited protocol, track that as an override the same way we do with overrides in classes. Such overrides are recorded in the AST but are omitted fr...
5:59 PM
プルリクにもうちょっと説明があるな
6:00 PM
Rolling this out in the standard library shrinks the size of the standard library binary by 196k.
Avatar
これはー、もともとのデフォルト挙動が @_nonoverride 相当だったのを override 相当にすることによって witness table が小さくなってサイズ削減できたって話っぽいですよね。
Avatar
omochimetaru 9/24/2021 6:03 PM
ふむふむ。
6:03 PM
そもそも overridenonoverride も付けない場合で、サブプロトコルで同じ名前をrequirementsに書くことができて、その場合テーブルエントリが別にできるわけですね。
6:04 PM
で、このPRでは、
6:05 PM
6:05 PM
overrideを付けてるところと、nonoverrideを付けてるところがあるから、
6:06 PM
そのままこれまでどおり別エントリであることを明示的にしたnonoverrideの方は別に何もかわってなくって、 このパッチではoverrideをつけたところに関して、テーブルエントリがなくなるからバイナリサイズが減ったよということか
6:06 PM
そうすると、なんでそもそも、同じ名前のテーブルエントリを作ってたんだ??
6:08 PM
This makes restating protocol requirements in inheriting protocols ABI-neutral, so we can restate protocol requirements to influence associated type inference without baking those decisions into the ABI.
6:14 PM
@swift-5.5.3 protocol Base { func foo() } protocol Derived: Base { func foo() } struct Impl: Derived { @_implements(Base, foo()) func foo1() { print("foo1") } @_implements(Derived, foo()) func foo2() { print("foo2") } } func callBase<T: Base>(_ x: T) { x.foo() } func callDerived<T: Derived>(_ x: T) { x.foo() } callBase(Impl()) callDerived(Impl())
Avatar
Avatar
omochimetaru
@swift-5.5.3 protocol Base { func foo() } protocol Derived: Base { func foo() } struct Impl: Derived { @_implements(Base, foo()) func foo1() { print("foo1") } @_implements(Derived, foo()) func foo2() { print("foo2") } } func callBase<T: Base>(_ x: T) { x.foo() } func callDerived<T: Derived>(_ x: T) { x.foo() } callBase(Impl()) callDerived(Impl())
foo1 foo1
Avatar
omochimetaru 9/24/2021 6:14 PM
逆ですね。どちらも付けなかった場合の挙動は、overrideです。
6:15 PM
↑のコードで、Derived.foo@_nonoverride をつけると、2行目の出力が foo2 に変わる。
6:21 PM
When a protocol restates a requirement from its inherited protocol, track that as an override the same way we do with overrides in classes.
プロトコル要求を再定義したとき、クラスのオーバライドと同じ仕組みで紐付けられる。
Such overrides are recorded in the AST but are omitted from the witness table itself.
このオーバライドはASTとして記録されているがwitness talbeでは消える。
This makes restating protocol requirements in inheriting protocols ABI-neutral,
継承先プロトコルでの再定義がABIに影響を与えない(netutral)ので
so we can restate protocol requirements to influence associated type inference without baking those decisions into the ABI.
これらの決定をABIに焼き込むことなしに、associated type推論を促すために、プロトコル要求の再定義をすることができる。
6:22 PM
ここまでは意味がまあわかる、associated type推論はずっと壊れがちだったから、これをうまく動かすために、継承先protocolでメソッドを再定義するという技があって、たとえ再定義してもオーバライド判定によりテーブルに影響はないからABI上の副作用はないと。
6:24 PM
As part of this, introduce tools that allow us to audit all of the restated protocol requirements within the standard library, via a warning new warning flag (-warn-implicit-overrides) to warn about such requirements, as well as an appropriate suppression mechanism (override to treat it as an override, @_nonoverride to give it a new witness table entry).
で、このオーバーライドがちゃんと効いてることをチェックできるように、ちゃんとマーキングした上で、マーキングなしでオーバライドしてたら通知する警告を作ったよと・・・そこもわかる。
(edited)
6:26 PM
Only those restated requirements that are meant to have a semantic effect,
再定義した要求において意味上の影響を意図しているものだけは
like BidirectionalCollection.index(_:offsetBy:),
たとえば BidirectionalCollection.indexなど
should use @_nonoverride,
は、nonoverrideを付けたほうが良い
because it commits us to having that entry in the witness table forever.
なぜならテーブルエントリを永遠に保持することを約束してくれるから。
(edited)
6:27 PM
言ってることはわかるけどやっぱりBidirectionalCollectionでそれをやりたい根本的な理由がわからないな。
6:28 PM
しかもこれ、2018年9月の話なんですよね。何年も気づかなかった。。
Avatar
AsyncSequenceでOptionalを扱いたい場合、nextの戻り値の型をOptionalのOptionalにしなければいけないのは、ループの終わり記号としてのnilと、要素としてのnilを区別するために仕方がないんですかね?(AsyncStream との比較のためにあえてAsyncSequence 使ってます) ちょっと不思議な気もしたのですが、nextの定義にOptionalが付いているのでそういうものなんですね...  改めて考えたらIteratorProtocol と同じですね(失礼しましたmm)。 mutating func next() async throws -> Self.Element? struct IntGenerator: AsyncSequence { typealias Element = Int? var strings: [String] struct AsyncIterator: AsyncIteratorProtocol { var current = 1 var strings: [String] fileprivate var index = 0 mutating func next() async -> Int?? { // <- ここ guard index < strings.count else { return nil } let string = strings[index] index += 1 return Int(string) } } func makeAsyncIterator() -> AsyncIterator { AsyncIterator(strings: strings) } } Task { let strings: [String] = ["1", "a", "2"] for await i in IntGenerator(strings: strings) { print(i) } } Optional(1) nil Optional(2) (edited)
Avatar
Avatar
shiz
AsyncSequenceでOptionalを扱いたい場合、nextの戻り値の型をOptionalのOptionalにしなければいけないのは、ループの終わり記号としてのnilと、要素としてのnilを区別するために仕方がないんですかね?(AsyncStream との比較のためにあえてAsyncSequence 使ってます) ちょっと不思議な気もしたのですが、nextの定義にOptionalが付いているのでそういうものなんですね...  改めて考えたらIteratorProtocol と同じですね(失礼しましたmm)。 mutating func next() async throws -> Self.Element? struct IntGenerator: AsyncSequence { typealias Element = Int? var strings: [String] struct AsyncIterator: AsyncIteratorProtocol { var current = 1 var strings: [String] fileprivate var index = 0 mutating func next() async -> Int?? { // <- ここ guard index < strings.count else { return nil } let string = strings[index] index += 1 return Int(string) } } func makeAsyncIterator() -> AsyncIterator { AsyncIterator(strings: strings) } } Task { let strings: [String] = ["1", "a", "2"] for await i in IntGenerator(strings: strings) { print(i) } } Optional(1) nil Optional(2) (edited)
Java 等の言語だと nullable の入れ子ができないので、 Iterator の API が hasNextnext に分かれていて、まず hasNext で存在を確認してから next を呼ぶという手順になっていますね。その点、 next だけで済ませられる Swift の設計はシンプルだと思います。
👍🏻 1
Avatar
Avatar
koher
Java 等の言語だと nullable の入れ子ができないので、 Iterator の API が hasNextnext に分かれていて、まず hasNext で存在を確認してから next を呼ぶという手順になっていますね。その点、 next だけで済ませられる Swift の設計はシンプルだと思います。
なるほど、ありがとうございます!確かにそう考えるとシンプルですね!
👍 1
Avatar
https://forums.swift.org/t/declarative-string-processing-overview/52459 Regex + 文字列パターンマッチングDSL
Declarative String Processing Overview Introduction String processing is hard and the current affordances provided by the Swift Standard Library are underpowered. We propose adding two new declarative string processing APIs—a familiar Regex literal and a more powerful Pattern result builder—to help make Swift string processing fast and easy. T...
👀 2
Avatar
オッ
3:04 AM
そういえばSwift5.5で追加されたAttributedStringは結構良かったですね
3:11 AM
他の言語でこういうRegexの外側にラッパーがあるみたいな構成が、公式から提供されてる例ってありましたっけ
3:11 AM
広義的にはperlの拡張regexとかもこの類と考えれるのかな
Avatar
ちょうど Raku の Grammar https://forums.swift.org/t/declarative-string-processing-overview/52459/13 が引き合いにだされましたね (edited)
Avatar
omochimetaru 9/30/2021 4:11 AM
func graphemeBreakPropertyData( forLine line: String ) -> (scalars: ClosedRange<Unicode.Scalar>, property: Unicode.GraphemeBreakProperty)? { line .match(/([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s*;\s(\w+).*/)? .captures.flatMap { (l, u, p) in guard let property = Unicode.GraphemeBreakProperty(p) else { return nil } let scalars = Unicode.Scalar(hex: l)! ... Unicode.Scalar(hex: u ?? l)! return (scalars, property) } }
4:12 AM
l, u, p の3要素タプルなのは正規表現パターンと対応しているのか。これはいいなあ。
4:13 AM
func graphemeBreakPropertyData( forLine line: String ) -> (scalars: ClosedRange<Unicode.Scalar>, property: Unicode.GraphemeBreakProperty)? { line.match { OneOrMore(.hexDigit).capture { Unicode.Scalar(hex: $0) } Optionally { ".." OneOrMore(.hexDigit).capture { Unicode.Scalar(hex: $0) } } OneOrMore(.whitespace) ";" OneOrMore(.whitespace) OneOrMore(.word).capture(GraphemeBreakProperty.init) Repeat(.anyCharacter) }?.captures.map { (lower, upper, property) in let scalars = lower ... (upper ?? lower) return (scalars, property) } }
4:13 AM
ResultBuilder記法もあるのね
Avatar
omochimetaru 9/30/2021 5:30 AM
これってResultBuilderになってるメリットあるのかな? 普通に配列で書けそうに見える。カンマが要らなくなってるだけじゃない?
Avatar
ResultBuilderを使うメリットがある場合は
5:41 AM
1. 複雑な型の構築 2. 1において必要となる複雑な型のピースをexpressionによる暗黙的変換の実現で見えなくする
5:41 AM
の2つで、どちらかは使ってるんじゃないだろうか
Avatar
omochimetaru 9/30/2021 5:42 AM
たしかに、 captures.map { (lower, upper, property) の3要素タプルになってるところで
5:42 AM
.match の中に書いてある3つの .capture があることと対応しているのか。
5:42 AM
配列じゃできないな。
Avatar
これは生成されている型は雪だるま式のヤバメgenericsだと思うよ
Avatar
omochimetaru 9/30/2021 5:43 AM
どうやってるんだろう、難しそうだ
5:43 AM
自由なツリー構造になる型パラメータを線形スキャンしてcaptureがある回数をタプル型に変換させないといけない
Avatar
要素があるか無しかの2択の畳み込みなら、
5:45 AM
まあ出来なくもないかな?って感じはする
Avatar
omochimetaru 9/30/2021 5:46 AM
The Swift Programming Language. Contribute to ishantheperson/swift development by creating an account on GitHub.
5:46 AM
フォーラムにプロトタイプ実装のリンクとしてここが貼ってあるけど見つからない
5:49 AM
ブランチが違うのか
5:52 AM
The Swift Programming Language. Contribute to ishantheperson/swift development by creating an account on GitHub.
5:54 AM
The Swift Programming Language. Contribute to ishantheperson/swift development by creating an account on GitHub.
5:54 AM
diffが出せた。ResultBuilder実装はまだ存在しないっぽい。
Avatar
norio_nomura 9/30/2021 5:54 AM
An early experimental general-purpose pattern matching engine for Swift. - GitHub - apple/swift-experimental-string-processing: An early experimental general-purpose pattern matching engine for Swift.
Avatar
omochimetaru 9/30/2021 5:54 AM
5:57 AM
うーんここにもなさそう?
Avatar
norio_nomura 9/30/2021 5:58 AM
なかった
5:59 AM
*OneOrMoreって書かれてて心配になる。
😲 1
Avatar
omochimetaru 9/30/2021 5:59 AM
5:59 AM
ZeroOrMore
Avatar
Appleのドキュメントに記載されている例を使ってAsyncStreamの挙動を調べていたのですが、(1)のループの後にfinishを呼ぶとonTerminationのコールバックが呼ばれてcancel扱いになるのですが、これってこういうものなのでしょうか? なんとなく「値の出力が全部終わってfinishしたらなぜかcancel処理が走った」みたいな印象を受けたのでどうなのかなあと思いまして😅 func hoge() async { let digits = AsyncStream(Int.self) { continuation in Task.detached { for digit in 0..<10 { // (1) continuation.yield(digit) } continuation.finish() continuation.onTermination = { @Sendable finished in if case .cancelled = finished { print("cancel") // 呼ばれる } } } } for await digit in digits { print(digit) } } https://developer.apple.com/documentation/swift/asyncstream (edited)
Avatar
多分なんですけど、finishを呼ぶ前にonTerminationを定義しておかないと
10:36 AM
AsyncSequenceが完了した後でonTerminationに登録される、ってなってて変になってる気がする (edited)
10:37 AM
この場合、onTerminationの発火はAsyncSequenceが解放された方をトリガーに発火していて、キャンセル扱いになってしまってるんじゃないでしょうか
Avatar
ありがとうございます!前に持ってきたらfinishedに変わりました!ただfinishedが出力されるタイミングが毎回変わるのがまだよくわかってないです… func hoge() async { let digits = AsyncStream(Int.self) { continuation in Task.detached { for digit in 0..<10 { continuation.yield(digit) } continuation.onTermination = { @Sendable finished in switch finished { case .finished: print("finished") // タイミングがバラバラ case .cancelled: print("cancel") @unknown default: break } } continuation.finish() } } for await digit in digits { print(digit) } } (edited)
Avatar
https://discord.com/channels/291054398077927425/291054454793306112/890879652363657227 この辺りで議論したんですが、yieldで渡した値がawaitの宣言側に渡されるのは非同期的なんですよね。一方でcontinuation.finishのコールは、awaitの宣言のない箇所なので、同期的になってるんじゃないかと。
10:59 AM
AsyncSequenceを他の言語のyield相当として使うことは出来ないので、非同期的な箇所と同期的な箇所の順番が保証されることも、同様に無いと考えています
Avatar
あーなるほど。その辺りの議論がきちんと理解できてませんでした💦 ありがとうございます🙇🏻‍♂️後片付けみたいな用途には使えないのか... (edited)
Avatar
"Swift Concurrency チートシート" の Case 20 ( MainActor )で final class UserViewController: UIViewController { private let state: UserViewState ... override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) state.loadUser() } } としてるの、ダメでは?これだと loadUser の非同期処理が終わるまで viewDidAppear を抜けられない・・・。 https://zenn.dev/koher/articles/swift-concurrency-cheatsheet#%F0%9F%92%BC-case-20-(mainactor)%3A-%E5%85%B1%E6%9C%89%E3%81%95%E3%82%8C%E3%81%9F%E7%8A%B6%E6%85%8B%E3%81%AE%E5%A4%89%E6%9B%B4%EF%BC%88%E3%83%A1%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89%E4%B8%8A%E3%81%A7%E3%81%AE%E5%87%A6%E7%90%86%EF%BC%89
Avatar
loadUserの実装次第では
3:53 AM
Taskを生成して非同期処理してるなら抜けれますね
Avatar
自分で書いたサンプルコード見たらそうなってました。混乱してた・・・。 func loadUser() { Task { do { user = try await fetchUser(for: userID) } catch { // エラーハンドリング } } }
4:00 AM
@MainActor で意図せず async であるべきメソッドが同期的に呼べてヤバいケースがあるんじゃないかと考えてたんだけど、 fetchUser@MainActor とは関係のない async 関数だから、ここで await が必須になって、 loadUserasync をつけなきゃとなった時点で気付くか。よかった。 (edited)
Avatar
そうですね、基本問題ないはず
👍 1
Avatar
@swift-main protocol P {} struct S: P {} func makeS() -> S { S() } let f1 = makeS as () -> P print("f1 ok") if let f2 = makeS as? () -> P { print("f2 ok") } else { print("f2 ng") }
Avatar
Avatar
omochimetaru
@swift-main protocol P {} struct S: P {} func makeS() -> S { S() } let f1 = makeS as () -> P print("f1 ok") if let f2 = makeS as? () -> P { print("f2 ok") } else { print("f2 ng") }
swiftNightly BOT 10/15/2021 2:22 PM
f1 ok f2 ngstderr:<stdin>:8:19: warning: runtime conversion from '() -> S' to '() -> P' is not supported; cast always fails if let f2 = makeS as? () -> P { ^ <stdin>:8:19: note: consider using 'as' coercion instead if let f2 = makeS as? () -> P { ^~~ as <stdin>:8:8: warning: value 'f2' was defined but never used; consider replacing with boolean test if let f2 = makeS as? () -> P { ~~~~^~~~~ ~~~ is
Avatar
as は通るけど as? は失敗する、という事があるらしい。
Avatar
Anyに一回キャストするといけません?
Avatar
@swift-main protocol P {} struct S: P {} func makeS() -> S { S() } let f1 = makeS as () -> P print("f1 ok") if let f2 = makeS as Any as? () -> P { print("f2 ok") } else { print("f2 ng") }
Avatar
Avatar
omochimetaru
@swift-main protocol P {} struct S: P {} func makeS() -> S { S() } let f1 = makeS as () -> P print("f1 ok") if let f2 = makeS as Any as? () -> P { print("f2 ok") } else { print("f2 ng") }
swiftNightly BOT 10/15/2021 2:24 PM
f1 ok f2 ngstderr:<stdin>:8:8: warning: value 'f2' was defined but never used; consider replacing with boolean test if let f2 = makeS as Any as? () -> P { ~~~~^~~~~ ~~~ is
Avatar
ダメだ
Avatar
こう?同じ結果になる
Avatar
動的キャスト強制すればなんか変わるかなと思ったんですけど
Avatar
Xcode13のSwift、 Swift パッケージに、 CodableConfiguration という新要素が勝手に追加されてる。 https://developer.apple.com/documentation/swift/keyeddecodingcontainer/3766918-decode
9:00 AM
swift-evolution飛ばして体験版(?)が出るやつ
Avatar
Just having a look at the documentation of CodableConfiguration. Maybe "the types are the documentation" is taken a little bit too far in this case? 😅
9:00 AM
これだw
Avatar
CodableConfigurationFoundation だからセーフか
Avatar
ググっても情報少なすぎて笑う
Avatar
Swift.KeyedDecodingContainer.func decode<T, C>(_: CodableConfiguration<T?, C>.Type, forKey key: KeyedDecodingContainer<K>.Key) throws -> CodableConfiguration<T?, C> where T : DecodableWithConfiguration, T : EncodableWithConfiguration, C : DecodingConfigurationProviding, C : EncodingConfigurationProviding, T.DecodingConfiguration == C.DecodingConfiguration, T.EncodingConfiguration == C.EncodingConfiguration
9:02 AM
いや、これは、protocol側に生えてるよな・・・?
9:02 AM
extensionでいける?
Avatar
Learn what the new CodableWithConfiguration type is and how you can use it to create better decoding and encoding code.
9:02 AM
解説記事だ
Avatar
KeyedDecodingContainerstruct だから、
9:05 AM
Foundation から extension で生やす分には
9:05 AM
Swift モジュールに影響はないのか。
Avatar
例によってオーバーロードのマジックで処理を差し込んでそう
9:06 AM
引数のインターフェースは同じだけどGenericsの型パラの数で優先度あげてそう
Avatar
このハック、公式で使われてるの見る度に「やってんな〜」って思う
Avatar
あ、これ引数の数同じなのか 普通 タイプを指定するところに、 CodableConfiguration に包んだタイプを指定する形か。ややこしー。
9:07 AM
機能としては便利なやつな気配がするので後で↑の解説をよく読んでみる。
Avatar
ちょっと前にフォーラムで
9:12 AM
Codableの困り募集スレがあったのは
9:12 AM
この機能リリースをぶちこむ時になるべく世のニーズにもすり合わせようとしたのかも
Avatar
omochimetaru 11/9/2021 2:08 PM
The core team is going through the backlog of proposed evolution proposals, and would like to put forward SE-0330: Conditionals in Collections for review by the community. The review begins now and runs through November 19th, 2021. The proposal is authored by @johnno1962. Reviews are an important part of the Swift evolution process. All revie...
2:09 PM
配列リテラルの途中で #if 書ける案
2:09 PM
#if より if 書きたいなと思った。
Avatar
Kishikawa Katsumi 11/9/2021 2:34 PM
The most notable use case for this is conditional inclusion of tests for the Swift version of XCTest though it is certain to have other applications in practice allowing data to be tailored to production/development environments, architecture or build configuration.
まあわかるけどどうかな。それ以外のユースケースあるかな。
Avatar
if書くのはResultBuilderで頑張ればそれっぽいの出来る
😯 1
Avatar
↓この辺りで話してたやつですね。 < ResultBuilder で頑張れば https://discord.com/channels/291054398077927425/375206337937801216/740039408903782452
Avatar
Kishikawa Katsumi 11/9/2021 2:59 PM
Dictionaryは確かにたまにある気がする。具体的なケース思い出せないけど
Avatar
Optional な値で、存在するときだけ ArrayDictionary に入れたいとか。
Avatar
Kishikawa Katsumi 11/9/2021 3:07 PM
あるような気がする。
3:08 PM
Process(シェルスクリプトの呼び出しとか)に渡すOptionをArrayで渡すときとかそんな感じかも。
3:10 PM
これはTypeScriptだけど const args = [ 'xcresulttool', 'get', '--path', this.bundlePath, '--format', 'json' ] if (reference) { args.push('--id') args.push(reference) } こういう感じだな。
Avatar
そういうやつですね。
Avatar
Kishikawa Katsumi 11/9/2021 3:15 PM
まあArrayなら + と三項演算子でそれっぽく書けるか。。。?
Avatar
omochimetaru 11/9/2021 4:07 PM
Optionalなときは .compact() で取り除いてる
Avatar
Kishikawa Katsumi 11/9/2021 4:10 PM
どっちが読みやすいかな
Avatar
Hello Swift Community, The review of SE-0326: Multi-statement closure parameter/result type inference has completed. Feedback was light but positive, and the core team has accepted this proposal. The core team recognizes that the language change has the slight possibility of requiring source changes, but that the benefits brought by this chang...
👀 1
3:35 PM
大物がacceptした、やったー
Avatar
おお、これって今まで一行クロージャにしかなかった型推論用の型パラの伝播が複数行クロージャにも対応するって感じですか?
Avatar
はい 複数行クロージャの型も中身のコードから推論可能になります
Avatar
これはすごい
Avatar
仕組みとしてはResultBuilderのために導入された型推論の進化を応用してる
Avatar
RxやCombineの書き心地がめちゃくちゃ改善しますね
Avatar
あれは結局複数の文から全体として一つの型を求めてるから。
Avatar
ELFも
Avatar
そうなんすよね guardが出てきて3文になった瞬間に型の明記が必要なのがだるかった
5:12 PM
まあそのへん全部async awaitに行けば解決するから適用領域はめっちゃ減りそうなタイミングだけどもw
Avatar
それは確かにw
Avatar
クソデカconcurrencyの着地が見えてきてまたSwiftの多様なアプデがいろいろ出てきそうだな
Avatar
もしかしてSE-0299によってprotocolをネームスペースとして使えるようになった? protocol P {} extension P { // static funcが書けるようになった static func foo() -> Int { 0 } /* インナータイプは作れないけど struct Inner {} */ } /* typealiasできるので実質可能? */ struct _P_Inner {} extension P { typealias Inner = _P_Inner } print(P.Inner())
Avatar
// static funcが書けるようになった
ここにちょっとテクニックが必要で、ダミーのPを何かしら用意しないと呼べないんですよね
Avatar
ほんまや
Avatar
struct InvalidP: P {} extension P where Self == InvalidP {} とすることで foo を呼べます
3:39 AM
それも P.foo() じゃなくて func f(_ p: P) に対して f(.foo()) という形になるので多少ややこしい
Avatar
ドット記法の場合だけか。じゃあネームスペースにはならんなあ
Avatar
yutailang0119 11/26/2021 3:59 AM
テクい
Avatar
extension Never: P {} extension P where Self == Never {} のほうが安全だということに気づいた
Avatar
propertyWrapperに空のinitがあるときだけは変数の型宣言が省略できる気がするんですけど、そういうもんでしたっけ。
Avatar
型宣言というか変数そのものをなくせる(から、連鎖的に型も消えて見える)という話かな?
Avatar
変数そのものを無くせる?
Avatar
@Bar var bar = 1 コレは通るんじゃないかしら
Avatar
ほんとだ、通った
6:48 AM
あ〜そういう事・・・?
Avatar
init() は引数なし、あるいはVoidなので
6:49 AM
そういうこと
Avatar
型宣言を代入文の右辺値からの推論で省略しているパターンの発展形で、 右辺値が空の式として推論できるから成立するみたいな・・・
Avatar
WrappedValueがGenericsなら、型の省略は許されなくなりそうだ
6:51 AM
規格には言及が無さそうなんだよね @propertyWrapper struct StringDictionary { var wrappedValue: [String: String] } @StringDictionary var d1. // infers Dictionary<String, String> @StringDictionary var d2: Dictionary // infers <String, String> ↑なんかいろいろ怪しいサンプルコードはある (edited)
Avatar
やばそうだなw
Avatar
そもそも「型が決まっててもinitが空なら右辺値を省略できる」なんて概念は他に無いし怪しいなあ
Avatar
普通にプロパティ宣言する場合は右辺値が空の式じゃなくても成立するから微妙にかみあってない感じがする
Avatar
var x: Int? は右辺値要らないけど・・・
Avatar
Avatar
Iceman
普通にプロパティ宣言する場合は右辺値が空の式じゃなくても成立するから微妙にかみあってない感じがする
あ〜いや、そうか
6:53 AM
そうすると @Bar var b が駄目なのが話と違うような気もしてきたな
Avatar
@swift-5.5.3 var a: Void
Avatar
Avatar
tarunon
@swift-5.5.3 var a: Void
no output
Avatar
事実上コレと一緒ってことかと
6:54 AM
Intは実はBarから推論されてるんだよね。で、空initはVoidを受け取るというPropertyWrapperの仕様が組み合わさった結果として
Avatar
@swift-5.5.3 var a: Void var b: Int
Avatar
Avatar
omochimetaru
@swift-5.5.3 var a: Void var b: Int
no output
Avatar
怪奇なコードがpopしてる
6:54 AM
あれ
6:55 AM
@swift-5.5.3 let a: Void
Avatar
Avatar
tarunon
@swift-5.5.3 let a: Void
no output
Avatar
これこれ
Avatar
@swift-5.5.3 func foo() { let a: Void let b: Int }
Avatar
Avatar
omochimetaru
@swift-5.5.3 func foo() { let a: Void let b: Int }
stderr:<stdin>:2:7: warning: immutable value 'a' was never used; consider replacing with '_' or removing it let a: Void ^ _ <stdin>:3:7: warning: immutable value 'b' was never used; consider replacing with '_' or removing it let b: Int ^ _
Avatar
?w
Avatar
あれれ〜〜〜〜〜
Avatar
@swift-5.4.3 @swift-5.3.3 @swift-5.2.5 func foo() { let a: Void let b: Int }
Avatar
Avatar
omochimetaru
@swift-5.4.3 @swift-5.3.3 @swift-5.2.5 func foo() { let a: Void let b: Int }
stderr:<stdin>:2:7: warning: immutable value 'a' was never used; consider replacing with '_' or removing it let a: Void ^ _ <stdin>:3:7: warning: immutable value 'b' was never used; consider replacing with '_' or removing it let b: Int ^ _
Avatar
Avatar
omochimetaru
@swift-5.4.3 @swift-5.3.3 @swift-5.2.5 func foo() { let a: Void let b: Int }
stderr:<stdin>:2:7: warning: immutable value 'a' was never used; consider replacing with '_' or removing it let a: Void ^ _ <stdin>:3:7: warning: immutable value 'b' was never used; consider replacing with '_' or removing it let b: Int ^ _
Avatar
Avatar
omochimetaru
@swift-5.4.3 @swift-5.3.3 @swift-5.2.5 func foo() { let a: Void let b: Int }
stderr:<stdin>:2:7: warning: immutable value 'a' was never used; consider replacing with '_' or removing it let a: Void ^ _ <stdin>:3:7: warning: immutable value 'b' was never used; consider replacing with '_' or removing it let b: Int ^ _
Avatar
右辺値って要らなかったのか
Avatar
使ってなければ宣言なくても怒られなくなった?
6:56 AM
@swift-5.5.3 let a: Void print(a)
Avatar
Avatar
tarunon
@swift-5.5.3 let a: Void print(a)
()
Avatar
@swift-5.5.3 func foo() { let a: Void let b: Int print(a) print(b) } (edited)
Avatar
Avatar
omochimetaru
@swift-5.5.3 func foo() { let a: Void let b: Int print(a) print(b) } (edited)
exit status: 1 with stderr:<stdin>:5:9: error: constant 'b' used before being initialized print(b) ^ <stdin>:3:7: note: constant defined here let b: Int ^
Avatar
よかった
Avatar
Voidは右辺値無しで初期化されるのね
6:57 AM
Intは未初期化使用が検出
6:57 AM
たしかにこの挙動が関係してる感じはあるな
Avatar
で、PropertyWrapperの無引数initはVoid扱いなんじゃない?っていう
Avatar
たしかに初期値で @Foo var a = () って書くのは変だな
6:58 AM
= () は何もない時にそう書いてる扱いがされるって感じか
7:00 AM
@propertyWrapper struct Bar { var wrappedValue: Int init(wrappedValue: Int = 0) { self.wrappedValue = wrappedValue } } struct S { @Bar var b }
7:00 AM
↑これもいけた、なるほどね
Avatar
ここで、IntがGenericsになると
Avatar
そうか、Optionalっぽいやつの場合にこれがあれば、 init(wrappedValue: T? = nil) がいけるのか
Avatar
型推論が通らなくなるから、完全省略が出来なくなるよ
Avatar
まあそのときでも @Bar<Int> var b これはいけるでしょ (edited)
Avatar
SwiftUIのEnvironmentは変数の型宣言を省略した解説をよく見ますね
7:11 AM
@Environment(\.colorScheme) var colorScheme みたいな
Avatar
この場合はpropertyWrapper側に明示的にイニシャライザを付けて呼び出しているから別の話でしたね
Avatar
onAppear の中はコンパイラ的にはMainActorっぽい(viewModel2のメソッド呼び出しにawaitがいらないので)けど明示的に @MainActor がついてないほうはコンテキストの引き継ぎが行われなくて、メインスレッド警告がでている?
7:47 AM
あ、このサンプルコードは-warn-concurrency ついてなかったから気づかなかったけどちゃんと警告でてた・・( Cannot use parameter 'self' with a non-sendable type 'ViewModel1' from concurrently-executed code ) Taskの中でawaitが起こるときにselfが明示的なactor contextを持っているかを確認してあればそのactor contextにスイッチするという感じなのかな
Avatar
そうか。 selfSendable じゃないからそもそも Task.init のクロージャに渡せないのか。
7:53 AM
Actor Context は func ごとに静的に決定されるもので、クロージャの場合、条件を満たせば( non-@Sendable または Task.init )引き継がれる?
7:54 AM
ある Actor Context から同期的に呼び出された関数の中は Actor Context を持たないという理解でいいのかな?
Avatar
現象を見る限りはそうだといえそうですね
8:01 AM
await の箇所ごとにコンパイラが見える範囲まで最寄りのActor Contextを探して、見つからなかったらそのままasync側のコンテキストに着地してそう
Avatar
async 側のコンテクストも存在しないのかな。結果的に async API の呼び出し先依存のスレッドで実行されるにしても、そこでさらにクロージャを書いたからといってそのコンテクストが引き継がれるとかはないと。
8:05 AM
actor Foo { func bar() -> Int { // Thread 2 & Foo の Actor Context 42 } } let foo = Foo() Task { // Thread 1 let x = await foo.bar() // Thread 2 (ただし Foo の Actor Context ではない) print(x) Task { // Thread 3 ( Foo の Actor Context は引き継がない) print(x) } } (edited)
Avatar
この場合はコンパイラがTaskのネストを探索してFooに到達できそうなのでコンテキストが引き継がれるかも?
8:12 AM
func global() async -> Int { return await withCheckedContinuation { c in DispatchQueue.global().async { c.resume(returning: 42) } } } @MainActor final class Foo { func start() { Task { let x = await global() print(x, Thread.isMainThread) // 42 true Task { let x = await global() print(x, Thread.isMainThread) // 42 true } } } } これは引き継がれてそうです
8:13 AM
(もちろんMainActorを外したらどちらもfalseになる)
Avatar
↑だと start が Main Actor の Actor Context を持つので、その中に書かれたクロージャには(条件を満たせば) Actor Context が引き継がれますね。
Avatar
あ、コードが修正されていた
Avatar
あ、すみません。 bar を呼び出すのに foo を書き忘れてたので・・・。
8:16 AM
await bar()await foo.bar() の修正と、 foo の宣言を最初に追加しました。
Avatar
actor Bar { func bar() -> Int { DispatchQueue.main.sync { 42 } } } final class Foo { func start() { let bar = Bar() Task { let x = await bar.bar() print(x, Thread.isMainThread) // 42 false Task { let x = await bar.bar() print(x, Thread.isMainThread) // 42 false } } } } これはfalseだ。async元のコンテキストを引き継いでるのではなく無のコンテキストにスイッチしてるのかな
Avatar
試してないけど多分↓になると思います。 @MainActor final class Bar { func bar() -> Int { 42 } } final class Foo { func start(bar: Bar) { Task { print(Thread.isMainThread) // 42 false let x = await bar.bar() print(x, Thread.isMainThread) // 42 true Task { print(Thread.isMainThread) // 42 false let x = await bar.bar() print(x, Thread.isMainThread) // 42 true } } } } (edited)
Avatar
Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context
8:18 AM
Bar がinit()できないですね・・
Avatar
外から与えるように修正しましたw
Avatar
実行したら全部falseでした
Avatar
えー、そうなのか?
8:20 AM
Fooactor になってないですよね?
8:20 AM
Task.init 自体がコンテクストを持つのかな?
Avatar
雑ですが
8:22 AM
呼び出し先のスレッドをそのまま使うことはなくて、コンテキストが未定義の場合は未定義用の無コンテキストを使うみたいですね
Avatar
import SwiftUI @MainActor struct ContentView: View { let bar = Bar() var body: some View { Text("Hello, world!") .onAppear { Foo().start(bar: bar) } } } @MainActor final class Bar { func bar() -> Int { print("bar", Thread.isMainThread) return 42 } } final class Foo { func start(bar: Bar) { Task { print("1", Thread.isMainThread, ObjectIdentifier(Thread.current)) let x = await bar.bar() print("2", Thread.isMainThread, ObjectIdentifier(Thread.current), x) Task { print("3", Thread.isMainThread, ObjectIdentifier(Thread.current)) let x = await bar.bar() print("4", Thread.isMainThread, ObjectIdentifier(Thread.current), x) Task.detached { print("5", Thread.isMainThread, ObjectIdentifier(Thread.current)) let x = await bar.bar() print("6", Thread.isMainThread, ObjectIdentifier(Thread.current), x) } } } } } 1 false ObjectIdentifier(0x0000600001348780) bar true 2 false ObjectIdentifier(0x0000600001319580) 42 3 false ObjectIdentifier(0x0000600001319580) bar true 4 false ObjectIdentifier(0x0000600001348780) 42 5 false ObjectIdentifier(0x0000600001319580) bar true 6 false ObjectIdentifier(0x0000600001348780) 42
8:29 AM
bar はたしかにメインスレッドで実行されているのと
8:30 AM
1 と 2 が異なるスレッドで実行されていることから、 Task は Actor Context を持つわけではなさそう。 Actor Context がない場合も await 先が結果を返したスレッドでそのまま実行されるわけではなく、また別のスレッドに投入される?
8:32 AM
↑も、 1 と 2 が同じスレッドで実行されることもあるけど(その方が多い)、それは節約されてるだけで、 1 と 2 が同じである保証はないと。
Avatar
無のコンテキストは複数あるみたいですが、シミュレーターだと2つで実機だともっとたくさんあるみたいな話をどこかで見ました
😇 1
Avatar
とりあえず、 Actor のメソッド中の最後の suspension point の後と、( Actor Context がないときの)呼び出し元の await の後は同期的だと思ってましたけど、それは違うと(どのスレッドで実行されるかわからない)。 Actor Context は静的に解決されると考えて、それ以外に想定外なところはなさそう。
👍 1
Avatar
anyプロポーザル読み終わった。良さそう。 心配なのはSwift6への自動マイグレーションだけだ。
11:32 AM
心配してもしょうがないしみんなベータ期間に頑張ってチャレンジして報告しよう、でしかない
Avatar
omochimetaru 2/18/2022 4:29 AM
@Icemanhttps://discord.com/channels/291054398077927425/430242233468452865/944056010585284649 で実験してるやつ 現場としては swift-nio で 2019年に発生してるんだけど https://github.com/apple/swift-nio/issues/1257 調べてたらこの既知の問題として整理されてた https://bugs.swift.org/browse/SR-14719
4:30 AM
@usableFromInline internal struct S { @usableFromInline internal var a: Int @inlinable internal init() { self.a = 0 } }
4:30 AM
a.swift:8:16: error: 'self' used before 'self.init' call or assignment to 'self' self.a = 0 ^ a.swift:9:5: error: 'self.init' isn't called on all paths before returning from initializer } ^
4:31 AM
struct S@frozen にするとビルドできるようになるんだけど
4:32 AM
「フィールドレイアウトが固定されていないのに init@inlinable だと、レイアウト変化後に、埋め込まれた古い init が正しく動作しないからおかしい」 というのが根底の話で
4:32 AM
https://bugs.swift.org/browse/SR-14783 そういう診断メッセージを出したいというチケットになってた
Avatar
await中の状態をassertしたいときに、ちょっとRunLoopが回ってほしいという用途でTask.yield()使ってみたらうまくいけたんですけれど、合法的な使い方なのか怪しい… async let result: () = viewModel.fetchRepository() await Task.yield() XCTAssertEqual(viewModel.repositories, []) stubApiClient.continue() // resumeで値を返却させる await result XCTAssertEqual(viewModel.repositories.count, 1)
Avatar
omochimetaru 2/19/2022 4:33 AM
考え方はあってると思いますけどお行儀は良く無いですね
4:34 AM
1回のyieldで期待したところまで処理が進むのかが、このコードからは保証されないですし。
4:36 AM
これ最初のfetchRepositoryはasync letではなく普通にawaitしたらダメなんですか?
Avatar
上のコードだとわかりにくいのですけれど、await中にだけ変化するパラメータをassertしたいというケースを考えていました
4:38 AM
たとえばプログレスを表示するみたいなパラメータがあって、await前と後はfalseなんですけれど、awaitの中でだけはtrueになるのをテストしたい、みたいなニーズになります
4:39 AM
yield使うのはコード読んだ人が混乱するしあまりよくなさそうですね…
Avatar
omochimetaru 2/19/2022 4:39 AM
あーfetch直後だけどawaitするまでの状態を確認したいってことですかね
Avatar
ですです
Avatar
omochimetaru 2/19/2022 4:40 AM
これ逆に、repositoriesに対するassertが、fetchの開始より先に評価されてしまう可能性がありそう (edited)
4:41 AM
stub.continueをするまで値が来てないことは保証できているのか
4:42 AM
Task.yieldがなくても
4:42 AM
狙ったテストシナリオが動くようにできそうに思うんですが
4:42 AM
これが無いと何の処理が止まってるんですか?
Avatar
StubのAPIリポジトリでその場で結果を返してしまうと、await中の状態に対するassertionが書けないと考えていて、疑似コードですけれどこういう感じで値を返すのを遅延させている感じです func fetchRepositories(userName: String) async throws -> [FooItem] {         // ここで値を返すとawait中の検証ができない return try await withCheckedThrowingContinuation { continuation in self.continuation = continuation } } func `continue`() { self.continuation.resume(returning: expectResult) }
4:47 AM
Task.yield() がない場合、await内の処理がまったく進まないので、上のコードだと支障ないんですけれど、内部で値を変えているものが未反映になる感じですね
4:48 AM
やりたいこととしてはこういう感じになります(こっちのほうがわかりやすかった) XCTAssertFalse(viewModel.showProgress) async let result: () = viewModel.fetchRepository() await Task.yield() XCTAssertTrue(viewModel.showProgress) // ここを検証したい stubApiClient.continue() // resumeで値を返却させる await result XCTAssertFalse(viewModel.showProgress)
Avatar
omochimetaru 2/19/2022 4:52 AM
うーんとつまり、 viewModel.fetchRepository の処理が動きはじめて viewModel.showPregress になったが、stubAPIClient.continue の呼び出しがまだされていない 時刻で、状態をassertしたいが、
4:53 AM
async let の後に Task.yield が無い場合、 viewModel.fetchRepository の処理がまだ開始していない時刻に assert が処理してしまうってことですよね?
Avatar
わかりにくくてすみません、その理解であっています
Avatar
omochimetaru 2/19/2022 4:54 AM
その場合は、「viewModel.fetchRepository の処理が動き始めるのを待機する」ロジックを明確に書くのが良いと思います。
4:55 AM
おそらく、 viewModel.fetchRepository の中で、 StubAPIClient.fetchRepository を呼ぶようになってますよね、なので、
4:55 AM
StubAPIClient に、 fetchRepository が呼ばれたら返ってくる await property を生やすのが良いんじゃないでしょうか
4:56 AM
つまりテストコードとしては
4:56 AM
XCTAssertFalse(viewModel.showProgress) async let result: () = viewModel.fetchRepository() await stubAPIClient.willFetchRepository XCTAssertTrue(viewModel.showProgress) stubApiClient.continue() await result XCTAssertFalse(viewModel.showProgress)
4:57 AM
こう書けるようにする。
Avatar
なるほど、こちらのほうが自明になりますね
Avatar
omochimetaru 2/19/2022 4:58 AM
はい。特定のタイミングで状態を検証したいという、シナリオの意図がコードで表現できるし、 Task.yield 1回だと期待した状態まで進行しない懸念も消せます (edited)
Avatar
withCString(:_) とか withUnsafeBytes(:_) をリストで扱いたいと思って、つまり let array: [String] = [...] array.with(each: String.withCString) { cStrings/*: [UnsafePointer<CChar>] */ in cFunctionReceivingCStringArray(cStrings) } こういうのがやりたくて、邪悪なものを生み出してしまった。 extension BidirectionalCollection { func with<U, R>( each mapFn: (Element) -> ((U) throws -> R) throws -> R, _ fn: ([U]) throws -> R ) rethrows -> R { try withoutActuallyEscaping(fn) { fn in try withoutActuallyEscaping(mapFn) { mapFn in var stash: [U] = [] stash.reserveCapacity(count) let closure = reversed().reduce({ try fn(stash) }) { closure, elem in { try mapFn(elem)() { val in stash.append(val) return try closure() } } } return try closure() } } } } (edited)
Avatar
@available(macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4, *) public protocol CodingKeyRepresentable となっているものの適合時に@available付けなくても何も言われず、下位バージョンだと以前のままArray扱いになってしまうみたいですね…
Avatar
そうなんですよね。結局Dictionaryの実装が動的にCodingKeyRepresentableを見に行くのでコンパイル時についてるだけじゃ意味ないっていう
Avatar
結構待ち望んでいたんですが、実際に使えるのは当分先ですね…
Avatar
omochimetaru 3/31/2022 6:14 AM
Hello Swift Community, The review of SE-0345 "if let shorthand for shadowing an existing optional variable" ended on March 22, 2022. The Core Team has decided to accept the proposal. Both the pitch and review threads for this proposal were very active, with well over 200 posts each. The Core Team would like to address a few of the discussion po...
6:14 AM
if let 採択
6:18 AM
commonly rejected list が覆されたから、じゃああれもやりたい、って話題が出そうだなー
Avatar
それ思った。
Avatar
omochimetaru 4/14/2022 5:34 PM
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
5:35 PM
Hello, @Alex_L and everyone in the Swift community, My name is Tongjie Wang, and currently I am a Master student in Computer Science at the University of Southern California. I am looking forward to participating in this year's GSoC event, and I am interested in the Bridging Swift Enums project. I have some experience in Swift and C++. For exa...
5:35 PM
Hello @Alex_L! My name is Roberto Rosmaninho, and I’m currently in my last year as an undergrad Computer Science student at the Universidade Federal de Minas Gerais in Brazil. I'm looking forward to participating in this year's GSoC event with Swift. I'm very interested in the project concerning bringing the Swift Error Handling Model to C++. ...
5:36 PM
GSoC2022のプロジェクトで、 Swiftの例外をC++にエクスポートする と Swiftのenum(with associated value)をC++にエクスポートする があってびっくり
5:37 PM
C++をSwiftにインポートするんじゃなくて、SwiftをC++にエクスポートする計画が進んでいた
Avatar
omochimetaru 5/21/2022 8:47 AM
Good morning everyone~! I'm happy to announce this year we'll be running 5 projects during Summer of Code! The accepted projects are: Improving Debug Output Of The Type Inference Algorithm, by Amrit Pankaur, mentored by @xedin Kafka Client Package for Swift, by Felix Schlegel, mentored by Franz Busch @FranzBusch Bootstrapping SwiftSynta...
8:49 AM
konladさんがGSoCの採用プロジェクト5つ書いてるけど C++系のやつが無い・・・
8:50 AM
スレッドの方には生徒さんがproposal提出したよって書きこんでるから、審査?で駄目だったんかな。 (edited)
Avatar
omochimetaru 6/3/2022 2:50 AM
Differentiable Swift is an experimental language feature that is currently being pitched in Differentiable programming for gradient-based machine learning . The original design grew out of the Swift for TensorFlow project at Google, and is now being maintained and advanced by the community. I'm a former member of the Swift for TensorFlow team, a...
2:51 AM
Swift for TensorFlowは終了しちゃったけど、 Swiftコンパイラに静的な自動微分を組み込むプロジェクトはコミュニティベースで生きていて、 Bardさんの会社ではその機能を使った物理シミュレーションをやっているらしい。 コントリビューションの呼びかけで今どんなissueがあるのかとか説明している。
Avatar
Swiftの自動微分って一部が main に取り込まれたんじゃなかったっけ?マニフェストが出ただけだっけ?
Avatar
Avatar
koher
Swiftの自動微分って一部が main に取り込まれたんじゃなかったっけ?マニフェストが出ただけだっけ?
omochimetaru 6/3/2022 3:14 AM
オプションと import _Differentiation で使える状態っぽい。 プロポーザルは下書きしか存在しないはず
3:17 AM
↑動いた
Avatar
これ、やるならいいけど、やらないなら無駄にコンパイラのコードが複雑化してそうですね・・・。
Avatar
omochimetaru 6/4/2022 7:26 AM
そうですね。 仕組み的には生成されたSILコードから二次的に微分関数を生成する感じなんで、設計上は分離できてそうですけど、 いろんな細かい都合で変更に対して面倒が生じたりはしてるでしょうね。
Avatar
https://discord.com/channels/291054398077927425/291054454793306112/777845365931376641 ↑このあたりのCOWの話って、2次元配列で起こる話だと勘違いしてたんですが、ただの1次元配列でも起こるんですね。さっき踏んで、しばらく悩んでました。
Avatar
そうですねぇ。1次元でも起きていて、2次元だと更に容易に大変な感じになるんですよね
9:00 AM
これレポートしたんでしたっけ(どなたかしてくださった気もする)
Avatar
何度か話題には上がってた気がしますがどうだったでしょうね。でも、今ひとつ再現条件がわからない。
9:01 AM
やばい。「更に容易に大変な感じになる」という表現がツボりました 😂
😂 1
Avatar
get/setの組で操作せずに _modify に出来ると回避できるんですよね
9:03 AM
後でレポートしておきます〜
t_kami 1
Avatar
1次元、複雑なコードでは再現したけど、単純なコードでは再現しませんでした。なにか条件がある 🥺
Avatar
@swift-5.6.3 import Foundation let arraySize = 1000000 let loopCount = 1000 class Values { var values = [Int](repeating: 0, count: arraySize) func foo1() { values[0] += values[0] } func foo2() { let v = values[0] values[0] += v } } func measure(_ body: () -> Void) { let time1 = Date.timeIntervalSinceReferenceDate for _ in 0 ..< loopCount { body() } let time2 = Date.timeIntervalSinceReferenceDate print(time2 - time1) } let values = Values() measure { values.foo1() } measure { values.foo2() }
Avatar
Avatar
hironytic
@swift-5.6.3 import Foundation let arraySize = 1000000 let loopCount = 1000 class Values { var values = [Int](repeating: 0, count: arraySize) func foo1() { values[0] += values[0] } func foo2() { let v = values[0] values[0] += v } } func measure(_ body: () -> Void) { let time1 = Date.timeIntervalSinceReferenceDate for _ in 0 ..< loopCount { body() } let time2 = Date.timeIntervalSinceReferenceDate print(time2 - time1) } let values = Values() measure { values.foo1() } measure { values.foo2() }
0.9675040245056152 0.00011301040649414062
Avatar
起こせた!
9:22 AM
ちなみにclassに包まなければ起こりませんでした。あと、 Values をstructにしても起こりません。
Avatar
要素のためのretainとvalues自体のretainの並びがあると、どういうわけかhoistingを邪魔しちゃうのかなぁ
Avatar
values自体のretainというのは、クラスのインスタンスを握っていることを指していますか?
Avatar
あ、誤読してました。Arrayの要素がクラスかと思ってたけど、Arrayをクラスで包んでるんですね
t_desudesu 1
9:55 AM
なにもわからない🙃
😇 1
Avatar
Describe the bug It looks like some release hoisting optimization opportunities are missed even in a simple case. To Reproduce Steps to reproduce the behavior: func measure(_ body: () -&gt; Voi...
🙇‍♂️ 1
Avatar
@escaping な non-@Sendable クロージャは actor context を引き継ぐという理解なんですけど、↓の foo が返すクロージャは常にメインスレッドで実行される( true が表示される)ということでしょうか? @MainActor func foo() -> () -> Void { // main actor context { // actor context を引き継ぐ print(Thread.isMainThread) } } この foo で返されたクロージャを Task.detached から呼び出すと false が表示されたんですが、これは僕の仕様理解が間違っているか、バグか、未実装か、実行方法に問題がある(何かオプションを付けないといけないなど)か、どう考えれば良いでしょうか? (edited)
3:34 AM
そもそも async でないからメインスレッドで同期実行というのが破綻してるか。
3:39 AM
前に DispatchQueue.global().async みたいな API に渡すケースは今は穴が空いているけど、将来的にはそういう穴は塞がれる( DispatchQueue.global().async のような API が廃止される?)みたいな話をしたと思うんですが、↑のようなケースはどうなるんでしょう? foo がコンパイルエラー? func foo() -> @MainActor () -> Void じゃないといけない?
Avatar
これmainactorが保証されてるのはクロージャを作るところまでで
4:24 AM
作られたクロージャがどこで実行されるかは保証されてないのでは
Avatar
Task.detachedのクロージャ内はcontextを引き継がないので、途切れて引き継がれないのではないでしょうか?(actorに分離されていないsyncコードと同じ扱いになる?)
DispatchQueue.global().async みたいな API に渡すケースは今は穴が空いているけど、将来的にはそういう穴は塞がれる
下記のコードはエラーになりましたね Xcode14.0 beta2 func bar() {   // StrictConcurrencyChecking: Minimal DispatchQueue.global().async { await foo()() // ❌ Cannot pass function of type '() async -> Void' to parameter expecting synchronous function type }   // StrictConcurrencyChecking: Complete DispatchQueue.global().async { await foo()() // ❌ Cannot pass function of type '@Sendable () async -> Void' to parameter expecting synchronous function type } }
(edited)
Avatar
mainactorが保証されてるのはクロージャを作るところまで
Task.detachedのクロージャ内はcontextを引き継がないので、途切れて引き継がれないのではない
そうすると、 @escaping クロージャの actor context 引き継ぎとは、何(誰)の context を引き継ぐのでしょうか?
5:43 AM
A closure that is not @Sendable cannot escape the concurrency domain in which it was formed.
https://github.com/apple/swift-evolution/blob/main/proposals/0306-actors.md そもそも escape できない?
5:44 AM
そうすると、 @MainActor で escape できるのがおかしい? @swift-5.6.3 func run(_ operation: () -> Void) { operation() } func runEscaping(_ operation: @escaping () -> Void) { operation() } actor Foo { var count: Int = 0 func countUp() { run { count += 1 } runEscaping { [weak self] in guard let self = self else { return } print(self.count) } } }
Avatar
Avatar
koher
そうすると、 @MainActor で escape できるのがおかしい? @swift-5.6.3 func run(_ operation: () -> Void) { operation() } func runEscaping(_ operation: @escaping () -> Void) { operation() } actor Foo { var count: Int = 0 func countUp() { run { count += 1 } runEscaping { [weak self] in guard let self = self else { return } print(self.count) } } }
exit status: 1 with stderr:<stdin>:18:24: error: actor-isolated property 'count' can not be referenced from a non-isolated context print(self.count) ^ <stdin>:10:9: note: property declared here var count: Int = 0 ^
Avatar
@swift-5.6.3 func run(_ operation: () -> Void) { operation() } func runEscaping(_ operation: @escaping () -> Void) { operation() } @MainActor final class Bar { var count: Int = 0 func countUp() { run { count += 1 } runEscaping { [weak self] in guard let self = self else { return } print(self.count) } } }
Avatar
Avatar
koher
@swift-5.6.3 func run(_ operation: () -> Void) { operation() } func runEscaping(_ operation: @escaping () -> Void) { operation() } @MainActor final class Bar { var count: Int = 0 func countUp() { run { count += 1 } runEscaping { [weak self] in guard let self = self else { return } print(self.count) } } }
no output
Avatar
そうすると、 @escaping クロージャの actor context 引き継ぎとは、何(誰)の context を引き継ぐのでしょうか?
上記の場合はMainActor(呼び出し側)のcontext を引き継いでいるので問題ない(domainをescapeしていない)のではないでしょうか?
Therefore, such a closure will be actor-isolated if it is formed within an actor-isolated context.
ただし、途中でdetachedが入るとそこでcontextの引き継ぎが途切れてMainActor上ではなくなるかなあと。 func runEscaping(_ operation: @escaping () -> Void) { Task.detached { operation() } } うろ覚えなんですが、Concurrencyの機能が使われていない場合、Sendableを削除してませんでしたっけ?なのでMainActorの方のcountはエラーにならない? // Strip off Sendable and (possibly) the global actor. https://github.com/apple/swift/blob/5c05da0a1d8dad5bd945918ce9e24603091b88c5/lib/Sema/TypeCheckConcurrency.cpp#L4546 asyncとSendableを使っている場合はConcurrencyを使っているとみなされる。 // Async and @Sendable closures use concurrency features. https://github.com/apple/swift/blob/5c05da0a1d8dad5bd945918ce9e24603091b88c5/lib/Sema/TypeCheckConcurrency.cpp#L4001 actorの内部にある場合もConcurrencyを使っているとみなされる。 // If we're in an actor, we're using concurrency features. https://github.com/apple/swift/blob/5c05da0a1d8dad5bd945918ce9e24603091b88c5/lib/Sema/TypeCheckConcurrency.cpp#L4027 @Sendable付けると@MainActor Barの方もエラーになるんですよねえ func runEscaping(_ operation: @Sendable @escaping () -> Void) { operation() }
(edited)
Avatar
Avatar
shiz
そうすると、 @escaping クロージャの actor context 引き継ぎとは、何(誰)の context を引き継ぐのでしょうか?
上記の場合はMainActor(呼び出し側)のcontext を引き継いでいるので問題ない(domainをescapeしていない)のではないでしょうか?
Therefore, such a closure will be actor-isolated if it is formed within an actor-isolated context.
ただし、途中でdetachedが入るとそこでcontextの引き継ぎが途切れてMainActor上ではなくなるかなあと。 func runEscaping(_ operation: @escaping () -> Void) { Task.detached { operation() } } うろ覚えなんですが、Concurrencyの機能が使われていない場合、Sendableを削除してませんでしたっけ?なのでMainActorの方のcountはエラーにならない? // Strip off Sendable and (possibly) the global actor. https://github.com/apple/swift/blob/5c05da0a1d8dad5bd945918ce9e24603091b88c5/lib/Sema/TypeCheckConcurrency.cpp#L4546 asyncとSendableを使っている場合はConcurrencyを使っているとみなされる。 // Async and @Sendable closures use concurrency features. https://github.com/apple/swift/blob/5c05da0a1d8dad5bd945918ce9e24603091b88c5/lib/Sema/TypeCheckConcurrency.cpp#L4001 actorの内部にある場合もConcurrencyを使っているとみなされる。 // If we're in an actor, we're using concurrency features. https://github.com/apple/swift/blob/5c05da0a1d8dad5bd945918ce9e24603091b88c5/lib/Sema/TypeCheckConcurrency.cpp#L4027 @Sendable付けると@MainActor Barの方もエラーになるんですよねえ func runEscaping(_ operation: @Sendable @escaping () -> Void) { operation() }
(edited)
ただし、途中でdetachedが入るとそこでcontextの引き継ぎが途切れてMainActor上ではなくなるかなあと。
これは、利用側からは runEscaping がどのように実装されているかわからないと思うんですが、 runEscaping がブラックボックスだと考えたときに @MainActor func foo() { // main actor context runEscaping { // ここに main actor context が引き継がれることが保証されていないと何も信じられない } } となりませんか?だから、 actor context の引き継ぎはコールスタックがどのようになっていてもクロージャの宣言箇所によって決められる(たとえ Task.detached を挟もうが、 main actor context を引き継ぐ箇所で宣言されたクロージャは実行時に再度 main queue に投入される)のだと思っていました。 ただ、普通の actor だとコンパイルエラーになっていることから、 MainActor (というか global actor ?)の挙動がおかしいんでしょうか?
(edited)
Avatar
僕の認識ですと // ここに main actor context が引き継がれることが保証されていないと何も信じられない そこはmain actor contextだと思っていて、いやClosure内部なので保証されていない気がする runEscapingfunc runEscaping(_ operation: @escaping () -> Void) { Task.detached { // actorのcontextは引き継がないのでmain actor contextではない operation() } } とコンパイラが判定していると思ってました。 あと、今再確認したら↓はSwift5.7だとエラーになりますね(昨日はなんかキャッシュが残っていたようです) func run(_ operation: () -> Void) { operation() } func runEscaping(_ operation: @escaping () -> Void) { operation() } @MainActor final class Bar { var count: Int = 0 func countUp() { run { count += 1 } runEscaping { [weak self] in guard let self = self else { return } print(self.count) // :x: Property 'count' isolated to global actor 'MainActor' can not be referenced from a non-isolated synchronous context } } } (edited)
Avatar
Avatar
koher
@escaping な non-@Sendable クロージャは actor context を引き継ぐという理解なんですけど、↓の foo が返すクロージャは常にメインスレッドで実行される( true が表示される)ということでしょうか? @MainActor func foo() -> () -> Void { // main actor context { // actor context を引き継ぐ print(Thread.isMainThread) } } この foo で返されたクロージャを Task.detached から呼び出すと false が表示されたんですが、これは僕の仕様理解が間違っているか、バグか、未実装か、実行方法に問題がある(何かオプションを付けないといけないなど)か、どう考えれば良いでしょうか? (edited)
non-Sendableな値(ここではクロージャ)は平行に触ることが出来ないので、Task.detachedでクロージャをコピーすることが違反だと思います。
t_naruhodo 1
3:09 AM
@swift-5.7.3 -warn-concurrency -Xfrontend -parse-as-library import Foundation @MainActor func foo() -> () -> Void { { print(Thread.isMainThread) } } @main struct Main { @MainActor static func main() async { let f = foo() let t = Task.detached { f() } _ = await t.value } } (edited)
Avatar
Avatar
Yuta Saito
@swift-5.7.3 -warn-concurrency -Xfrontend -parse-as-library import Foundation @MainActor func foo() -> () -> Void { { print(Thread.isMainThread) } } @main struct Main { @MainActor static func main() async { let f = foo() let t = Task.detached { f() } _ = await t.value } } (edited)
falsestderr:<stdin>:16:7: warning: capture of 'f' with non-sendable type '() -> Void' in a `@Sendable` closure f() ^ <stdin>:16:7: note: a function type must be marked '@Sendable' to conform to 'Sendable' f() ^ (edited)
Avatar
5.7では-warn-concurrencyでワーニングが出ますね
3:13 AM
違反しないコードを書いている内は、non-Sendableクロージャを作ったactor contextで実行されることが保証されると思います。 (edited)
Avatar
そうか、たしかにそっちが違反ですね! > Task.detachedでクロージャをコピーすることが違反 (edited)
Avatar
いやClosure内部なので保証されていない気がする
やっぱり引き継がれないですねー func runEscaping(_ operation: @escaping () -> Void) { Task.detached { // Taskも同じ結果 print("3", Thread.isMainThread) // false operation() } } @MainActor final class Bar { func countUp() { print("1", Thread.isMainThread) // true runEscaping { print("2", Thread.isMainThread) // false } } } ↓はWWDCのセッションで言われていた通り、nonisolatedなsync関数は呼び出し側のcontextに依る(そもそもescapingしないのか) func runEscaping(_ operation: @escaping () -> Void) { print("3", Thread.isMainThread) // true operation() } @MainActor final class Bar { func countUp() { print("1", Thread.isMainThread) // true runEscaping { print("2", Thread.isMainThread) // true } } }
(edited)
Avatar
(すいませんどうしても気になってしまいw) func runEscaping(_ operation: @escaping () -> Void) { Task.detached { print("3", Thread.isMainThread) // false operation() } } @MainActor final class Bar { func countUp() { print("1", Thread.isMainThread) // true runEscaping { print("2", Thread.isMainThread) // false Task { // ここはmain actor contextが引き継がれる print("4", Thread.isMainThread) // true👀 } } } } asyncを足すとtrueになる(MainActorにhopできる) func runEscaping(operation: @escaping () async -> Void) { Task.detached { print("3", Thread.isMainThread) // false await operation() } } @MainActor final class Bar { func countUp() { runEscaping { print("2", Thread.isMainThread) // trueになる👀 } } } (edited)
Avatar
Xcode 14でasyncなとこでNSRange渡すとめっちゃ嫌味言われるんだけど、_NSRangeがSendable対応してないのって単にApple側のミス? (edited)
Avatar
もしかして対象のNSStringへの参照を掴んでいたりしたらSendableにならないかもしれんと思ったけど、OSS Foundationを見る限りはただのタプルなので、Sendableにしたらいいですね public struct _NSRange { public var location: Int public var length: Int public init() { location = 0 length = 0 } public init(location: Int, length: Int) { self.location = location self.length = length } } https://github.com/apple/swift-corelibs-foundation/blob/ee856f110177289af602c4040a996507f7d1b3ce/Sources/Foundation/NSRange.swift
The Foundation Project, providing core utilities, internationalization, and OS independence - swift-corelibs-foundation/NSRange.swift at ee856f110177289af602c4040a996507f7d1b3ce · apple/swift-corel...
Avatar
勝手にSendableにするとそれはそれで嫌がられるのよね。まぁAppleにフィードバック出すか。
Avatar
omochimetaru 6/29/2022 1:29 PM
extension _NSRange: @unchecked Sendable {} はどうですか?
Avatar
確かに@uncheckedつけると黙らせられるな。なんか気持ち悪いけど、まぁ今回のケースは実際安全なことがわかってるからとりあえずはこれでもいいか。ありがとう。
Avatar
omochimetaru 6/29/2022 1:53 PM
警告文の内容は「Sendableへの準拠はその型と同じファイルの中で定義すべきで、後付するなら @unchecked を使いなさい」って感じですけど、 この理由はおそらく、別のファイルで Sendable 準拠すると、定義元のライブラリがソースアップデートする場合には(本当にスレッドアンセーフなデグレ改修がされて)ソース互換性が壊れる可能性があるし、バイナリアップデートする場合には嘘のSendableになってしまうからですね。 @unchecked はそのように後に壊れる可能性がある事を許容する宣言でもある。 まさに「実際安全な事がわかってる間」にしのぐための言語仕様です。 (edited)
Avatar
Sendable、基本的に実装で平行安全を保証する場合 @uncheckedをつけることになるのでその場しのぎじゃなくても普通に使いませんか?
Avatar
omochimetaru 6/29/2022 2:09 PM
class の実装で内部は DispatchQueue とかで自力で安全を保障する場合はそうですね。
2:10 PM
その場合は後付conformじゃなくて型定義するところで準拠すると思うので今は無視してました。NSRangeの後付の話だったので。
Avatar
確かにextensionでの後付と宣言部分についてるのは大きく意味が違いますね
Avatar
@unchecked が気持ち悪いとか実装で保証してることとの区別がつかなくて嫌なときは @preconcurrency import struct Foundation.NSRange と書くのもいいかもしれない
2:23 PM
だめだ意味ないなこれ
2:23 PM
@swift-5.6.3 -warn-concurrencyimport Foundation @preconcurrency import struct Foundation.NSRange func f() { let range = NSRange.init() let string = NSString.init() Task { print(range, string) } }
Avatar
Avatar
Iceman
@swift-5.6.3 -warn-concurrencyimport Foundation @preconcurrency import struct Foundation.NSRange func f() { let range = NSRange.init() let string = NSString.init() Task { print(range, string) } }
stderr:<stdin>:8:15: warning: capture of 'range' with non-sendable type 'NSRange' (aka '_NSRange') in a `@Sendable` closure print(range, string) ^ Foundation._NSRange:1:15: note: struct '_NSRange' does not conform to the 'Sendable' protocol public struct _NSRange { ^ <stdin>:1:1: remark: add '@preconcurrency' to suppress 'Sendable'-related warnings from module 'Foundation' import Foundation ^ @preconcurrency <stdin>:8:22: warning: capture of 'string' with non-sendable type 'NSString' in a `@Sendable` closure print(range, string) ^ Foundation.NSString:1:12: note: class 'NSString' does not conform to the 'Sendable' protocol open class NSString : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSCoding { ^ <stdin>:2:17: remark: '@preconcurrency' attribute on module 'Foundation' is unused @preconcurrency import struct Foundation.NSRange ~~~~~~~~~~~~~~~~^
Avatar
@swift-5.6.3 -warn-concurrency@preconcurrency import struct Foundation.NSRange import Foundation func f() { let range = NSRange.init() let string = NSString.init() Task { print(range, string) } }
Avatar
Avatar
Iceman
@swift-5.6.3 -warn-concurrency@preconcurrency import struct Foundation.NSRange import Foundation func f() { let range = NSRange.init() let string = NSString.init() Task { print(range, string) } }
no output
Avatar
先に出てきた方に全部吸われちゃう (edited)
Avatar
Avatar
1024jp
勝手にSendableにするとそれはそれで嫌がられるのよね。まぁAppleにフィードバック出すか。
一応出しておいた FB10502989。
👌 1
Avatar
Avatar
1024jp
一応出しておいた FB10502989。
Xcode 14.0 beta 3でNSRangeにSendable追加された。similar reportsはless than 10だった。
Avatar
omochimetaru 7/8/2022 4:31 AM
おお 1件だったかも
Avatar
本当に1件しかないときはsimilar reportsはnoneになるから2件はあったはず。
Avatar
omochimetaru 7/8/2022 7:44 AM
ほほ〜
Avatar
@rethrows って、いつ正式に Swift に入ったんですっけ? @rethrows protocol AsyncSequence https://developer.apple.com/documentation/Swift/AsyncSequence ↓にも追加されてなさそうだし、 https://docs.swift.org/swift-book/ReferenceManual/Attributes.htmlAsyncSequence の Proposal にも書かれてなさそう。 https://github.com/apple/swift-evolution/blob/main/proposals/0298-asyncsequence.md
Avatar
omochimetaru 7/25/2022 2:41 AM
まだ話し合いだと思ってた。
2:42 AM
ResultBuilderの件があるから
2:42 AM
Xcode Betaに搭載されているコンパイラは
2:42 AM
未認証仕様を実装していることがあるのでそういう系じゃないかしら
2:44 AM
You have a generic effect in that where clause. It is saying that any Collection is creatable as a Sequence when the generic effect of the throwing is "nothrow". Granted that is a bit of an extreme case of interpretation of how the generics system works (but is somewhat true today with other conditional constraints). One of the key reasons why ...
2:44 AM
最新スレッドは多分これ?
Avatar
そういう場合って大抵 @_ じゃない? _ なくてびっくりした。
Avatar
omochimetaru 7/25/2022 2:50 AM
ピッチの仕様ではrequirementsにrethrowsって書くけどこれはprotocolに @rethrows が付くのか
2:51 AM
すでに rethrows キーワードは存在してるからそれで _ が無いんだろうか?
Avatar
(当たり前だけど) AsyncSequenceProtocol にも @rethrows 付いてるな。 https://developer.apple.com/documentation/swift/asynciteratorprotocol
Avatar
Avatar
omochimetaru
ピッチの仕様ではrequirementsにrethrowsって書くけどこれはprotocolに @rethrows が付くのか
@rethrowsrethrows は直接的にキーワードとして結びつくのかな? @SendableSendable みたいな意味合いでってこと? @Sendable は Proposal 通ってるしなぁ。 Marker Protocol と @ の関係が先送りされただけで。
Avatar
omochimetaru 7/25/2022 2:53 AM
そもそもどういう意味なのかよくわからないのでなんとも。
Avatar
あ、リプライ先間違えた。↓こっち。
すでに rethrows キーワードは存在してるからそれで _ が無いんだろうか?
(edited)
Avatar
omochimetaru 7/25/2022 2:54 AM
ピッチでは func next() rethrows によって機能するらしいけど
Avatar
@rethrows が何をやりたいのかはわかるにしても、どう働く仕様なのか何の資料もなくてわからない・・・。
Avatar
omochimetaru 7/25/2022 2:55 AM
↑のreferenceでどのメンバが @rethrows の影響をうけてどう変化するのかがわからん
2:56 AM
たいていこういうのはWWDCに動画があるんだけどなあ
Avatar
まだ AsyncIteratorProtocol の方は唯一の throws を持つメソッドがあるからわからんでもないけど、 AsyncSequence はさらに謎じゃない?
Avatar
ピッチ内での Rethrows protocol って表現されてるプロトコルに @rethrows が付いてそう
2:58 AM
rethrows付きのprotocol requirementが書けるのはrethrows protocol内だけで、コンパイラはrethrows protocolに対するコンフォーマンスにだけthrows付きか否かを記録するだけで済む
Avatar
omochimetaru 7/25/2022 2:59 AM
@available(SwiftStdlib 5.1, *) @rethrows public protocol AsyncSequence { /// The type of asynchronous iterator that produces elements of this /// asynchronous sequence. associatedtype AsyncIterator: AsyncIteratorProtocol where AsyncIterator.Element == Element /// The type of element produced by this asynchronous sequence. associatedtype Element /// Creates the asynchronous iterator that produces elements of this /// asynchronous sequence. /// /// - Returns: An instance of the `AsyncIterator` type used to produce /// elements of the asynchronous sequence. __consuming func makeAsyncIterator() -> AsyncIterator }
3:00 AM
↑これは AsyncIterator も @rethrows だから、throws性が伝搬するって決まるの?
Avatar
The definition of a rethrows protocol is transitive: if any generic requirement within the definition of the protocol (e.g., via an inherited protocol or a requirement on an associated type) is a rethrows protocol, then at protocol is also a rethrows protocol.
たぶんここのtransitive性が明示的になってるんだと
Avatar
omochimetaru 7/25/2022 3:00 AM
@available(SwiftStdlib 5.1, *) @rethrows public protocol AsyncIteratorProtocol { associatedtype Element /// Asynchronously advances to the next element and returns it, or ends the /// sequence if there is no next element. /// /// - Returns: The next element, if it exists, or `nil` to signal the end of /// the sequence. mutating func next() async throws -> Element? } ↑さらに、rethrowsじゃなくてthrowsって書いてあるんだけど・・・ (edited)
t_kusa 1
Avatar
そうなんよね。
Avatar
だめじゃん…
Avatar
omochimetaru 7/25/2022 3:01 AM
「requirementsに書いてあるrethrows」なら、通常はrethrowsが書けないところに書いてある事によって特別な意味があるとみなすのはわかるんだけど
3:02 AM
@rethrows protocol における requirements に書かれた throws に影響があるとしたら
Avatar
好意的に解釈すると、 AsyncIteratorProtocolthrows を持つ唯一の required なメソッドを持つからそれに @rethrows が働いていると考えられるけど、
3:02 AM
AsyncSequence への伝播が謎。
Avatar
omochimetaru 7/25/2022 3:02 AM
逆に 常に throws な requirements が定義できなくなってしまって変だ
Avatar
Avatar
koher
AsyncSequence への伝播が謎。
omochimetaru 7/25/2022 3:02 AM
好意的に解釈すると伝搬するとしかいえなそう
Avatar
Avatar
omochimetaru
逆に 常に throws な requirements が定義できなくなってしまって変だ
norethrows とかで抑制するとか?
Avatar
omochimetaru 7/25/2022 3:03 AM
とりあえず実験してみたらいいのかな
Avatar
Avatar
koher
norethrows とかで抑制するとか?
omochimetaru 7/25/2022 3:03 AM
難しいなw たしかに問題は回避できるけど。 (edited)
Avatar
もしかすると @rethrows 付与されてるだけで解釈されてなくて、 AsyncSequenceAsyncIteratorProtocol 以外では働かない可能性ありそう。
Avatar
omochimetaru 7/25/2022 3:04 AM
とりあえず for try await infor await in にできるだけみたいな。
Avatar
@swift-5.7.3 @rethrows protocol RethrowsIterator { func next() throws -> Int? } struct NonfailableIter: RethrowsIterator { func next() -> Int? { return 1 } } func callNextRethrows<T: RethrowsIterator>(_ iter: inout T) async throws -> Int? { try iter.next() }
Avatar
Avatar
Yuta Saito
@swift-5.7.3 @rethrows protocol RethrowsIterator { func next() throws -> Int? } struct NonfailableIter: RethrowsIterator { func next() -> Int? { return 1 } } func callNextRethrows<T: RethrowsIterator>(_ iter: inout T) async throws -> Int? { try iter.next() }
no output
Avatar
@swift-5.7.3 protocol RethrowsIterator { func next() throws -> Int? } struct NonfailableIter: RethrowsIterator { func next() -> Int? { return 1 } } func callNextRethrows<T: RethrowsIterator>(_ iter: inout T) async throws -> Int? { try iter.next() }
Avatar
Avatar
koher
@swift-5.7.3 protocol RethrowsIterator { func next() throws -> Int? } struct NonfailableIter: RethrowsIterator { func next() -> Int? { return 1 } } func callNextRethrows<T: RethrowsIterator>(_ iter: inout T) async throws -> Int? { try iter.next() }
no output
Avatar
これだと @rethrows 関係ない気が。
Avatar
むずかしい…
3:09 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
@swift-5.7.3 @rethrows protocol RethrowsIterator { func next() throws -> Int? } struct NonfailableIter: RethrowsIterator { func next() -> Int? { return 1 } } struct FailableIter: RethrowsIterator { func next() throws -> Int? { return 1 } } func callNextRethrows<T: RethrowsIterator>(_ iter: inout T) rethrows -> Int? { try iter.next() } var it = NonfailableIter() _ = callNextRethrows(&it) var it2 = FailableIter() _ = try callNextRethrows(&it2) (edited)
Avatar
Avatar
Iceman
@swift-5.7.3 @rethrows protocol RethrowsIterator { func next() throws -> Int? } struct NonfailableIter: RethrowsIterator { func next() -> Int? { return 1 } } struct FailableIter: RethrowsIterator { func next() throws -> Int? { return 1 } } func callNextRethrows<T: RethrowsIterator>(_ iter: inout T) rethrows -> Int? { try iter.next() } var it = NonfailableIter() _ = callNextRethrows(&it) var it2 = FailableIter() _ = try callNextRethrows(&it2) (edited)
no output (edited)
Avatar
便利そうな機能だ
Avatar
あ、そういうことか。
Avatar
いままでこれをやるためにはResultとかでエラー型をコンフォーマンスに焼いておく必要があったけど、自然にできるようになるのか
Avatar
omochimetaru 7/25/2022 3:16 AM
エラー型をパラメータにして Result<T, Never> にするのと同じことが throws に対してできる
Avatar
@swift-5.7.3 protocol RethrowsIterator { associatedtype Failure: Error func next() -> Result<Int?, Failure> } struct NonfailableIter: RethrowsIterator { func next() -> Result<Int?, Never> { return .success(1) } } struct FailableIter: RethrowsIterator { func next() -> Result<Int?, Error> { return .success(1) } } func callNextRethrows<T: RethrowsIterator>(_ iter: inout T) -> Result<Int?, T.Failure> { iter.next() } var it = NonfailableIter() let _: Result<Int?, Never> = callNextRethrows(&it) var it2 = FailableIter() _ = try callNextRethrows(&it2).get() (edited)
Avatar
Avatar
Yuta Saito
@swift-5.7.3 protocol RethrowsIterator { associatedtype Failure: Error func next() -> Result<Int?, Failure> } struct NonfailableIter: RethrowsIterator { func next() -> Result<Int?, Never> { return .success(1) } } struct FailableIter: RethrowsIterator { func next() -> Result<Int?, Error> { return .success(1) } } func callNextRethrows<T: RethrowsIterator>(_ iter: inout T) -> Result<Int?, T.Failure> { iter.next() } var it = NonfailableIter() let _: Result<Int?, Never> = callNextRethrows(&it) var it2 = FailableIter() _ = try callNextRethrows(&it2).get() (edited)
no output (edited)
Avatar
こうだった
Avatar
omochimetaru 7/25/2022 3:19 AM
Never な Result の nothrow get() が標準にあったら話がわかりやすかった。
Avatar
Task.valueはその辺丁寧なんだけどなぁ
Avatar
inout とか除いて単純にするとこうか。 @swift-5.7.3 @rethrows protocol P { func foo() throws } struct S1: P { func foo() { print("S1") } } struct S2: P { func foo() throws { print("S2") } } func callFoo<T: P>(of p: T) rethrows { try p.foo() } callFoo(of: S1()) do { try callFoo(of: S2()) } catch { print(error) }
Avatar
Avatar
koher
inout とか除いて単純にするとこうか。 @swift-5.7.3 @rethrows protocol P { func foo() throws } struct S1: P { func foo() { print("S1") } } struct S2: P { func foo() throws { print("S2") } } func callFoo<T: P>(of p: T) rethrows { try p.foo() } callFoo(of: S1()) do { try callFoo(of: S2()) } catch { print(error) }
S1 S2
Avatar
伝播もできた。 @swift-5.7.3 @rethrows protocol P { func foo() throws } @rethrows protocol Q { associatedtype PType: P func makeP() -> PType } struct S1: P { func foo() { print("S1") } } struct S2: P { func foo() throws { print("S2") } } struct T1: Q { func makeP() -> S1 { S1() } } struct T2: Q { func makeP() -> S2 { S2() } } func callFoo<T: Q>(from q: T) rethrows { try q.makeP().foo() } callFoo(from: T1()) do { try callFoo(from: T2()) } catch { print(error) }
Avatar
Avatar
koher
伝播もできた。 @swift-5.7.3 @rethrows protocol P { func foo() throws } @rethrows protocol Q { associatedtype PType: P func makeP() -> PType } struct S1: P { func foo() { print("S1") } } struct S2: P { func foo() throws { print("S2") } } struct T1: Q { func makeP() -> S1 { S1() } } struct T2: Q { func makeP() -> S2 { S2() } } func callFoo<T: Q>(from q: T) rethrows { try q.makeP().foo() } callFoo(from: T1()) do { try callFoo(from: T2()) } catch { print(error) }
S1 S2
Avatar
throws を持つメソッドが複数あった場合、両方に働きそう。 @swift-5.7.3 @rethrows protocol P { func foo() throws func bar() throws } @rethrows protocol Q { associatedtype PType: P func makeP() -> PType } struct S1: P { func foo() { print("S1.foo") } func bar() { print("S1.bar") } } struct S2: P { func foo() throws { print("S2.foo") } func bar() throws { print("S2.bar") } } struct T1: Q { func makeP() -> S1 { S1() } } struct T2: Q { func makeP() -> S2 { S2() } } func callFoo<T: Q>(from q: T) rethrows { try q.makeP().foo() } callFoo(from: T1()) do { try callFoo(from: T2()) } catch { print(error) }
Avatar
Avatar
koher
throws を持つメソッドが複数あった場合、両方に働きそう。 @swift-5.7.3 @rethrows protocol P { func foo() throws func bar() throws } @rethrows protocol Q { associatedtype PType: P func makeP() -> PType } struct S1: P { func foo() { print("S1.foo") } func bar() { print("S1.bar") } } struct S2: P { func foo() throws { print("S2.foo") } func bar() throws { print("S2.bar") } } struct T1: Q { func makeP() -> S1 { S1() } } struct T2: Q { func makeP() -> S2 { S2() } } func callFoo<T: Q>(from q: T) rethrows { try q.makeP().foo() } callFoo(from: T1()) do { try callFoo(from: T2()) } catch { print(error) }
S1.foo S2.foo
Avatar
↓これは無理。 throws を互い違いに付けた場合。 @swift-5.7.3 @rethrows protocol P { func foo() throws func bar() throws } @rethrows protocol Q { associatedtype PType: P func makeP() -> PType } struct S1: P { func foo() { print("S1.foo") } func bar() throws { print("S1.bar") } } struct S2: P { func foo() throws { print("S2.foo") } func bar() { print("S2.bar") } } struct T1: Q { func makeP() -> S1 { S1() } } struct T2: Q { func makeP() -> S2 { S2() } } func callFoo<T: Q>(from q: T) rethrows { try q.makeP().foo() } callFoo(from: T1()) do { try callFoo(from: T2()) } catch { print(error) }
Avatar
Avatar
koher
↓これは無理。 throws を互い違いに付けた場合。 @swift-5.7.3 @rethrows protocol P { func foo() throws func bar() throws } @rethrows protocol Q { associatedtype PType: P func makeP() -> PType } struct S1: P { func foo() { print("S1.foo") } func bar() throws { print("S1.bar") } } struct S2: P { func foo() throws { print("S2.foo") } func bar() { print("S2.bar") } } struct T1: Q { func makeP() -> S1 { S1() } } struct T2: Q { func makeP() -> S2 { S2() } } func callFoo<T: Q>(from q: T) rethrows { try q.makeP().foo() } callFoo(from: T1()) do { try callFoo(from: T2()) } catch { print(error) }
exit status: 1 with stderr:<stdin>:49:1: error: call can throw but is not marked with 'try' callFoo(from: T1()) ^~~~~~~~~~~~~~~~~~~ <stdin>:49:1: note: call is to 'rethrows' function, but a conformance has a throwing witness callFoo(from: T1()) ^
Avatar
Avatar
koher
↓これは無理。 throws を互い違いに付けた場合。 @swift-5.7.3 @rethrows protocol P { func foo() throws func bar() throws } @rethrows protocol Q { associatedtype PType: P func makeP() -> PType } struct S1: P { func foo() { print("S1.foo") } func bar() throws { print("S1.bar") } } struct S2: P { func foo() throws { print("S2.foo") } func bar() { print("S2.bar") } } struct T1: Q { func makeP() -> S1 { S1() } } struct T2: Q { func makeP() -> S2 { S2() } } func callFoo<T: Q>(from q: T) rethrows { try q.makeP().foo() } callFoo(from: T1()) do { try callFoo(from: T2()) } catch { print(error) }
omochimetaru 7/25/2022 3:30 AM
なるほど。callFoo の宣言がrethrowsになってて、普通なら一緒に渡してる引数のクロージャがthrowsがどうかが伝搬するけど、ここでは引数のrethrowsプロトコルがどうか、になるんですね (edited)
Avatar
そうみたいですね。
Avatar
omochimetaru 7/25/2022 3:31 AM
伝搬のルールは、 rethrows protocol の requirements の返り値の rethrows protocol が
3:31 AM
元protocolのthrows性と同一になる、という事か。
3:32 AM
で、rethrowsマーカーはrequirements全てのthrowsに連動していて、conform側では一貫していないといけない。
3:32 AM
一応動きそうなルールだ。
Avatar
伝播の実験 @swift-5.7.3 @rethrows protocol P { func foo() throws } @rethrows protocol Q { associatedtype PType1: P associatedtype PType2: P func makeP1() -> PType1 func makeP2() -> PType2 } struct S1: P { func foo() { print("S1") } } struct S2: P { func foo() throws { print("S2") } } struct T1: Q { func makeP1() -> S1 { S1() } func makeP2() -> S2 { S2() } } struct T2: Q { func makeP1() -> S2 { S2() } func makeP2() -> S1 { S1() } } func callFooOfP1<T: Q>(from q: T) rethrows { try q.makeP1().foo() } callFooOfP1(from: T1()) do { try callFooOfP1(from: T2()) } catch { print(error) }
Avatar
Avatar
koher
伝播の実験 @swift-5.7.3 @rethrows protocol P { func foo() throws } @rethrows protocol Q { associatedtype PType1: P associatedtype PType2: P func makeP1() -> PType1 func makeP2() -> PType2 } struct S1: P { func foo() { print("S1") } } struct S2: P { func foo() throws { print("S2") } } struct T1: Q { func makeP1() -> S1 { S1() } func makeP2() -> S2 { S2() } } struct T2: Q { func makeP1() -> S2 { S2() } func makeP2() -> S1 { S1() } } func callFooOfP1<T: Q>(from q: T) rethrows { try q.makeP1().foo() } callFooOfP1(from: T1()) do { try callFooOfP1(from: T2()) } catch { print(error) }
exit status: 1 with stderr:<stdin>:48:1: error: call can throw but is not marked with 'try' callFooOfP1(from: T1()) ^~~~~~~~~~~~~~~~~~~~~~~ <stdin>:48:1: note: call is to 'rethrows' function, but a conformance has a throwing witness callFooOfP1(from: T1()) ^
Avatar
@rethrows が付与されたプロトコルを @rethrows プロトコルと呼ぶことにする。また、 P@rethrows プロトコルのとき 、 func foo<T: P>(_ x: T) rethrowsthrows になる場合、 T が rethrowing であると呼ぶことにする。 このとき、 T が non-rethrowing である条件は、下記の二つが同時に満たされる場合に限る。
  • P のメソッドの内、 throws が付与されたものをすべて non-throws なメソッドとして実装する
  • Passociatedtype の内、 @rethrows プロトコルを制約として持つものをすべて non-rethrowing な型で実装する
Avatar
omochimetaru 7/25/2022 3:52 AM
あーなるほど。associatedtypeをnon-rethrowingで埋めてる、という形で再帰的なセットアップになるのか。
3:53 AM
返り値とかじゃなくて「全てのassociatedtype」なら、「全てのメソッド」と同じような感覚になっているしちょっとスッキリした。
Avatar
上記の挙動だと予測可能そうだね。
Avatar
おお、↓この挙動もいけた。 @swift-5.7.3 @rethrows protocol P { func foo() throws } @rethrows protocol Q { func bar() throws } struct S1: P { func foo() { print("S1") } } struct S2: P { func foo() throws { print("S2") } } struct T<PType: P>: Q { let p: PType func bar() rethrows { try p.foo() } } T(p: S1()).bar() do { try T(p: S2()).bar() } catch { print(error) }
Avatar
Avatar
koher
おお、↓この挙動もいけた。 @swift-5.7.3 @rethrows protocol P { func foo() throws } @rethrows protocol Q { func bar() throws } struct S1: P { func foo() { print("S1") } } struct S2: P { func foo() throws { print("S2") } } struct T<PType: P>: Q { let p: PType func bar() rethrows { try p.foo() } } T(p: S1()).bar() do { try T(p: S2()).bar() } catch { print(error) }
S1 S2
Avatar
関数の型パラメータじゃなく、ジェネリック型の型パラメータから @rethrows 使って rethrows できる。
4:57 AM
↓が必要なのでは? @rethrows protocol Error { func throw() throws -> Never } (edited)
Avatar
↑があれば、たとえば↓のようなことができる。 @rethrows protocol FailureProtocol: Error { func throwSelf() throws -> Never } extension FailureProtocol { func throwSelf() throws -> Never { throw self } } extension Never: FailureProtocol { func throwSelf() -> Never { fatalError() } } struct FooError: FailureProtocol {} @rethrows protocol ResultProtocol { associatedtype Value associatedtype Failure: FailureProtocol func get() throws -> Value } enum Result<Value, Failure: FailureProtocol>: ResultProtocol { case success(Value) case failure(Failure) func get() rethrows -> Value { switch self { case .success(let value): return value case .failure(let error): try error.throwSelf() } } } func useResult<R: ResultProtocol>(_ result: R) rethrows { try print(result.get()) } useResult(Result<Int, Never>.success(42)) try useResult(Result<Int, FooError>.success(42))
Avatar
omochimetaru 7/25/2022 5:09 AM
ResultのErrorの有無をrethrows protocolに自然に繋げられるんですね。 (edited)
Avatar
Forumでこういうの話されてないのかな?
Avatar
omochimetaru 7/25/2022 5:10 AM
心当たりはないです
5:10 AM
さっきのスレッドは当時眺めたけど。
Avatar
調べてなさそうだったら書いてみるか。
5:12 AM
元々は PublisherAsyncSequence でないのはなんでだろう?と考えていて、 values を挟んで AsyncPublisherAsyncThrowingPublisher が必要になるのは↑が欠けているのが問題なんじゃないかなと。
Avatar
@reasync があれば AsyncSequnceSequence に統合可能になる?
Avatar
omochimetaru 7/25/2022 5:58 AM
型理論としてはそんな気はしますが、コード生成上は難しそうですね (edited)
5:59 AM
throwsに関しては、
5:59 AM
Swiftは例外をcallerに返すところで専用のレジスタを使用しているので、
5:59 AM
throwsかnon throwsかで、ABI互換性があるんです。
5:59 AM
(non throwsな関数を、throwsな関数として使用することができる)
6:00 AM
でも、non asyncな関数と、asyncな関数はABIが全く違うので
6:00 AM
同じようにはできない。でもthunkでラップするだけで同じ感じにできるかも。 (edited)
Avatar
Avatar
omochimetaru
でも、non asyncな関数と、asyncな関数はABIが全く違うので
これは non-async な関数を async な関数として渡すときは大丈夫なの?暗黙の変換がされている?
Avatar
Avatar
koher
これは non-async な関数を async な関数として渡すときは大丈夫なの?暗黙の変換がされている?
omochimetaru 7/25/2022 6:01 AM
そういうときはthunkがついてるはずですね
Avatar
なるほど。
Avatar
omochimetaru 7/25/2022 6:01 AM
だから、non-asyncな関数をasyncな関数として渡すときは、ちょっとだけオーバーヘッドが増えてるはず
6:01 AM
でもasyncになる以上多少遅くなっても気にならない、というのがあると思うんですが
6:02 AM
うーん?Sequence側が遅くなる話ではないから、いいのかな?
6:02 AM
ラップすればいいような気もしてきた。 (edited)
Avatar
うーん難しい気がするなぁ
6:12 AM
await呼び出しは普通の関数呼び出しと全く違うので
6:15 AM
awaitのポイントで関数がsplitされていて、 func asyncF(_ item: Int, transform: (Int) async -> String)) async -> String { let out = await transform(item) print(out) return out } が、気持ち的にはこんな感じなんですよね↓ func asyncF(_ item: Int, transform: (Int) async -> String), nextContinuation: () -> Void) async { return transform(item, { out in print(out) return nextContinuation(out) }) } (edited)
Avatar
omochimetaru 7/25/2022 6:16 AM
あーそうか、継続になっているから、
Avatar
そうすると、sync版クロージャが渡された時とasync版が渡された時でそもそも形がぜんぜん違うんで
6:16 AM
そうそう
Avatar
omochimetaru 7/25/2022 6:16 AM
async関数として受け取るつもりになっているところに、実際はsyncな関数が渡ってきた場合に、全体をsyncに見せようとするためには
6:17 AM
async → sync の変換が必要で、継続をreturnに変換するために待たないといけないのか
6:18 AM
待たないといけないけど制御的には一度はswift concucurrencyに投げちゃう事になるから
6:18 AM
swift concurrencyでブロックしてはいけない規則と衝突してデッドロックのリスクが出そう
Avatar
syncクロージャをsync -> asyncに変換するだけならExecutorには制御移らないので、そのへんは実は大丈夫なんですけど
6:22 AM
reasync関数をsyncとして呼び出しても呼び出し元を全部CPS変換しないといけないかも
6:25 AM
実はこんなサンクで大丈夫かも func asyncF(_ item: Int, transform: (Int) async -> String), nextContinuation: () -> Void) async -> String [sync] func asyncF(_ item: Int, transform: (Int) -> String) -> String { var out: String! asyncF(item, sync_to_async(transform), { out = $0 }) return out } (edited)
Avatar
omochimetaru 7/25/2022 7:03 AM
なるほど ローレベルにはexecutorと関わらない生のasyncのようなものがあったのか (edited)
Avatar
そうそう。むしろactor hopやTaskによるunstructured job以外は全部こんな感じのはず
Avatar
omochimetaru 7/25/2022 7:18 AM
actor hopなかったら生の継続だったのか
Avatar
omochimetaru 8/9/2022 1:07 AM
Hi all, In the past few years, some components of the Swift compiler have started being implemented in Swift, including: The new Swift Driver, which coordinates Swift compilations. Parsing of regular expression literals. Some new SIL optimization passes. All of these components are optional for one reason or another. The new Swift Driver is ...
1:08 AM
SwiftコンパイラをSwiftで実装する提案、というか方針のアナウンス
1:10 AM
正確には、Swiftコンパイラのビルドプロセスに、Swiftコンパイラが必要な部分を導入する、かな?
1:11 AM
利用箇所として
  • CLIドライバー
  • 正規表現リテラル
  • gybとtablegen
の候補を挙げてる
1:12 AM
CLIドライバーと正規表現はすでにSwift実装されてるし、正規表現はセカンドステージビルドされてるし、 ドライバーなくてもコンパイラ動くからこいつらはあんまり状況が変わらない気がする (edited)
1:13 AM
gybとtablegenはpython実装だから、これがswift製のコードジェネレータになったら再利用しやすくて嬉しい (edited)
1:14 AM
Swift性のOptimizerは C++ Interoperabilityが完成するまでは必須パスには入れない・・・のかな
Avatar
随分CppInteropのやる気あるなぁと思っていたんですが、Swiftコンパイラで使うっていう直接的な需要があったからなんですかねぇ
Avatar
omochimetaru 8/9/2022 1:19 AM
同じ事思ってました、そんな気がしますね
Avatar
https://github.com/apple/swift-driver が元々 C++ 実装の置き換えを目指して作られていたので,それが始まった時点である程度既定路線な感じがしますね.
Swift compiler driver reimplementation in Swift. Contribute to apple/swift-driver development by creating an account on GitHub.
Avatar
Dictionary.KeysSet 的なメソッド( intersection, subtracting 等)ほしくないですか?一度 Set に包み直すのはオーバーヘッドがあるし、 DictionarySet もハッシュテーブルなので原理的には同等のパフォーマンスで実現できるかと。
Avatar
SetAlgebra を実装する?
Avatar
Commonly used data structures for Swift. Contribute to apple/swift-collections development by creating an account on GitHub.
3:39 AM
これの keysOrderedSet なのでそういうことできそうな
Avatar
逆に OrderedDictionarykeys が O(1) じゃないんじゃないかという心配が・・・
Avatar
Avatar
koher
逆に OrderedDictionarykeys が O(1) じゃないんじゃないかという心配が・・・
Commonly used data structures for Swift. Contribute to apple/swift-collections development by creating an account on GitHub.
Avatar
あー、なるほど。最初から OrderedSet で持っとくのか。
Avatar
逆に普通のDictionaryのkeysってO(1)なんですかね?
Avatar
O(1) です、
3:52 AM
NSDictionary のときに O(n) になってたんですが、それも O(1) になる PR を昔出しました。
Avatar
実際要素を集めてるわけじゃないのかな。 でSetに包むところで要素回収が入ってO(1)になる?
Avatar
Clock ってmacOS Venturaにならないと無いんでしたっけ
Avatar
omochimetaru 9/28/2022 8:33 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0329-clock-instant-duration.md at main · apple/swift-evolution
8:33 AM
Swift 5.7 から使えるんじゃ?
Avatar
使えそうに思ってたんですが、 Cannot find type 'Clock' in scope 言われちゃうんですよね
8:34 AM
Linuxだといける
Avatar
omochimetaru 9/28/2022 8:34 AM
https://github.com/apple/swift/pull/40609/files#diff-c98f1c7fa6a243da8b061282d3314e1d51d6a84ffdecabc1835132d3ac56cd17 @available(SwiftStdlib 5.7, *) public protocol Clock: Sendable { associatedtype Instant: InstantProtocol var now: Instant { get } var minimumResolution: Instant.Duration { get } func sleep(until deadline: Instant, tolerance: Instant.Duration?) async throws }
Avatar
いつもなら Xxx is available from mac OS 13 みたいな言い方されてた気がしますが、それすら出ない
Avatar
omochimetaru 9/28/2022 8:34 AM
ふーむ?
Avatar
iOSターゲットにしたら 'Clock' is only available in iOS 16.0 or newer になった
Avatar
ClockはstdlibなんでOS同梱のやつが更新されない限り使えないですよ
Avatar
omochimetaru 9/28/2022 9:08 AM
5.7コンパイラを搭載したXcodeは、
9:08 AM
Linux向けには5.7 stdlibを出荷しているけど
9:08 AM
mac向けにビルドする時に参照するようの5.7 stdlibは出荷していなくて、
9:08 AM
そこは実行環境のstdlibを見に行くってこと?
9:09 AM
ビルド用のSDKとしてはXcodeに同梱されている上で、 ビルドするときのdeployment targetの検査として、エラーになるのが正しい形な気がする。
9:09 AM
開発環境とターゲット環境がごっちゃになっているような感じがする。
Avatar
XcodeのツールチェインにlibswiftCore.dylib入ってたか覚えてないんですけど、
9:12 AM
OSSツールチェインの方には確実に入ってるんでコンパイル時のavailability checkを外せば動く
9:13 AM
開発時なら手元に最新のstdlibあるんだから動かせても良いじゃないか、には同意
Avatar
omochimetaru 9/28/2022 9:15 AM
[omochi@omochi-iMacPro Contents]$ find . | grep libswiftCore.dylib ./Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift/libswiftCore.dylib ./Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/appletvsimulator/libswiftCore.dylib ./Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/watchos/libswiftCore.dylib ./Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/iphoneos/libswiftCore.dylib ./Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/appletvos/libswiftCore.dylib ./Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/watchsimulator/libswiftCore.dylib ./Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/macosx/libswiftCore.dylib ./Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/iphonesimulator/libswiftCore.dylib [omochi@omochi-iMacPro Contents]$ pwd /Applications/Xcode14.app/Contents
9:16 AM
swift-5.0/macos/libswiftCore.dylib はあった。(この -5.0 ってなんだ?
Avatar
あ、そうそう、だからiOS Simulatorなら動きますよw
9:17 AM
-5.0 ちゃんと知らない
Avatar
間違ってたらすいませんmmこれで制御していたりしますか? That is to say, instead of # # @available(macOS 10.15.4, iOS 13.4, watchOS 6.2, tvOS 13.4, *) # # we can write # # @available(SwiftStdlib 5.2, *) SwiftStdlib 5.7:macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0 https://github.com/apple/swift/blob/475ed80c3eedb060d617fceed74686a4c6c86990/utils/availability-macros.def
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 9/29/2022 4:37 AM
なるほど、仕組み的にこういうエイリアスなんだ
Avatar
@swift-5.6.3 func get(id: Int)->String { "" } var myID: String { get(id: 1) // error: expected '{' to start getter definition } (edited)
Avatar
Avatar
t.ae
@swift-5.6.3 func get(id: Int)->String { "" } var myID: String { get(id: 1) // error: expected '{' to start getter definition } (edited)
exit status: 1 with stderr:<stdin>:6:8: error: expected '{' to start getter definition get(id: 1) // error: expected '{' to start getter definition ^ (edited)
Avatar
これコンパイラ側でうまくできないんだろうか。名前を変えるだけで回避できるので問題にされなそうですが。
Avatar
omochimetaru 11/2/2022 1:46 AM
バッククォートつけてもだめですか?
Avatar
@swift-5.6.3 func get(id: Int)->String { "" } var myID: String { `get`(id: 1) // error: expected '{' to start getter definition }
👀 2
Avatar
Avatar
Iceman
@swift-5.6.3 func get(id: Int)->String { "" } var myID: String { `get`(id: 1) // error: expected '{' to start getter definition }
no output
Avatar
バッククォートなるほど。 自前関数なら_一個つけるほうが短いですが、ライブラリとかで変更できない場合は使えますね。
Avatar
omochimetaru 11/4/2022 8:54 AM
言語機能にバックデプロイ機能をつける提案! https://github.com/apple/swift-evolution/blob/main/proposals/0376-function-back-deployment.md
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0376-function-back-deployment.md at main · apple/swift-evolution
8:54 AM
@Yuta Saito この前の会話にタイムリーかも
8:57 AM
宣言にバックデプロイが必要な境界バージョンを書く コンパイルターゲットがそれより低ければ、ライブラリのコードを埋め込む、ただしランタイムに本物を探して差し替えるフック処理を仕込む
9:04 AM
シンプルな分岐付きのサンクを吐くっぽいなー
Avatar
Kishikawa Katsumi 11/4/2022 9:38 AM
こういうのは嬉しいな
Avatar
Kishikawa Katsumi 11/4/2022 9:45 AM
読んでみたらこれは3rdのライブラリ作者のためのものじゃなくてStdLibのためのものかな?
9:45 AM
そりゃそうか。
Avatar
omochimetaru 11/4/2022 9:47 AM
そうですね、本家が提供するための仕組みっぽい
Avatar
Kishikawa Katsumi 11/4/2022 9:48 AM
そうよね。OSに同梱されるライブラリのものだからStbLibだけじゃないけど今のところAppleのための仕組みだな。
Avatar
これは嬉しそう
9:51 AM
ただこの書き方だとコールサイトごとにインライン展開されるっぽいなぁ
Avatar
Kishikawa Katsumi 11/4/2022 10:05 AM
関数定義をコピーして参照する、ような実装は複雑になっちゃうのかな。
Avatar
その方式だとコンパイル単位が複数あるときに複数コピーが入り込む余地があるので、なんとかしないといけないですね
10:10 AM
weakシンボルとして提供すれば静的なリンク時に1個だけピックされるんで、なんとかなる気はするんですが、PR見る限りそうはなって無さそう?
Avatar
Kishikawa Katsumi 11/4/2022 10:13 AM
ああ、なるほど。確かに。だいぶ複雑になるか。
Avatar
@swift-5.7.3 protocol P {} struct S: P {} extension CustomStringConvertible { func f() -> some P { S() } } var foo: some P { "".f() } var bar: some P { ("" as any CustomStringConvertible).f() }
Avatar
Avatar
Iceman
@swift-5.7.3 protocol P {} struct S: P {} extension CustomStringConvertible { func f() -> some P { S() } } var foo: some P { "".f() } var bar: some P { ("" as any CustomStringConvertible).f() }
exit status: 1 with stderr:<stdin>:15:39: error: type 'any P' cannot conform to 'P' ("" as any CustomStringConvertible).f() ^ <stdin>:15:39: note: only concrete types such as structs, enums and classes can conform to protocols ("" as any CustomStringConvertible).f() ^ <stdin>:14:10: note: required by opaque return type of var 'bar' var bar: some P { ^~~~~~
Avatar
この、existentialから呼び出した関数の返り値ORTがconcrete typeとして扱われないのって何でなんでしょうか?
Avatar
これexistentialがopenされてるからfの型がラップされてsome Pからany Pになってる?
Avatar
any CustomConvertibleとsome CustomConvertibleで差がありそう
8:08 AM
Error型でやったら違う結果になったりしませんか
Avatar
Error にしても変わりませんでした
8:11 AM
@swift-5.6.3 @swift-5.7.3 protocol P {} struct S: P {} extension Error { func f() -> some P { S() } } extension String: Error {} var foo: some P { "".f() } var bar: some P { ("" as any Error).f() } (edited)
Avatar
Avatar
Iceman
@swift-5.6.3 @swift-5.7.3 protocol P {} struct S: P {} extension Error { func f() -> some P { S() } } extension String: Error {} var foo: some P { "".f() } var bar: some P { ("" as any Error).f() } (edited)
exit status: 1 with stderr:<stdin>:17:21: error: type 'any P' cannot conform to 'P' ("" as any Error).f() ^ <stdin>:17:21: note: only concrete types such as structs, enums and classes can conform to protocols ("" as any Error).f() ^ <stdin>:16:10: note: required by opaque return type of var 'bar' var bar: some P { ^~~~~~ (edited)
Avatar
Avatar
Iceman
@swift-5.6.3 @swift-5.7.3 protocol P {} struct S: P {} extension Error { func f() -> some P { S() } } extension String: Error {} var foo: some P { "".f() } var bar: some P { ("" as any Error).f() } (edited)
exit status: 1 with stderr:<stdin>:17:7: error: member 'f' cannot be used on value of protocol type 'Error'; use a generic constraint instead ("" as any Error).f() ~~~~^~~~~~~~~~~~~ ~
8:16 AM
↑この話でassociatedtypeがeraseされる理屈でORTも保てないような気がする
Avatar
ORTの真の型がSelf に依存しうるから、一律で禁止されているという感じでしょうかね?
8:23 AM
protocolのextensionだけに生やした関数はprotocolのwitness tableに乗らないからexistential経由で呼ぶ場合は常に同じ関数が呼ばれるけど、とはいえその中でSelfを使う可能性があるか (edited)
Avatar
そうですね。これができる。 struct S<T>: P {} extension CustomErrorConvertible { func foo() -> some P { return S<Self>() } }
Avatar
これは気持ち悪いなw
Avatar
ORTはその関数に対して返り値の真の型を先に取得する仕組みがあって、 呼び出し側はそれを使って先に返り値の領域を用意するけど、 var bar: some P の真の型がどうなるかが CustomStringConvertible を open した self によって動的に変わるから事前に決定できない (edited)
Avatar
any Tにsome Uを生やせるのがそもそもマズいのでは?と思った
8:31 AM
extension Tと書いたときに、それがsome Tに生えてるのかany Tに生えてるのかを区別できれば
8:31 AM
問題にならなくなる気がするな
Avatar
Avatar
tarunon
any Tにsome Uを生やせるのがそもそもマズいのでは?と思った
これ5.5以前はできなかったんじゃないかな・・・?
8:31 AM
5.6?5.7から、existentialの制限が無くなって
8:31 AM
例えばassociatedtypeがあってもany Pが作れるようになった (edited)
8:32 AM
で、いろんな問題があるんだけど、 それは any P を openして <T: P> に対して呼び出す瞬間までは問題なくて、 any Pを触った人のところに戻すところでeraseすることで問題を解決?している
8:32 AM
なので P に生えてるものは全部 any P に生えてる扱いなんですよ
Avatar
@swift-5.7.3 @swift-5.6.3 @swift-5.5.3 protocol P {} struct S: P {} extension Error { func f() -> some P { S() } }
Avatar
Avatar
Iceman
@swift-5.7.3 @swift-5.6.3 @swift-5.5.3 protocol P {} struct S: P {} extension Error { func f() -> some P { S() } }
no output
Avatar
Avatar
Iceman
@swift-5.7.3 @swift-5.6.3 @swift-5.5.3 protocol P {} struct S: P {} extension Error { func f() -> some P { S() } }
no output
Avatar
Avatar
Iceman
@swift-5.7.3 @swift-5.6.3 @swift-5.5.3 protocol P {} struct S: P {} extension Error { func f() -> some P { S() } }
no output
Avatar
今ってextension Tを書くと実質的に任意のsome Tに対して関数生やしてる状態になってると思うんですが
8:33 AM
人々の理解はここに至ってなくて、結構any Tに生やしてると思ってそう
Avatar
生やすことはできるけど、使うときのほうに制約がかかってそうですね
Avatar
Avatar
tarunon
今ってextension Tを書くと実質的に任意のsome Tに対して関数生やしてる状態になってると思うんですが
extension P は常に <Self where Self. P> に対するextensionなんですよね
Avatar
selfを見たときにopenedなのがそれを示してる
🆗 1
Avatar
any P が implicit openによって <T: P> も使えてるってのが真実 (edited)
Avatar
だから、ここがextension書くときに明示的にsomeに対してなのか、anyに対してなのかを区別したくて
8:35 AM
これを区別できなければ、extension Tに生やしたsome Uが帰る関数を、any Tから使わせることは出来ない
Avatar
Avatar
Iceman
生やすことはできるけど、使うときのほうに制約がかかってそうですね
5.5からこのerase挙動あったのかもしれんな・・・?
Avatar
extension any Tなる構文がなければ、icemanのやりたいことは実現できないと思う
Avatar
なるほど確かにそうですね。 > これを区別できなければ 実際僕はSelfを使うつもりがないのにこの制約にハマって困ってしまった
Avatar
ああたしかに。 extension any P だったら固定で真の型が返せるね。 (edited)
Avatar
結論、extension some Tとextension any Tできっちり分離するべきなんじゃないかなーと考えました
t_tashikani 1
Avatar
いやでも、any P は P のメソッドが呼べるっていうのは出発点だから
Avatar
someならselfはopened anyならselfはexistential
Avatar
some Pだけにextensionするっていうのはおかしくなっちゃう
8:39 AM
今までは、呼べないエントリがあるとany Pが作れなくなる、という縛りだったのが
8:39 AM
5.7から、呼べないエントリは呼べる形にeraseすることでどんなany Pも作れるようになる (edited)
8:39 AM
という方向に改善された、というのが全体の流れ (edited)
Avatar
言ってることもやってることも、これは俺もおもちもicemanもわかるけど
8:41 AM
じゃあさっきicemanが踏んだ事象をいきなり見たときに、なるほどね、とはならなくないかw
8:41 AM
相当ムズいぞ
Avatar
extension P { ... } // ↓第一の心の目: ジェネリックなセマンティクスを正しくみつめる extension <Self: P> {} // ↓第二の心の目: self引数を opaque parameter type的に捉える事ができる extension some P { } // ↓第三の心の目: Swift 7 で `P` を `any P` から `some P` に切り替えるので extension P { ... } // もどった! (edited)
Avatar
Avatar
tarunon
相当ムズいぞ
まあ今までは、「なんでassociated typeあると P が変数に使えないの?」で、難しい話が蓋されてたんだよね、それが開いちゃった
Avatar
それ一般的に理解できないと思うが、Swiftの方向性としては、人々がanyとsomeを正しく理解しなくても、コンパイラの導きの元、もっともらしく動作するならコンパイルが通るようになる、と言うところを目指してるんだろうけど
8:46 AM
これrustならextensionの宣言でanyとsomeを明示する方向性になってそうだ (edited)
Avatar
@swift-5.5.3 protocol P {} protocol Q { func p() -> some P } func foo(q: Q) -> some P { return q.p() }
Avatar
Avatar
omochimetaru
@swift-5.5.3 protocol P {} protocol Q { func p() -> some P } func foo(q: Q) -> some P { return q.p() }
exit status: 1 with stderr:<stdin>:3:15: error: 'some' type cannot be the return type of a protocol requirement; did you mean to add an associated type? func p() -> some P ^~~~~~ <#AssocType#>
Avatar
@swift-5.5.3 protocol P {} protocol Q {} struct S: P {} extension Q { func p() -> some P { return S() } } func foo(q: Q) -> some P { return q.p() }
Avatar
Avatar
omochimetaru
@swift-5.5.3 protocol P {} protocol Q {} struct S: P {} extension Q { func p() -> some P { return S() } } func foo(q: Q) -> some P { return q.p() }
exit status: 1 with stderr:<stdin>:8:10: error: member 'p' cannot be used on value of protocol type 'Q'; use a generic constraint instead return q.p() ^ ~
Avatar
5.5までは any Q の some P を返すエントリは呼び出せなかったのか〜
Avatar
「extension Tに生やした関数fooをany Tから使うとき、any Tに直接生えた関数fooではなく、any Tに包まれているsome Tに生えた関数fooをanyに包んで参照している」
🙆‍♂️ 1
Avatar
@swift-5.6.3 @swift-5.7.3 protocol P {} protocol Q {} struct S: P {} extension Q { func p() -> some P { return S() } } func foo(q: Q) -> some P { return q.p() }
Avatar
Avatar
omochimetaru
@swift-5.6.3 @swift-5.7.3 protocol P {} protocol Q {} struct S: P {} extension Q { func p() -> some P { return S() } } func foo(q: Q) -> some P { return q.p() }
exit status: 1 with stderr:<stdin>:8:10: error: member 'p' cannot be used on value of protocol type 'Q'; use a generic constraint instead return q.p() ^ ~
Avatar
Avatar
omochimetaru
@swift-5.6.3 @swift-5.7.3 protocol P {} protocol Q {} struct S: P {} extension Q { func p() -> some P { return S() } } func foo(q: Q) -> some P { return q.p() }
exit status: 1 with stderr:<stdin>:8:12: error: type 'any P' cannot conform to 'P' return q.p() ^ <stdin>:8:12: note: only concrete types such as structs, enums and classes can conform to protocols return q.p() ^ <stdin>:7:19: note: required by opaque return type of global function 'foo(q:)' func foo(q: Q) -> some P { ^~~~~~
Avatar
これが命題なワケだが…一般的に理解するのはしんどいなぁw
Avatar
5.6も同じエラーだな。5.7から即any Pにeraseされる形でopenできるようになって、エラーメッセージがこうかわるんだ
8:51 AM
@swift-5.7.3 protocol P {} protocol Q {} struct S: P {} extension Q { func p() -> some P { return S() } } func foo(q: Q) -> any P { return q.p() // erase to any P } (edited)
Avatar
Avatar
omochimetaru
@swift-5.7.3 protocol P {} protocol Q {} struct S: P {} extension Q { func p() -> some P { return S() } } func foo(q: Q) -> any P { return q.p() // erase to any P } (edited)
no output (edited)
Avatar
anyとsomeのまとめ、結構需要ありそうだな
8:58 AM
some Tってもうその辺で使えるようになったんですよね、これを切っ掛けとして
Avatar
"Swift 5.7におけるProtocol-Oriented Programming"と題して、今週末ライブコーディングします。Swift 5.7でsomeとanyに色々変更が加えられましたが、それらを考慮した現代のProtocol-Oriented Programmingを、標準ライブラリを題材に実演予定です。 #swiftzoomin https://t.co/KNEPQcxwr3
Avatar
もうやってた
Avatar
@koher さんが最近(10/29)にもそういうのやってたっぽい
Avatar
some Tが返り値限定だったときはただのReverseGenericsだったのが
9:00 AM
一級になったもんだからその辺にカジュアルにジェネリクスがぽんと涌いて出るようになって
9:00 AM
既にいたexistentialとどっち?!みたいなことになりがちなのかな
Avatar
そろそろ5.7普通に使っていいころだと考えると、 any P のanyキーワードのプロポーザルが出たのが去年の12月、引数の some P が2月で、 自分の場合1年間ぐらい予習期間があったっぽいな (edited)
9:04 AM
予習なしだといよいよ大波が来る感じだな 大変だ
Avatar
予習というか殊これに関しては、本質的な理解と考察が全てを救えるので
9:06 AM
わいわいの1から3あたりの話題を理解してれば解が得られるんじゃないかという気もする (edited)
9:06 AM
最初の頃existential vs genericsが専らの話題だった
Avatar
Avatar
omochimetaru
@koher さんが最近(10/29)にもそういうのやってたっぽい
これは someany 中心の話というより、 Primary Associated Type と some, any 込みで SequenceCollection を題材にもう一度 POP を考えてみましょうって話でした。
Avatar
あの時と本質は変わってないと思います
Avatar
Avatar
tarunon
あの時と本質は変わってないと思います
たしかに最初の頃はexistentialとopenってなんだ?って話してたねw
Avatar
あれマジで本質、ukitakaくんには感謝しかない
Avatar
たしかに。こんなに長く役立つSwiftの難しさの本質を捉えたテーマだったとは・・・ (edited)
Avatar
で、今や暗黙的なopenと、その逆の操作でexistentialからあらゆる関数が呼べるようになるって言うのが入った
9:09 AM
最初のopenを正しく理解してれば、そこの延長ですね
Avatar
Avatar
koher
これは someany 中心の話というより、 Primary Associated Type と some, any 込みで SequenceCollection を題材にもう一度 POP を考えてみましょうって話でした。
なるほど。
Avatar
Hi Evolution! Below is my pitch to introduce some new high level reflection APIs to Swift. Please let me know what you think! Reflection Proposal: SE-NNNN Authors: Alejandro Alonso Review Manager: TBD Status: Awaiting implementation Introduction I propose adding a new module to the Swift toolchain named Reflection that provides high lev...
7:22 PM
azoyさんがリフレクションAPIのピッチを出してる。 コード生成とかに使えそう。
Avatar
omochimetaru 12/5/2022 4:04 PM
Anyone who works on command line tools written in Swift will know that program crashes can be somewhat tricky to debug — in some cases a crashing program will simply terminate with no output to explain what went wrong. We know that this is a pain point for users both within and outside of Apple. To those users: there is light at the end of the ...
4:05 PM
スタックトレースをサードパーティライブラリ入れなくても出せるように作業しているらしい
Avatar
Taskの切り替えが発生してもいい感じに生のスタックじゃなくて論理的なスタックトレースになってくれるのかな
Avatar
omochimetaru 12/5/2022 4:21 PM
cross async boundaryについてコメントも付いてるけどまだスレ主の返信はないね 流石にやるんじゃない?と思うけど・・・
Avatar
omochimetaru 12/5/2022 4:29 PM
There will be further posts about this in due course, including a Swift Evolution proposal for APIs in the standard library that will provide programs with the ability to programmatically capture a backtrace when required.
4:30 PM
スタックトレースを取得するstdlib APIも提供するつもりで、そこでEvolution通すから、もし言及がなかったらそのタイミングで聞けそう
Avatar
なるほど
Avatar
omochimetaru 12/7/2022 7:38 PM
Experiment with expressing the Swift type system as value types - GitHub - DougGregor/SwiftTypeSystem: Experiment with expressing the Swift type system as value types
7:39 PM
ツール(?)やリフレクションAPIに渡すための型情報のライブラリが出来てる
7:40 PM
型システムが型パラメータ化されてて、なんかテクニカルな定義になってるけどまだ用例がなくて謎だ
Avatar
omochimetaru 12/8/2022 4:01 PM
Add @_objcImplementation by beccadax · Pull Request #60630 · apple/swift · GitHub is a great PR and will greatly improve more Swift coverage on old ObjC codebase projects. But it is a fairly big change and adds some new features to Swift. Should it go through the Swift Evolution Process? cc @beccadax Swift Evolution Process Scope The Swift ev...
4:02 PM
謎のデカい機能が実装されてるw
4:02 PM
objcヘッダー+swift実装でobjcクラスを実装できる機能で
4:03 PM
@objc classとは違って、本物のobjc classが実装されるらしい
4:03 PM
例えば@objc classはobjc側から触れるアダプターがついたswift classにすぎないから、
4:03 PM
objcからもっかいそれを継承したり、メソッドswizzleしたりするのはうまくいかないらしいが
4:04 PM
これはそういうobjc互換性が完全に提供されるらしい
4:05 PM
これは予想なんだけど、Apple内部でUIKitとかを完全にSwift化するために、インクリメンタルに書き換えていけるようにするために必要なんじゃないかしら。 (edited)
Avatar
SwiftでObjCが書ける!
Avatar
omochimetaru 12/8/2022 4:08 PM
まだSwift化できてないプロジェクトを抱えてる人の役に立つ。。
Avatar
純粋なObjC実装ができるという部分にどういうメリットがあるのかが謎ですね
Avatar
omochimetaru 12/8/2022 4:09 PM
上で軽く書いた通りですね プロポーザルに詳しく書いてある
Avatar
書かれている通りswizzleとかが動くのは嬉しいのだろうけど、そんなにswzzle多用してるコードをクッションのためだけにSwiftで書き直したいとなるものなのだろうか・・・?
Avatar
omochimetaru 12/8/2022 4:11 PM
再継承を可能にするやつの方がやりたいんじゃないかな。
4:11 PM
UIKitを置き換えるなら、ユーザーはそれをobjcからもUIButtonのサブクラスを作ったりできないといけないし (edited)
4:11 PM
現状だと先にUIViewをSwift化することとかもできない
Avatar
あ〜、UIViewを単純に今の形でSwift化すると黒魔術使ってる人全般が困るということですね
Avatar
omochimetaru 12/8/2022 4:13 PM
黒魔術もそうだし普通にobjcでカスタムクラス作ってる人が詰んでしまう
4:13 PM
This limits their capabilities—for instance, Objective-C code cannot subclass an @objc class, reliably swizzle its methods, or introspect its instance variables.
Avatar
あ、Swift定義したクラスってObjCから継承できないんですね。やろうとしたことなかったから気づかなかった
Avatar
omochimetaru 12/8/2022 4:15 PM
俺も今知った。
Avatar
全部にdynamicつければプロパティとかはいけそうだけど、親クラスをすり替えるとかは無理そうですね
Avatar
omochimetaru 12/8/2022 4:17 PM
あとなんかカテゴリ実装した時に名前が被った時の挙動とかも微妙に違うみたいなことがかいてある
4:18 PM
今までの@objcがswiftのクラスをobjc互換にする機能とすると、@objImplementationはswiftクラスを定義するのではなくswiftで書いたコードをobjcにトランスパイルするような感じに近いと思う (edited)
Avatar
final つければObjCから見えなくなるって書いてあるので、Swiftの機能が使えたりしそう?
4:19 PM
関数内部に閉じてればKeyPathとか使えるのかな
Avatar
omochimetaru 12/8/2022 4:21 PM
final funcはswift only typeが使えるって書いてあるしできそう
4:22 PM
As a special exception to the usual rule, a non-category @objcImplementation extension can declare stored properties.
extensionでプロパティ定義できるのウケる。objcは確かにそうだった。
Avatar
あれ、objc_getAssociatedObjectとか使わなくても増やせるんでしたっけ
4:28 PM
Unlike regular categories, a class extension can add its own properties and instance variables to a class. If you declare a property in a class extension, like this: @interface XYZPerson () @property NSObject *extraProperty; @end
4:29 PM
↑これでヘッダーに載せないフィールドが書ける
4:29 PM
It’s also possible to use a class extension to add custom instance variables. These are declared inside braces in the class extension interface: @interface XYZPerson () { id _someCustomInstanceVariable; } ... @end
Avatar
あ、.m側に書くやつですね
👌 1
4:30 PM
a non-category @objcImplementation extension ってそういうことか
Avatar
omochimetaru 12/8/2022 4:30 PM
この空の丸かっこ(無名カテゴリ?)の気持ちを表したルールやろうね (edited)
4:33 PM
cxx interopも頑張ってるし、appleがいよいよ既存のobjc実装を捨てようとしてるのかもしれないなあ CoreGraphicsとかは内部がcxx実装だから、objc層をswiftに置き換えるならcxx層を呼び出せないと困るし。
t_naruhodo 2
Avatar
Kishikawa Katsumi 12/8/2022 4:35 PM
無名カテゴリはクラスエクステンションといいます。無名カテゴリともいうけど。
naruhodo 1
Avatar
個人的には完全にprivate修飾子の代わりと思って使ってました
Avatar
objective-c は private(気持ち) しかないからなあ
7:31 PM
swiftでobjc がかけるのすごいな
7:32 PM
objc でswiftがかければ置き換える必要がなくなる
Avatar
omochimetaru 12/9/2022 3:06 AM
objc -> swiftは謎のattributeで多少見え方をが変えられるぐらいですよね。
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/using-swift-from-c++.md at main · apple/swift-evolution
6:54 AM
C++からSwiftを使うinteropについてのvision documentが公開されたそうです
Avatar
Hello, Swift community. "Manifestos" have historically served an important role in Swift's design. A manifesto pairs a long-form analysis of the current state of one area of the project with a high-level vision for how that area should evolve in the future. It establishes common terminology, propagates key conceptual models, and sets communit...
8:21 AM
vision documentというのは、従来のmanifestoを改善するもので、対象のワーキンググループによる承認プロセスを通すらしい。その過程で、内容にコミュニティがフィードバックできるようにするらしい。manifestoはコアチームが内輪でやっていたし、手続きの決め事もなかったのでそれを改善するらしい。
8:22 AM
現状の解決すべき課題やその方向性を合意するもので、ただし具体的な方法は確定しないらしい。そこは従来どおりevolusion proposalなんだろう。
Avatar
C++ interoperability does not require Swift opt in
SwiftをObjCから呼び出すためには、Swift側で @objc を付けるなどのオプトインの作業が必要だったけど、SwiftをC++から呼び出す機能の設計にあたっては、 C++コンパイラが Swift Calling Conventionをサポートする事によって、オプトインの作業無しで、全てのSwift moduleを直接C++から使えるようにするらしい。すごい。
Avatar
C++コンパイラがSwiftのために専用実装を持つということでしょうか? (edited)
Avatar
まだ↑の概要読んだだけだから細かいことはわからんけど多分そう C++って __stdcall みたいな、関数にattributeを付ける事によって、呼び出し規約を指定する機能があるんだけど、これに __swiftcc を追加するって事だと思う。 で、 __swiftcc が付いたC++で書かれたブリッジヘッダーをSwiftコンパイラ側が生成するんだろう。 (edited)
Avatar
なるほど。よその言語のためにそれしてもらうのすごいですね(実は前例がいくつかあるのだろうか?)
Avatar
まあSwiftのためにLLVMに swiftcc 追加されたりしてるから、 clang にそれを追加するのもいけるって感じなんじゃないかなあ。SwiftコアチームにはC++コンパイラの人も居るし。 あと、家庭くんがSwiftをWASMにコンパイルするために、WASMのバイナリフォーマットにRelative Pointerを追加してもらった件とかはちょっと似てると思う。 ただ、Visual Studioに搭載されてるMS製のC++コンパイラはどうするんだろうね。
Avatar
CPPコンパイラたくさんありますもんね iccとかも追従するのかな
Avatar
たしかにねえ
Avatar
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
12:40 AM
c++ CLANG_MACRO("SWIFT_INDIRECT_RESULT", , "__attribute__((swift_indirect_result))") CLANG_MACRO("SWIFT_CONTEXT", , "__attribute__((swift_context))") CLANG_MACRO("SWIFT_ERROR_RESULT", , "__attribute__((swift_error_result))") ↑このへんもあった。
12:40 AM
indirect_result とかもポートしてるの面白いね
12:42 AM
たしかにこれ系って、SIL生成時に付与されて、LLVM-IRにそのまま転送されて、LLVMによってネイティブコードになるところで処理されるから、(LLVMベースの実装であるclangなどの)C++コンパイラとしては、別にSwift対応ってそんなに作業量は多くないのかも (edited)
Avatar
Hello, Swift community! The C++ Interoperability Workgroup has been hard at work developing a vision for both forward and reverse interop (using C++ from Swift and visa-versa). The reverse interop vision has recently been accepted by The Language Workgroup and the forward interop vision is approaching completeness. While The C++ Interop Workgr...
11:48 PM
c++をSwiftにインポートする機能のビジョンが出た まだ正式確定ではないっぽい
Avatar
kateiくんの発表で紹介されてたbenchmarkgamesのSwiftのコードを見てたら、↓が他より30倍以上遅いんだけど、何がそんなに悪いんだろう?コードの処理の中身までちゃんと追ってないから効率の悪い計算してるのかもしれないけど、そんなにヤバいことしてなさそうな。変にクラスとかも使ってないし、CoWのコピーも発動してなさそう。ジェネリクスの Specialize が効いてなかったりする?? https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/nbody-swift-9.html
5:10 AM
SIMD4(repeating:) を多用してるのは気になる。
5:13 AM
やってるのは N体のシミュレーションっぽい。太陽・木星・土星・天王星・海王星の運動をシミュレーションしてる。
5:14 AM
SIMDの使い方がよくないのかな・・・。
5:15 AM
あとは計算方法が普通に効率悪い可能性あるけど、それはちゃんと見比べないとわからないな。
5:17 AM
SIMD3 にして質量を別で扱うと速くなるかも。 SIMD4 にしてる利点がない気がする。
5:18 AM
-Ounchecked でコンパイルされてるみたいだから、普通に考えたら Specialize はされそう。
5:18 AM
swiftc nbody.swift-9.swift -Ounchecked -wmo -o nbody.swift-9.swift_run
Avatar
手元でちょっと試したら、 dot を自前なのやめて import simd したら倍くらいの速度になりました ❯ time ./test 20000000 -0.169075164 -0.169031665 ./test 20000000 2.19s user 0.00s system 99% cpu 2.200 total ❯ time ./test2 20000000 -0.169075164 -0.169031665 ./test2 20000000 1.20s user 0.00s system 99% cpu 1.207 total
7:07 AM
❯ diff test.swift test2.swift 1a2 > import simd 8,14c9,15 < func dot<V : SIMD>(_ a: V, _ b: V) -> V.Scalar where V.Scalar : FloatingPoint { < var total = V.Scalar(0) < for i in a.indices { < total = total.addingProduct(a[i], b[i]) < } < return total < } --- > // func dot<V : SIMD>(_ a: V, _ b: V) -> V.Scalar where V.Scalar : FloatingPoint { > // var total = V.Scalar(0) > // for i in a.indices { > // total = total.addingProduct(a[i], b[i]) > // } > // return total > // }
Avatar
simdモジュールって何入ってるんですか?
Avatar
何なんでしょうね?
Avatar
というかこれDarwin-onlyっぽい
Avatar
そうなんですよ
7:11 AM
とはいえ、SIMDの実装に大きく影響をうけてそうだなと
Avatar
stdlibには普通にSIMD用の型があるのと (edited)
7:12 AM
いや、dotは特殊命令ないのか? (edited)
Avatar
omochimetaru 1/23/2023 7:15 AM
積和だからありそう
Avatar
stdlibにはSIMD型はあってもほとんど機能がなくて、いろんな計算はsimdモジュール使うんですけど、そこ分かれてるのよくわからないんですよね
7:34 AM
https://github.com/apple/swift/blob/336af608c0234f27ea1727ef0e1f4afabc07bcdc/stdlib/public/core/SIMDVector.swift#L846-L850 このただの掛け算も全然ベクトル計算してなさそうに見える
7:35 AM
// Implementations of floating-point operations. These should eventually all // be replaced with @_semantics to lower directly to vector IR nodes.
って書いてある
Avatar
その置き換えがされてない?置き換えられなかったらめっちゃ遅そうですよね。これ。 @_transparent public static func *(a: Self, b: Self) -> Self { var result = Self() for i in result.indices { result[i] = a[i] * b[i] } return result }
Avatar
Avatar
Iceman
https://github.com/apple/swift/blob/336af608c0234f27ea1727ef0e1f4afabc07bcdc/stdlib/public/core/SIMDVector.swift#L846-L850 このただの掛け算も全然ベクトル計算してなさそうに見える
そのへんは全部LLVM側でベクトル計算に最適化されます。ベクトル計算サポートしてないターゲットではSwiftで書かれたとおりのナイーブな実装にフォールバックする
1:45 AM
@swift-5.7.3 -frontend -emit-assembly -O -parse-as-library -module-name CHECK public func SHOW_ME_MULPD(lhs: SIMD2<Double>, rhs: SIMD2<Double>) -> SIMD2<Double> { lhs * rhs } (edited)
Avatar
Avatar
Yuta Saito
@swift-5.7.3 -frontend -emit-assembly -O -parse-as-library -module-name CHECK public func SHOW_ME_MULPD(lhs: SIMD2<Double>, rhs: SIMD2<Double>) -> SIMD2<Double> { lhs * rhs } (edited)
.text .file "<swift-imported-modules>" .protected $s5CHECK13SHOW_ME_MULPD3lhs3rhss5SIMD2VySdGAG_AGtF .globl $s5CHECK13SHOW_ME_MULPD3lhs3rhss5SIMD2VySdGAG_AGtF .p2align 4, 0x90 .type $s5CHECK13SHOW_ME_MULPD3lhs3rhss5SIMD2VySdGAG_AGtF,@function $s5CHECK13SHOW_ME_MULPD3lhs3rhss5SIMD2VySdGAG_AGtF: mulpd %xmm1, %xmm0 retq .Lfunc_end0: .size $s5CHECK13SHOW_ME_MULPD3lhs3rhss5SIMD2VySdGAG_AGtF, .Lfunc_end0-($s5CHECK13SHOW_ME_MULPD3lhs3rhss5SIMD2VySdGAG_AGtF) .hidden __swift_reflection_version .type __swift_reflection_version,@object .section .rodata,"a",@progbits .weak __swift_reflection_version .p2align 1 __swift_reflection_version: .short 3 .size __swift_reflection_version, 2 .type .L_swift1_autolink_entries,@object .section .swift1_autolink_entries,"e",@progbits .p2align 3 .L_swift1_autolink_entries: .asciz "-lswift_Concurrency\000-lswiftCore\000-lswift_StringProcessing" .size .L_swift1_autolink_entries, 57 .section ".linker-options","e",@llvm_linker_options .section ".note.GNU-stack","",@progbits (edited)
Avatar
ちゃんとベクトル計算化されてる mulpd %xmm1, %xmm0
Avatar
おおなるほど、そういう仕組みなんですね
3:02 AM
LLVM側でベクトル計算を試みてほしいフラグがついてるのでしょうか?それとも計算式だけ見てLLVMが勝手にやってる?
Avatar
LLVMがパターンを勝手に見つけて頑張って最適化します
⁉️ 1
Avatar
すごい
3:04 AM
じゃあ func dot<V : SIMD>(_ a: V, _ b: V) -> V.Scalar where V.Scalar : FloatingPoint { var total = V.Scalar(0) for i in a.indices { total = total.addingProduct(a[i], b[i]) } return total } このdotの実装はLLVMがうまくパターン見つけられなくて最適化されなかったのかもなぁ
Avatar
ですねぇ
Avatar
言語間の速度テストじゃなくてLLVMの気持ちわかり選手権になってる可能性があると
👀 1
Avatar
コンパイラがいかにLLVMに優しいコードを吐くか
Avatar
omochimetaru 1/25/2023 3:20 AM
llvm側が既存のC出力を見て育てられた側面もありそう
Avatar
固定長配列が無いのが痛いなぁ
Avatar
omochimetaru 1/25/2023 4:27 AM
indicesで動的な長さのループに抽象化されてるところが難しいのか。
Avatar
そうなんですよねー
4:53 AM
そうするとLoop Unrollingがむずかしくて
4:53 AM
おそらくその結果branchの数がRustの10倍くらいになってる
naruhodo 1
Avatar
RustはLLVMの最適化レベルを3にしてる https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/nbody-rust-6.html が、Swiftの -O はレベル2なのでそもそも比較の土台が全然違った
😮 1
5:41 AM
Rustの最適化レベルを2にするとSwiftのほうが速くなるが、Rustコンパイラの前段の最適化も抑制されそうなのでこれも比較できなさそう。
Avatar
omochimetaru 1/25/2023 5:42 AM
Swiftに -O3 が必要じゃん。
Avatar
動くのかなー
Avatar
omochimetaru 1/25/2023 5:42 AM
前提条件満たせなくてぶっ壊れるみたいなことがありえるのか
Avatar
壊れてもおかしくない
5:50 AM
Loop Unrollingの効き方にかなり差があって、流石にこれは勝てない。
5:50 AM
上がSwift下がRust
Avatar
SwiftとRustの一番の違いは最適化の差だったのか・・・
5:52 AM
for i in 0 ..< 100 みたいなのでもアンロールされない?
Avatar
展開後のコードサイズが一定を超えるとアンロールされなくなるんですよね。-O3はその閾値を上げるか無視するかだったはず
Avatar
なるほど
Avatar
むやみにUnrollしてコードサイズ増やすとCPUキャッシュのヒット率が下がって、むしろ遅くなるのでそういうしきい値が入ってるんですけど、今回のRustの場合だと展開後の定数畳み込みと、それによるdead code eliminatinでうまくハマってる感じだと思います。 (edited)
6:04 AM
perf-statの結果 $ perf stat -d -d -- ./target.rust-run 5000000 Performance counter stats for './target.rust-run 5000000': 187.63 msec task-clock # 0.994 CPUs utilized 20 context-switches # 0.107 K/sec 0 cpu-migrations # 0.000 K/sec 85 page-faults # 0.453 K/sec 864088142 cycles # 4.605 GHz (32.07%) 385088 stalled-cycles-frontend # 0.04% frontend cycles idle (34.18%) 421948 stalled-cycles-backend # 0.05% backend cycles idle (36.31%) 1486120161 instructions # 1.72 insn per cycle # 0.00 stalled cycles per insn (38.44%) 18768109 branches # 100.027 M/sec (40.55%) 29184 branch-misses # 0.16% of all branches (42.36%) 543690464 L1-dcache-loads # 2897.670 M/sec (40.26%) 19859 L1-dcache-load-misses # 0.00% of all L1-dcache hits (38.12%) <not supported> LLC-loads <not supported> LLC-load-misses 141810 L1-icache-loads # 0.756 M/sec (35.99%) 2004 L1-icache-load-misses # 1.41% of all L1-icache hits (33.87%) 78 dTLB-loads # 0.416 K/sec (31.97%) 21 dTLB-load-misses # 26.92% of all dTLB cache hits (31.96%) 0 iTLB-loads # 0.000 K/sec (31.97%) 18 iTLB-load-misses # 0.00% of all iTLB cache hits (31.96%) 0.188802738 seconds time elapsed 0.188263000 seconds user 0.000000000 seconds sys
6:04 AM
$ perf stat -d -d -- ./head.swift-run 5000000 Performance counter stats for './head.swift-run 5000000': 260.12 msec task-clock # 0.996 CPUs utilized 26 context-switches # 0.100 K/sec 0 cpu-migrations # 0.000 K/sec 71 page-faults # 0.273 K/sec 1200493971 cycles # 4.615 GHz (30.86%) 451884 stalled-cycles-frontend # 0.04% frontend cycles idle (32.41%) 132 stalled-cycles-backend # 0.00% backend cycles idle (33.94%) 2904262641 instructions # 2.42 insn per cycle # 0.00 stalled cycles per insn (35.46%) 217096810 branches # 834.616 M/sec (37.00%) 10523 branch-misses # 0.00% of all branches (38.42%) 675633481 L1-dcache-loads # 2597.435 M/sec (38.42%) 10807 L1-dcache-load-misses # 0.00% of all L1-dcache hits (38.42%) <not supported> LLC-loads <not supported> LLC-load-misses 119631 L1-icache-loads # 0.460 M/sec (38.43%) 3361 L1-icache-load-misses # 2.81% of all L1-icache hits (38.41%) 6382 dTLB-loads # 0.025 M/sec (36.86%) 116 dTLB-load-misses # 1.82% of all dTLB cache hits (35.33%) 417 iTLB-loads # 0.002 M/sec (33.80%) 176 iTLB-load-misses # 42.21% of all iTLB cache hits (32.25%) 0.261201137 seconds time elapsed 0.260805000 seconds user 0.000000000 seconds sys
Avatar
omochimetaru 1/25/2023 6:19 AM
Rustのシンプルなコードに比べてSwiftの方はだいぶワチャワチャしてるな
Avatar
↑のSwiftソース。だいぶ頑張ってホットパス中のHeapObjectのアロケーションをゼロにした
Avatar
omochimetaru 1/25/2023 6:23 AM
FixedArray5だ
Avatar
この前、 freddi さんか誰かが Twitter に、重めの同期処理を別スレッドに投げて非同期に待ちたいみたいなことを書いていて、結局 withTaskGroup で解決したとツイートしてたのを見てから(探したけどツイートを発見できず)、 withGroupTask はちょっと大掛かりな気がして考えてたんだけど、一番シンプルな方法って↓かな? async let x = { print("foo") // 重めの同期処理 return 42 }() print("bar") print(await x) ↓の順で表示されるから、同期関数でもちゃんと child task として実行されている。 bar foo 42 前はよく let x = await Task.detached { print("foo") // 重めの同期処理 return 42 }.value print(x) としてたけど、これだと unstructured concurrency になってしまってキャンセル伝播しないから、 async let の方が良い気がする。 (edited)
Avatar
omochimetaru 2/11/2023 9:41 AM
Swift ConcurrencyにはCPUハードな処理を書いてはいけないという認識です
9:42 AM
協調的マルチタスクを前提に設計されていて、
9:42 AM
スケジューラが確保してる実スレッド数が有限になっていると思うので
9:43 AM
例えば実スレッド数が4個になるような環境で、
9:43 AM
重いタスクが4つ投げられた結果、
9:43 AM
その他のすぐに終わる非同期処理が全部戻ってこなくなるという問題が起こりうると思う。
9:43 AM
CPUハードな処理が例えばものすごい回数ループするような処理であるならば、
9:43 AM
Task.yield() を呼び出すことで
9:44 AM
一つ一つのPartial Task(suspenstion pointに挟まれる同期部分)が短い実行時間で済むようにできて、これならセーフです (edited)
9:44 AM
APIとして Task.yield が存在するのもこのような状況に対応するためという認識です。 (edited)
Avatar
Avatar
omochimetaru
Swift ConcurrencyにはCPUハードな処理を書いてはいけないという認識です
そうは言っても Data.write とかは存在するわけで、メインスレッドで Data.write を待ちたくないし、別スレッドに逃したいケースはあるのでは?
9:46 AM
それとも、バイトストリームで async に write する API を作るべきってこと?
Avatar
omochimetaru 2/11/2023 9:47 AM
なのでSwift Concurrencyは「別スレッドに逃がす」という意味論ではないということですね 「並行に実行する」とはまた別の議論です
9:47 AM
Data.write ぐらいなら1秒も止まらなそうなので問題ないと思いますけど
9:48 AM
理想は DispatchIO などの非同期IO を asyncでラップすることだと思います。
9:48 AM
もっと長い計算を実行したい(+ yieldを差し込めない)なら、Swift Concurrencyでは対応できないので、
9:48 AM
DispatchQueueとかNSThreadとか、(Swift concurrencyではない)他のAPIを使う必要があると思います (edited)
9:49 AM
ただそれをラップしてasync-awaitで待機するのは問題ないです。
Avatar
程度問題であって、0.1秒でもメインスレッドのブロックは許容できないけど、0.1秒の同期処理を並行にchild taskに実行させるのは意味があると思う。
Avatar
Avatar
koher
程度問題であって、0.1秒でもメインスレッドのブロックは許容できないけど、0.1秒の同期処理を並行にchild taskに実行させるのは意味があると思う。
omochimetaru 2/11/2023 9:49 AM
いや、僕が言ってるのは程度問題ではないですね
9:49 AM
「逃がす先が埋まってしまう」と
Avatar
はい、それは理解しています。
Avatar
omochimetaru 2/11/2023 9:49 AM
意味的には並行に動かしたいその他の小粒なタスクが、全部詰まってしまって全く進まないという事故がありえる。
Avatar
なので、0.1秒くらいのケースであれば、 child taskに逃したいケースはあって、その場合に↑に書いたようなやり方が役立つことがあると思います。
9:50 AM
その場合にどのように一番シンプルに記述できるかという話。
Avatar
omochimetaru 2/11/2023 9:50 AM
はい、それは正しい用法だと思います。メインスレッドは(Swift conrreuncyでは許容できる停止時間である)0.1秒とかでも嫌ですからね。 (edited)
Avatar
Avatar
koher
その場合にどのように一番シンプルに記述できるかという話。
omochimetaru 2/11/2023 9:51 AM
はい、本題とそれてるのはわかってるんですが、そのツイッターの話題を見た時にはスルーしちゃったんで一応書いときました。本題に戻りましょう。
9:52 AM
これ書かないで本題だけ進めちゃうと、やっちゃいけない場合の条件があることが知られずに結論だけ拡散するのが心配で・・・
Avatar
なるほど。了解です。
Avatar
omochimetaru 2/11/2023 9:54 AM
async let x = { // (1) print("foo") // 重めの同期処理 return 42 }() ↑この書き方なんですけど、(1)が「メインスレッドに投入されない」保証はあるんですかね?
Avatar
その他のすぐに終わる非同期処理が全部戻ってこなくなるという問題が起こりうる
この問題は、標準ライブラリや Foundation が提供する重めの API はすべて async で細切れにして提供されるようになった上で、自前のループの中では適切に Task.yield を挟むというのをみんなが意識しないとですね。
Avatar
omochimetaru 2/11/2023 9:55 AM
withTaskGroup は動的なN個のためのAPIで、async let は定数個の場合のAPIなので、今回1件なのであれば withTaskGroupasync let に書き換える事自体は全く正しい改善だと思うのですが。
Avatar
Avatar
koher
その他のすぐに終わる非同期処理が全部戻ってこなくなるという問題が起こりうる
この問題は、標準ライブラリや Foundation が提供する重めの API はすべて async で細切れにして提供されるようになった上で、自前のループの中では適切に Task.yield を挟むというのをみんなが意識しないとですね。
omochimetaru 2/11/2023 9:56 AM
そうですね。ちなみに随分昔にasync/awaitを導入したC#のwindowsプログラミングでは、そのタイミングで全く同じ議論があって、すべてのファイルIOとかもasync版が用意されてました。で、50ms以上かかる同期ポイントは作るな、ってガイドラインも出してました。
Avatar
Avatar
omochimetaru
async let x = { // (1) print("foo") // 重めの同期処理 return 42 }() ↑この書き方なんですけど、(1)が「メインスレッドに投入されない」保証はあるんですかね?
メインスレッドしかない環境だとだめだと思いますが、 child task は並行に実行されることを想定されているので、空いてるスレッドがあれば別スレッドで実行されないかな?
Avatar
omochimetaru 2/11/2023 9:56 AM
そのへん徹底的に整理されたWindows RTのライブラリキットが揃っていた。
Avatar
Avatar
koher
メインスレッドしかない環境だとだめだと思いますが、 child task は並行に実行されることを想定されているので、空いてるスレッドがあれば別スレッドで実行されないかな?
omochimetaru 2/11/2023 9:58 AM
そんな気もするんですけど。 Task.detachedと違ってコンテキストが引き継がれますよね。 Actorのメソッドの中とかだったらどうなるんだろう。
Avatar
child task は actor context は引き継がないんじゃないかな?
Avatar
child task は並行に実行されることを想定されている
例えばさっき言ったような前提(全てのAPIが、短いかasyncになっている)が満たされている場合は、async let の右辺側自体が同じメインスレッドに戻ってきても問題ないんですよ。
Avatar
import Foundation @MainActor func main() async { print(Thread.current.isMainThread) async let x = { print("foo", Thread.current.isMainThread) // 重めの同期処理 return 42 }() print("bar") print(await x) } await main() true bar foo false 42 (edited)
Avatar
制御として「並行に複数開始して、全ての終了を待つ」事と、その個別の処理がどのスレッドにあるかは別の話だから。
Avatar
メインスレッドで実行されないことは保証できないけど、 actor context を引き継いでいたら必ずメインスレッドで実行されるはずだから、 actor context は引き継いでなさそう。
Avatar
https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md ↑どっかに書いてあるかもしれないけどデカすぎてあたりが付かない・・・ (edited)
Avatar
Avatar
koher
import Foundation @MainActor func main() async { print(Thread.current.isMainThread) async let x = { print("foo", Thread.current.isMainThread) // 重めの同期処理 return 42 }() print("bar") print(await x) } await main() true bar foo false 42 (edited)
なるほど・・・なんか処理をバラ撒くようのスレッドに行かされてる感じはしますね。 僕がiOS開発でやってみたときもデバッガで見る限りはそんな感じだった。
10:10 AM
実際の挙動を観察する限りは良さそうなんですけど個人的にはこれで大丈夫と言い切るための根拠が欲しい。
Avatar
Avatar
omochimetaru
そうですね。ちなみに随分昔にasync/awaitを導入したC#のwindowsプログラミングでは、そのタイミングで全く同じ議論があって、すべてのファイルIOとかもasync版が用意されてました。で、50ms以上かかる同期ポイントは作るな、ってガイドラインも出してました。
Erlangの軽量プロセスとかだと実スレッドから切り離されていて、うまくスケジューリングして実行されるから、そういう仕組みだと重めの同期処理の問題は起こらないかも。その分オーバーヘッドがありそうではあるけど。 https://ubiteku.oinker.me/2016/08/09/how-do-erlang-microprocesses-work-internally/
Avatar
Avatar
koher
Erlangの軽量プロセスとかだと実スレッドから切り離されていて、うまくスケジューリングして実行されるから、そういう仕組みだと重めの同期処理の問題は起こらないかも。その分オーバーヘッドがありそうではあるけど。 https://ubiteku.oinker.me/2016/08/09/how-do-erlang-microprocesses-work-internally/
おお、erlangはプリエンプティブなんですね。
10:12 AM
多分コードがerlang VMで実行されるから、VM上の命令の途中でスイッチしちゃえるように作れるんでしょうね。
10:13 AM
この記事にもあるように、 プリエンプティブ or 協調的 って言葉で区別すると良いんですね。 (edited)
Avatar
gorutine は時間見て別スレッドに移されたりするんですっけ
10:14 AM
仕組みがどう変わったんだろう 先のページを見てみると、go1.14ではシステムシグナルに基づく非同期プリエンプションスケジューリングが導入されたと書いてあります。なるほどさっぱりわからない。ただ、少なくともgoroutine=スレッドになったわけではなさそうです。
10:14 AM
パッとぐぐったらこんなのが出てきた。
10:15 AM
「システムシグナルに基づく」だから、VMの命令で切ってるんじゃなくて、OSのシグナルの仕組みを使って割り込むことでプリエンプションしてるようですね。 (edited)
naruhodo 1
Avatar
Avatar
omochimetaru
実際の挙動を観察する限りは良さそうなんですけど個人的にはこれで大丈夫と言い切るための根拠が欲しい。
確実にメインスレッドで実行されないことを保証したいとして、これまでだと DispatchQueue.global().async とかだとその保証はあったのかな?
Avatar
Avatar
koher
確実にメインスレッドで実行されないことを保証したいとして、これまでだと DispatchQueue.global().async とかだとその保証はあったのかな?
あるはず。DispatchQueueは全てのQueueに対して serial / parallel のどちらかがそもそも設定されていて、
10:16 AM
DispatchQueue.global はシステムが用意したparallel queueを返すって明記されてるんですよ
10:17 AM
で、parallel queue は、2連続で async を呼び出して処理を投入した時、その前後順も無視されるんですよね 同時に走る
10:18 AM
語としては serial / parallel じゃなくて serial / concurrency だった。 https://developer.apple.com/documentation/dispatch/dispatchqueue
👀 1
Avatar
でもそれって serial queue より条件が弱いだけで、 parallel queue が環境によって serial queue で実装されていてはいけないわけじゃないんじゃないかな?
10:20 AM
スレッドが一つしかない環境なら、 DispatchQueue.global().async もメインスレッドで実行されるのでは?
Avatar
When designing tasks for concurrent execution, do not call methods that block the current thread of execution. When a task scheduled by a concurrent dispatch queue blocks a thread, the system creates additional threads to run other queued concurrent tasks. If too many tasks block, the system may run out of threads for your app.
10:22 AM
1文目「現在のスレッドの実行をブロックするメソッドを呼ぶな」って書いてある・・・?
10:22 AM
2文目のほうが実感としてはあって、DispatchQueueシステムは、詰まってたら新しいスレッド立ち上げてでも並列実行するんですよね。(ので、現実的な実感としては詰まりは遭遇しない (edited)
10:23 AM
ただ3文目で言ってるのは、スレッドを使い果たす(run out)可能性がある、という事で、そうすると同じですね。
10:25 AM
DispatchQueueでもスレッド生成による並列化は上限があるからブロッキングが長い処理を大量に発行したら、全部の処理用のスレッドが止まっちゃって、短い処理も進まない状況が生じるのかも (edited)
Avatar
Avatar
koher
スレッドが一つしかない環境なら、 DispatchQueue.global().async もメインスレッドで実行されるのでは?
「スレッドが一つしか無い環境」が、現代OSの無い組み込み機器か、WASMぐらいしか思い当たらないので、Dispatchが実装されたタイミングだとそんな環境はないって感じだと思いますけど・・・ (edited)
10:28 AM
最近だとむしろWASMの事積極的に考えておく必要がありそうだから悩ましいな。
10:29 AM
WASMだとスレッド1個しかないですね、ほんとに。
Avatar
ほんとに細切れにしないと UI が固まっちゃうね。
Avatar
そういえば、nodejsも最初はそうですね、最近は知らないですが
10:30 AM
あれもスレッドを増やさずに非同期イベントベースにしたほうがパフォーマンスがスケールするっていうところが出発点のシステムで
10:30 AM
ファイルIOとかも全部何もかも非同期版が最初からありましたね
10:31 AM
まあそれが、async/awaitが無い世代のJSで提供されてたからすごいけど。 (edited)
Avatar
child task が同じスレッドで実行されるリスクは、 DispatchQueue の場合と同じくらいにならないかなぁ。明確にドキュメントされてないのと、スレッド新しく作らない点が違い?
Avatar
Avatar
koher
child task が同じスレッドで実行されるリスクは、 DispatchQueue の場合と同じくらいにならないかなぁ。明確にドキュメントされてないのと、スレッド新しく作らない点が違い?
そうですね。 「ドキュメントされてない」←こっちは3%ぐらい気になっていて 「スレッド新しく作らない」←こっちが97%ですね。
Avatar
Avatar
omochimetaru
まあそれが、async/awaitが無い世代のJSで提供されてたからすごいけど。 (edited)
コールバックヘル😇
Avatar
DispatchQueueはなんだかんだかなりたくさんスレッド作るんですよね
10:32 AM
run outするのはほんとに1000とかのOS(が割り当てたプロセスに対する)上限だと思います
10:32 AM
swift concurrencyは最初から強気に(CPUコアに応じた)8とかで固定してそうなので (edited)
10:33 AM
お行儀の悪いコードを書いたときに実際にスレッドが全部詰まる可能性があると思ってます
10:33 AM
そのへんの話は thread explosion って話があって
10:34 AM
Dispatch Queueのアプローチは、たとえ1000スレッドまでスケールしたとしても
10:34 AM
それはそれでthread explosion 問題があるんですよね
10:34 AM
物理的には4とか8でしか並列実行できないので、1000とかあると、スレッドにCPUを割り当てるためのスイッチングコストが無駄にかかりすぎる
10:34 AM
あとメモリもかなり食います(スレッドごとに数MBのスタックメモリ領域を事前確保するので) (edited)
10:35 AM
Swift concurrencyはthread explosionないように最適なスレッド数しか最初から用意しないよってWWDC動画でいってました
Avatar
それはそれで詰まっちゃうのもきついけどなぁ。
Avatar
Avatar
koher
それはそれで詰まっちゃうのもきついけどなぁ。
言語がasync/awaitなら、詰まる関数を無くせる、ってところが出発点ですね。
Avatar
でも、たとえば sort とかでも n が増えたら詰まるよ?
Avatar
だから本当は C# や NodeJSがやったように、APIを全部非同期版を用意しないといけないんですよ。
10:37 AM
Foundationがそのままなのが問題です。
Avatar
特にライブラリを作ってるときとか、利用者がどんな n で利用するかわからないので、仮に async 版の sort があったとしても、どっち使うべきか判断できない。詰まらないときは async 版使うの効率悪いし。
Avatar
Avatar
koher
でも、たとえば sort とかでも n が増えたら詰まるよ?
50msかかるソートってなかなか行かないんじゃないかなあ
Avatar
O(n log n) はともかく、 O(n^2) のアルゴリズムとかもあるわけで。
Avatar
あれですね、
10:38 AM
今話しを混ぜじゃってるけど
Avatar
O(n log n)でもn=1億とかだと50msで済まなそうだけど。 (edited)
Avatar
「長く時間がかかるので待機したい」タスク(async化されてるかどうかはいったん置いといて)と 「常にすぐに反応してほしいUIなどのたくさんの小粒な処理」があって
10:39 AM
これが、前者によってシステムが詰まって、後者が動かないことが問題なのであって
10:39 AM
例えば実スレッドが8つあるときに、後者のために守られてるスレッドが1個あれば
10:39 AM
現実的な問題は起きないですね
Avatar
そうですね。 iOS のメインスレッドはそうなってるんじゃないかなぁ。
Avatar
前者のために7つのスレッドを割り当てていたとして、
10:40 AM
仮に10個のタスクがあったら、3こははみ出るから「全く着手されない」ことになってしまうわけだけど
10:41 AM
「長く時間がかかるので待機したい」タスクはそもそも、「まだ着手されていない」としてもアプリケーションとしては問題ないですね
Avatar
MainActor context でない限りメインスレッドに投入されないのであれば、 iOS アプリでは重めの同期処理を投げても現実的にはあまり問題にはならなさそう。
Avatar
Imagine there's a function which does a large amount of work on the CPU. We want to optimize it by splitting the work across two cores; so now the function creates a new thread, does half the work in each thread, and then has its original thread wait for the new thread to finish. (In a more modern system, the function might add a task to a global thread pool, but the basic concept is the same.) There is a relationship between the work done by these two threads, but the system doesn't know about it. That makes it much harder to solve systemic problems.
Motivationセクションにそれっぽい話は出てくるんだけどな、もっかいザッと見したけどいまいち実行計画についての記述が見つけられない
Avatar
Avatar
omochimetaru
Foundationがそのままなのが問題です。
これめっちゃ感じます Data.writeみたいなお手軽なやつにasync版がないからどうやってawaitしようか悩みが発生する
Avatar
少なくとも メインスレッドはMain actorに掌握されているから、後はTaskGroupの投げ先がどこなのか、というハッキリした記述があれば、メインスレッドを追い詰めることはないことは言えるんだけど。
10:57 AM
実験結果ではそうなってますけどね。それでOK,としても良さそう。 後から挙動変えたら、あらゆるアプリがOSアプデ後にメインスレッドがカクカクになっちゃうからApple的にやれないだろうしw (edited)
😅 1
Avatar
Apple過去にメインスレッドで呼ばれてたコールバックをバックグラウンドに変更したりするのでやりかねない…
😨 1
Avatar
Avatar
Iceman
これめっちゃ感じます Data.writeみたいなお手軽なやつにasync版がないからどうやってawaitしようか悩みが発生する
そうですよねえ
10:58 AM
あと、iOSはいいとして、サーバーサイドが問題なんですよね
10:59 AM
メインが一個あるわけじゃなくて、
10:59 AM
HTTPリクエストを受けてそれに応答する、めっちゃ並列するやつら、これを守らないといけない
10:59 AM
「長く時間がかかるので待機したいタスク」と「常にすぐに反応してほしいUIなどのたくさんの小粒な処理」の個数対応関係が違う。
11:00 AM
Vaporだったら前者のために ThreadPool があって 後者のために EventLoop があって分けられているのでプログラマがコントロール可能。
11:01 AM
まあ、async/await版においても 前者は ThreadPool に明示的に逃せばいいっちゃいいが、swift concurrencyで完結できてないのはダサいよな。
Avatar
今自分でグローバルアクター作れるんでしたっけ
11:03 AM
作れるならプロセス単位ではあるけどタスク種類ごとのスレッドプールを用意できそう
Avatar
@globalActor で作れたと思う
11:03 AM
で、そのactorのなかで executor をオーバライドできるんじゃなかったかな。
Avatar
おお。
Avatar
なるほど。たしかにそうやって自前でやればいいのか。
Avatar
Avatar
koher
MainActor context でない限りメインスレッドに投入されないのであれば、 iOS アプリでは重めの同期処理を投げても現実的にはあまり問題にはならなさそう。
現実的には処理の数や重さのたかが知れてて、適当に投げても問題にならなそうですよね。だから詰まりそうなコード見かけても自分に関係なければスルーしてます
Avatar
だいたい問題にならなそうだけど潜在的に問題があるパターンをみんながなんとなく共有していって当たり前になったころに、特殊な状況の人がその罠を踏むの怖い (edited)
Avatar
みんながなんとなく共有していって当たり前に
確かにこのパターンは嬉しくないですね…
Avatar
Avatar
Iceman
現実的には処理の数や重さのたかが知れてて、適当に投げても問題にならなそうですよね。だから詰まりそうなコード見かけても自分に関係なければスルーしてます
それもなんですが、メインスレッドに投入されないことさえわかっていれば、残りが詰まっても UI がフリーズすることはないので、単に非同期処理を待っている状態としてアプリユーザーには見えるからマシかなと。
Avatar
Avatar
koher
それもなんですが、メインスレッドに投入されないことさえわかっていれば、残りが詰まっても UI がフリーズすることはないので、単に非同期処理を待っている状態としてアプリユーザーには見えるからマシかなと。
問題があるとすれば、actor を使って ViewModel を書いたりするアーキテクチャでやってたりする場合ですかね。
11:12 AM
UIを駆動するロジックがMain Actor 以外 でも走るように作っていた場合。
11:13 AM
シンプルにSwiftUIの素直なやり方だったら大丈夫そう。
Avatar
Avatar
koher
それもなんですが、メインスレッドに投入されないことさえわかっていれば、残りが詰まっても UI がフリーズすることはないので、単に非同期処理を待っている状態としてアプリユーザーには見えるからマシかなと。
タスク優先度すら不適切に管理されてて関係のないバックグラウンドタスク待ちでローディングをひたすら見せ続けらるパターンもあるので、最悪ケースまで考えるとやっぱり回避したいですね
😄 1
11:13 AM
ありそうなのが画像の読み込みとか?
11:15 AM
リスト中画像リサイズ処理群の最後にローディング表示解除のタスクが積まれてたら悲惨になりそう
Avatar
画像リサイズ処理がCPU食ってて、リスト要素だからNが多くてスレッド食いつぶして、ってことか。
Avatar
Avatar
omochimetaru
UIを駆動するロジックがMain Actor 以外 でも走るように作っていた場合。
これは、 SwiftUI は ObservableObjectobjectWillChange がメインスレッド以外でトリガーされるのを禁止しているはずなので大丈夫そう。
Avatar
Avatar
Iceman
リスト中画像リサイズ処理群の最後にローディング表示解除のタスクが積まれてたら悲惨になりそう
そうですねー。そもそも、ローディングインジケータ出して画面触れなくして待たせるのってよくありますけど、それって画面フリーズしてるのと実質変わらないと思うんですよね・・・。
Avatar
Avatar
koher
これは、 SwiftUI は ObservableObjectobjectWillChange がメインスレッド以外でトリガーされるのを禁止しているはずなので大丈夫そう。
SwiftUIをビューだけで使って、自前のactorでMVVMとか凝った事やってる場合を考えてました。
11:19 AM
普通にSwiftUIのObservableObjectでやると無難そうですね (edited)
Avatar
Avatar
omochimetaru
SwiftUIをビューだけで使って、自前のactorでMVVMとか凝った事やってる場合を考えてました。
UIKitにSwiftUIのViewを埋め込むんで外から値を与えるとかそんなイメージですか?SwiftUIオンリーだと再描画をトリガーするのに @StateObject が必要になって、メインスレッド必須だから Main Actor にするしかなさそう。
Avatar
@omochimetaru @tarunon actor ViewModel { var count: Int func run1() { count += 1 // state change Task { let res = await VM2.request() // effect run2(res) // feedback } } private func run2(_ res: Res) { ... } }
12:17 PM
@koher ↑こんな感じで actor でViewModelを作る場合ですね。そうするとこの ViewModel.run1() はMainActorでは実行されないから、処理系が混んでたら止まる。 具体的にどうやってUIKitやSwiftUIに接続するか、とか、実際やってる人がいるかはわかんないです。
Avatar
Avatar
omochimetaru
@koher ↑こんな感じで actor でViewModelを作る場合ですね。そうするとこの ViewModel.run1() はMainActorでは実行されないから、処理系が混んでたら止まる。 具体的にどうやってUIKitやSwiftUIに接続するか、とか、実際やってる人がいるかはわかんないです。
実際iOSアプリで actor を使うこともあるけど、最終的に View に接続するときに @MainActorObservableObject を挟むから大丈夫だと思う。直接は接続できないけど。
12:33 PM
↑のツイートスレッドの、 async を避けるために Task.init にしたことで何が解決されてるのかはよくわからない。
12:34 PM
structured concurrency のツリーが途切れて、キャンセルが伝播しなくなるし、メソッドを async にした方がいいと思う。 (edited)
Avatar
Avatar
koher
実際iOSアプリで actor を使うこともあるけど、最終的に View に接続するときに @MainActorObservableObject を挟むから大丈夫だと思う。直接は接続できないけど。
最終的にMainでも、途中でMainではないactorを経由していると、もし重い処理でスレッドが埋まってたらUIが固まってしまうという話です (edited)
12:38 PM
あーまあ固まるといっても見た目には固まらないですね。
Avatar
Avatar
omochimetaru
最終的にMainでも、途中でMainではないactorを経由していると、もし重い処理でスレッドが埋まってたらUIが固まってしまうという話です (edited)
はい、あくまで、画面が固まってスクロールできなくなるとか、そういうレベルの問題は起こらないという話ですね。
👌 1
12:39 PM
5秒で終わるはずの処理が10分かかる他の処理で埋められていて、10分待たなければならないケースは起こりうると思います。
12:40 PM
(suspension pointを挟まない10分の処理というのはかなり例外的だとは思いますが)
Avatar
今さらの話かもしれませんが、async letはdefaultのglobal executorで実行されるはずです。async letのPRに書いてあります。 By default, child tasks use the global, width-limited, concurrent executor, in the same manner as task group child-tasks do. https://github.com/apple/swift-evolution/blob/main/proposals/0317-async-let.md#proposed-solution (edited)
Avatar
omochimetaru 2/11/2023 6:18 PM
おお、async letとtask group両方いっぺんにわかりますね
t_desudesu 1
Avatar
Concurrencyの話題だとこんなPitchが出てましたね。@MainActorのメソッドをawaitなしで呼べるようにする。noasyncなのでsyncコードからのみ呼び出し可能。 @MainActor func updateUI(_ diffs: [Difference]) { /* ... */ } public extension SingleUpdate { func apply() { generateDiffs(from: rawContent, on: DispatchQueue.main) { diffs in unsafeAssumeOnMainActor { updateUI(diffs) } } } // ... } https://forums.swift.org/t/pitch-unsafe-assume-on-mainactor/63074 実行時に本当にMainActorかのチェックもしてくれるみたいです。 The unsafeAssumeOnMainActor function is a nonisolated, non-async function that accepts a @MainActor closure. First, unsafeAssumeOnMainActor performs a runtime test to see if it has been called on the MainActor. If the assumption was wrong, the program will emit a diagnostic message and can either continue executing the closure or abort execution. (edited)
Avatar
Avatar
shiz
今さらの話かもしれませんが、async letはdefaultのglobal executorで実行されるはずです。async letのPRに書いてあります。 By default, child tasks use the global, width-limited, concurrent executor, in the same manner as task group child-tasks do. https://github.com/apple/swift-evolution/blob/main/proposals/0317-async-let.md#proposed-solution (edited)
ありがとうございます!この前kateiくんと話してて自分で言及したのに完全に忘れてました😂 記憶喪失がやばい・・・。 https://twitter.com/koher/status/1619191759468396545
😆 1
Avatar
Avatar
koher
ありがとうございます!この前kateiくんと話してて自分で言及したのに完全に忘れてました😂 記憶喪失がやばい・・・。 https://twitter.com/koher/status/1619191759468396545
omochimetaru 2/12/2023 4:14 AM
一月も経ってない!w
Avatar
2週間で記憶消えてた😇
3:17 AM
We decided to hold off on this to better figure out how this fits with the macro story and potential static reflection features in the future. We’re actively looking into making this a public package for the time being while we continue to develop these APIs.
🥲 2
Avatar
Kishikawa Katsumi 3/16/2023 3:20 AM
マクロはいろいろ巻き込んでるけどその辺の兼ね合いをうまいことバランスとっていくんだと思ってた。
Avatar
omochimetaru 3/16/2023 5:56 AM
できること結構被ってるなとは思ってたがそうなるのか (edited)
Avatar
omochimetaru 3/16/2023 1:15 PM
Hello Swift community, I have a pitch for you about changing the default meaning for plain protocols. Please share any thoughts, questions or suggestions! Proposal: SE-NNNN Authors: Angela Laar, Holly Borla Review Manager: TBD Status: Awaiting implementation, implemented on main behind the experimental flag -enable-experimental-feature Imp...
1:16 PM
裸のプロトコルをanyじゃなくてsomeにするやつのピッチ
1:17 PM
ソース互換性壊れないって書いてあるんだけど・・・どゆこと? 関数引数の場合ならanyがsomeに変わっても型情報が厳しくなるだけだから壊れないし implicit existential openがあるから従来any Pを渡してた部分も呼び出せないケースもない・・・? マ・・・? (edited)
Avatar
varで再代入してるところは壊れるけど、それ以外は正しいと思う
1:18 PM
let宣言ならイケる
Avatar
omochimetaru 3/16/2023 1:22 PM
再代入はたしかにダメそう anyを使うべき限られた状況が提案書に書いてあって、varとかarray of any Pの例があるな・・・
Avatar
インナークラスがコンパイルエラーになる…
Avatar
omochimetaru 3/16/2023 1:24 PM
Swift 6 will enforce SE-0335 3 for all existential types, blocking the use of plain protocol syntax in any Swift codebase. The change laid out in this proposal will allow such code to compile in the supported positions and improve semantics instead of causing a compiler error.
1:25 PM
6で裸をエラーにする代わりにセマンティックを改善する、っていうけど厳密には壊れるケースがあるよねえ
Avatar
6でガッと色々変えるタイミングならまあって感じはしますね
1:26 PM
壊れるケースはたくさんありそう
Avatar
omochimetaru 3/16/2023 1:26 PM
まあ5.6で警告モードかけていったん裸を一掃して・・・みたいな手順が現実的な想定だろうけど
1:27 PM
そのへんの野良コードとか触るときにはそれがいつの時代の気持ちで書かれたか気にしないといけなくなるなあ
Avatar
警告モードは踏むべきですねぇ
Avatar
omochimetaru 3/16/2023 1:46 PM
手元のプロジェクトは手順を踏めるけどもなあ
1:47 PM
swiftpm packageだったら、 // swift-tools-version: 5.6 で管理できてなんとかなんのかな
1:48 PM
依存先のライブラリはanyのつもりで書かれてるけど依存元のアプリはsomeのつもり、って混在するよね
Avatar
omochimetaru 3/17/2023 2:11 PM
This PR tracks an example of custom actor executor support, as well as updating our AsyncAwait example to clearly annotate (via precondition[Not]OnEventLoop) whether the code in question is executi...
2:12 PM
NIOのカスタムエグゼキュータ対応
2:13 PM
変更としてはEventLoopをSerialExecutorに準拠させておくだけでかなり小さい 例としてactorのinitでEventLoop受け取って設定してる (edited)
Avatar
シンプルで良いですね かわりようなさそうだしこれからこれ意識して書いてこうかな
Avatar
omochimetaru 4/4/2023 5:16 AM
Hi everyone. Thanks to everyone who participated in the review for SE-0392, Custom Actor Executors. The Language Workgroup accepts the proposal in principle, but has decided to return the proposal for revision. There are some relatively minor changes to the proposed API that we would like to see explored in a second round of review: The propo...
5:17 AM
Custom Executor概ねOKだけど微調整 Job は一般的な名前すぎるので ExecutorJob にするらしい
👍🏻 1
Avatar
omochimetaru 4/7/2023 1:21 AM
Swift 5.8 の機能を使った ExistentialAny 対応のための変更、弊プロジェクトだと量が多すぎて心折れた Xcode の提案で HogeProtocol?(any HogeProtocol)? になってくれるのに HogeProtocol!any HogeProtocol! になっちゃって意味が変わるので結局手作業になっちゃう
1:21 AM
それは厳しい・・・ any必須化はツールマイグレーションが簡単だから良いよねって議論だったんだけどやっぱりツールに穴があったか
1:24 AM
ここはマイグレーター動かないと、大きなコードベース持ってたらかなり大変だから厳しそう まあSwift6必須化までに直せばいいのか (edited)
Avatar
Kishikawa Katsumi 4/7/2023 2:43 AM
SwiftRefactorでうまいこと作れないかな。
Avatar
omochimetaru 4/7/2023 3:09 AM
サードパーティで作る手もあるか
3:11 AM
Xcodeの機能のやつはどこに実装されてるんだろう
3:11 AM
コンパイラの中にはない・・・?
Avatar
treastrain / Tanaka.R 4/7/2023 8:45 AM
共有ありがとうございます! このツイートの後、一応 any 付与は完遂したのですが、以下の事象に出くわしました(メモ書き形式で雑ですが……) # Xcode 14.3 ## 正しい提案 - `HogeProtocol` → `any HogeProtocol` - `HogeProtocol?` → `(any HogeProtocol)?` - `as HogeProtocol` → `as (any HogeProtocol)`(`as?`・`as!` も同様) - `HogeProtocol.self` → `(any HogeProtocol).self` - `HogeProtocol.Type` → `any HogeProtocol.Type` ## ビルドできなくなる提案(100% 再現) - `HogeProtocol!` を `any HogeProtocol!` にしてしまう - `HogeProtocol?` は `(any HogeProtocol)?` になってくれるのに…… - `HogeProtocol & FugaProtocol` を `any HogeProtocol & any FugaProtocol` にしてしまう - `any HogeProtocol & FugaProtocol` にしてほしい ## ビルドできなくなる提案(ときどき再現) - `HogeProtocol.self` を `(any HogeProtocol).self` にしてくれないときがあった - `any HogeProtocol.self` にしたときがあった - Array でビルドできなくなるときがある - `let arr = [HogeProtocol]()` が `let arr = [any HogeProtocol]()` に置換されたが、「file contains invalid or unrecognized Swift syntax.」と言われてビルドに失敗することがあった - 一度この状況になると clean したりしてもダメだった - 別なプロジェクト等では発生しない - `let dict = [Key: HogeProtocol]()` が `let dict = [Key: any HogeProtocol]()` に置換されたが、「file contains invalid or unrecognized Swift syntax.」と言われてビルドに失敗することがあった - 一度この状況になると clean したりしてもダメだった - 別なプロジェクト等では発生しない
👏🏻 1
Avatar
最小の再現コードできるものは、xcodeかswiftにフィードバックしていくのが良いかな
Avatar
Avatar
treastrain / Tanaka.R
共有ありがとうございます! このツイートの後、一応 any 付与は完遂したのですが、以下の事象に出くわしました(メモ書き形式で雑ですが……) # Xcode 14.3 ## 正しい提案 - `HogeProtocol` → `any HogeProtocol` - `HogeProtocol?` → `(any HogeProtocol)?` - `as HogeProtocol` → `as (any HogeProtocol)`(`as?`・`as!` も同様) - `HogeProtocol.self` → `(any HogeProtocol).self` - `HogeProtocol.Type` → `any HogeProtocol.Type` ## ビルドできなくなる提案(100% 再現) - `HogeProtocol!` を `any HogeProtocol!` にしてしまう - `HogeProtocol?` は `(any HogeProtocol)?` になってくれるのに…… - `HogeProtocol & FugaProtocol` を `any HogeProtocol & any FugaProtocol` にしてしまう - `any HogeProtocol & FugaProtocol` にしてほしい ## ビルドできなくなる提案(ときどき再現) - `HogeProtocol.self` を `(any HogeProtocol).self` にしてくれないときがあった - `any HogeProtocol.self` にしたときがあった - Array でビルドできなくなるときがある - `let arr = [HogeProtocol]()` が `let arr = [any HogeProtocol]()` に置換されたが、「file contains invalid or unrecognized Swift syntax.」と言われてビルドに失敗することがあった - 一度この状況になると clean したりしてもダメだった - 別なプロジェクト等では発生しない - `let dict = [Key: HogeProtocol]()` が `let dict = [Key: any HogeProtocol]()` に置換されたが、「file contains invalid or unrecognized Swift syntax.」と言われてビルドに失敗することがあった - 一度この状況になると clean したりしてもダメだった - 別なプロジェクト等では発生しない
omochimetaru 4/7/2023 8:53 AM
すごいまとめてて偉い・・・
🙇 1
8:53 AM
複数の課題があるんですね。
😢 1
Avatar
Avatar
tarunon
最小の再現コードできるものは、xcodeかswiftにフィードバックしていくのが良いかな
omochimetaru 4/7/2023 8:54 AM
コンパイラ内部にあるならswiftで良かったんだけどそれがよくわかんないんだよなー Xcode固有機能なら、フィードバックアシスタントでXcodeの問題として報告するのが正しそうではある(が、見てくれないんだよなあ、あれ)
Avatar
omochimetaru 4/7/2023 10:58 PM
@treastrain / Tanaka.R この any を自動で付けるのってXcodeにリファクタリングメニュー(?)があるのでしょうか? それとも、コンパイルした後個別のエラーとして表示されて、FixItボタンを一個ずつ(?)押していますか?
Avatar
omochimetaru 4/7/2023 11:13 PM
フォーラムやコンパイラソースからマイグレーター関係の話題や実装を探しているんですが見当たらず・・・
11:14 PM
The old existential type syntax will continue to be supported under the Swift 5 language mode, and the transition to the new syntax is mechanical, so it can be performed automatically by a migrator.
any 付けるのは機械的だからマイグレーターで自動でできるよって仕様書には書いてある。 https://github.com/apple/swift-evolution/blob/main/proposals/0335-existential-any.md
(edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0335-existential-any.md at main · apple/swift-evolution
Avatar
Avatar
omochimetaru
@treastrain / Tanaka.R この any を自動で付けるのってXcodeにリファクタリングメニュー(?)があるのでしょうか? それとも、コンパイルした後個別のエラーとして表示されて、FixItボタンを一個ずつ(?)押していますか?
treastrain / Tanaka.R 4/8/2023 2:06 AM
Xcode プロジェクトないし Package.swift で enable upcoming feature "ExistentialAny" を設定します。 はじめ、Xcode の「Edit」>「Convert…」>「To Current Swift Syntax」を使って一発でできるかなと思い試したのですが、エラーとなってしまって変換できませんでした(エラー表示の文面は忘れてしまいました……)。 そのため、一度ビルドをしてコンパイルエラーにさせた後、「Editor」>「Fix all issues(Cmd + Ctrl + Option + F)」を何度も押し、その結果が先述のまとめになります。
Avatar
omochimetaru 4/8/2023 2:18 AM
ありがとうございます。 ということは専用のマイグレーターが実装されてるわけではなく、 コンパイラの診断エラーとそれに付随するFixItをXcodeから叩いてるだけなのかも。 その線で調べてみます。 (edited)
🙇 1
Avatar
omochimetaru 4/8/2023 2:25 AM
診断メッセージ c++ ERROR(existential_requires_any,none, "use of %select{protocol |}2%0 as a type must be written %1", (Type, Type, bool)) https://github.com/apple/swift/blob/main/include/swift/AST/DiagnosticsSema.def#L5159-L5161
2:26 AM
any不足のエラーその1 any付けるfixitを構築してる c++ std::string fix; llvm::raw_string_ostream OS(fix); if (needsParens) OS << "("; ExistentialTypeRepr existential(SourceLoc(), replaceRepr); existential.print(OS); if (needsParens) OS << ")"; if (auto *proto = dyn_cast_or_null<ProtocolDecl>(T->getBoundDecl())) { if (proto->existentialRequiresAny() && !Ctx.LangOpts.hasFeature(Feature::ImplicitSome)) { Ctx.Diags.diagnose(T->getNameLoc(), diag::existential_requires_any, proto->getDeclaredInterfaceType(), proto->getDeclaredExistentialType(), /*isAlias=*/false) .fixItReplace(replaceRepr->getSourceRange(), fix); } } https://github.com/apple/swift/blob/1b6d160c5ce9b55cf82bd4ee0df51774d0410e03/lib/Sema/TypeCheckType.cpp#L5201 (edited)
2:31 AM
any不足のエラーその2 こっちはfixitが無い・・・? c++ auto parameterized = ParameterizedProtocolType::get(ctx, protoType, argTys); diags.diagnose(loc, diag::existential_requires_any, parameterized, ExistentialType::get(parameterized), /*isAlias=*/isa<TypeAliasType>(type.getPointer())); https://github.com/apple/swift/blob/1b6d160c5ce9b55cf82bd4ee0df51774d0410e03/lib/Sema/TypeCheckType.cpp#L778-L785
2:32 AM
丸括弧が追加されるパターンかどうかの判定 c++ needsParens = existentialNeedsParens(*parentIt);
2:33 AM
c++ bool existentialNeedsParens(TypeRepr *parent) { switch (parent->getKind()) { case TypeReprKind::Optional: case TypeReprKind::Protocol: return true; case TypeReprKind::Metatype: case TypeReprKind::Attributed: case TypeReprKind::Error: case TypeReprKind::Function: case TypeReprKind::Ownership: case TypeReprKind::Composition: case TypeReprKind::OpaqueReturn: case TypeReprKind::NamedOpaqueReturn: case TypeReprKind::Existential: case TypeReprKind::SimpleIdent: case TypeReprKind::GenericIdent: case TypeReprKind::Member: case TypeReprKind::Dictionary: case TypeReprKind::ImplicitlyUnwrappedOptional: case TypeReprKind::Tuple: case TypeReprKind::Fixed: case TypeReprKind::Array: case TypeReprKind::SILBox: case TypeReprKind::Isolated: case TypeReprKind::Placeholder: case TypeReprKind::CompileTimeConst: case TypeReprKind::Vararg: case TypeReprKind::Pack: case TypeReprKind::PackExpansion: case TypeReprKind::PackElement: return false; } }
2:33 AM
↑これ, case TypeReprKind::ImplicitlyUnwrappedOptional: を上にもってくるだけでなんかうまくいったりしねえかなw (edited)
2:34 AM
case TypeReprKind::Composition: のパターンもあるけどこれはそう簡単な話かどうか微妙だな
2:37 AM
@treastrain / Tanaka.R とりあえず、コンパイラの中に実装されてる診断エラーおよびそのFixItの不具合である事がわかったので、githubのapple/swiftにissueを立てると良いと思います。 100%再現するとしている2つのケースについて、それぞれ別のissueにするのが良いと思います。 1件目については僕でも直せるかもしれない。
👍 1
2:38 AM
ときどき再現系は、確定条件がほしいですねえ
2:39 AM
ただ、「file contains invalid or unrecognized Swift syntax」は特徴的なメッセージなので、再現できなくても調べられるかもしれないし、これも報告しちゃっても良いかも。 (edited)
2:41 AM
「file contains invalid unrecognized Swift syntax」はGitHub全体から検索しても見つからない・・・ Xcode内部にあるメッセージなのかなあ
Avatar
file contains invalid unrecognized Swift syntax は swift-format のメッセージ(だった)っぽいです
Avatar
omochimetaru 4/8/2023 3:23 AM
お。今のバージョンには含まれてないから検索で出なかった・・・?
Avatar
omochimetaru 4/8/2023 3:24 AM
@treastrain / Tanaka.R さんの環境でswift-format導入されててXcodeと干渉してエラーメッセージが出てややこしくなってるのかも。
Avatar
Prebuild のスクリプトがエラーになってそれ以上すすんでないのかも
👉 1
Avatar
omochimetaru 4/8/2023 4:46 AM
とりあえず再現確認
Avatar
treastrain / Tanaka.R 4/8/2023 7:10 AM
file contains invalid or unrecognized Swift syntax
すみません… こちら確かに apple/swift-format によるメッセージでした……
Avatar
Avatar
treastrain / Tanaka.R
file contains invalid or unrecognized Swift syntax
すみません… こちら確かに apple/swift-format によるメッセージでした……
omochimetaru 4/8/2023 7:36 AM
swift-formatの実装が古くて [any HogeProtocol]() をパースできなかった、とかですかね
😢 1
Avatar
https://github.com/apple/swift/pull/42277 をみた感じだと,any P?(any P)? にする対応はここの分岐で書かれているので,ここに any P!(any P)! にする対応を追加する必要があるのかもしれないですね. https://github.com/apple/swift/blob/c7766763e8ef7b0425c95c8c688f34fcaa884f26/lib/Sema/TypeCheckType.cpp#L4845-L4857
The compiler now emits the following error for the incorrect any P? syntax, with a fix-it to insert parenthesis: protocol P {} var p: any P? = nil // error: optional 'any' type must be wri...
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
Avatar
omochimetaru
@treastrain / Tanaka.R とりあえず、コンパイラの中に実装されてる診断エラーおよびそのFixItの不具合である事がわかったので、githubのapple/swiftにissueを立てると良いと思います。 100%再現するとしている2つのケースについて、それぞれ別のissueにするのが良いと思います。 1件目については僕でも直せるかもしれない。
treastrain / Tanaka.R 4/8/2023 8:18 AM
ありがとうございます。ひとまず - `HogeProtocol!` を `any HogeProtocol!` にしてしまう - `HogeProtocol?` は `(any HogeProtocol)?` になってくれるのに…… - `HogeProtocol & FugaProtocol` を `any HogeProtocol & any FugaProtocol` にしてしまう - `any HogeProtocol & FugaProtocol` にしてほしい について 2つ issue を書いてみようと思います。
👍 1
Avatar
Avatar
kebo
https://github.com/apple/swift/pull/42277 をみた感じだと,any P?(any P)? にする対応はここの分岐で書かれているので,ここに any P!(any P)! にする対応を追加する必要があるのかもしれないですね. https://github.com/apple/swift/blob/c7766763e8ef7b0425c95c8c688f34fcaa884f26/lib/Sema/TypeCheckType.cpp#L4845-L4857
omochimetaru 4/8/2023 8:25 AM
そっちでもいいですが、 P?(any P)? にしてるこちらを改良して P!(any P)! にする機能も追加したほうが一手短くて良いと思います https://discord.com/channels/291054398077927425/306995750418513920/1094085905586855937 (edited)
t_naruhodo 1
Avatar
Avatar
treastrain / Tanaka.R
ありがとうございます。ひとまず - `HogeProtocol!` を `any HogeProtocol!` にしてしまう - `HogeProtocol?` は `(any HogeProtocol)?` になってくれるのに…… - `HogeProtocol & FugaProtocol` を `any HogeProtocol & any FugaProtocol` にしてしまう - `any HogeProtocol & FugaProtocol` にしてほしい について 2つ issue を書いてみようと思います。
treastrain / Tanaka.R 4/8/2023 8:54 AM
前者のほう、apple/swift に issue を作りました The suggested fix for the existential types with implicit unwrapping is incorrect when enable upcoming featureExistentialAny · Issue #65026 · apple/swift https://github.com/apple/swift/issues/65026
Description In Swift 5.8, SE-0335 "Introduce existential any" can be enabled by SE-0362 "Piecemeal adoption of upcoming language improvements". In that case, if the existential ...
❤️ 5
👍 2
Avatar
Avatar
treastrain / Tanaka.R
ありがとうございます。ひとまず - `HogeProtocol!` を `any HogeProtocol!` にしてしまう - `HogeProtocol?` は `(any HogeProtocol)?` になってくれるのに…… - `HogeProtocol & FugaProtocol` を `any HogeProtocol & any FugaProtocol` にしてしまう - `any HogeProtocol & FugaProtocol` にしてほしい について 2つ issue を書いてみようと思います。
treastrain / Tanaka.R 4/8/2023 1:25 PM
こちらの後者の方も作りました (2つ以上の protocol や class を & で繋ぐことを "Protocol Composition Type" というんですね… 知りませんでした) The suggested fix for the protocol composition type is incorrect when enable upcoming featureExistentialAny · Issue #65027 · apple/swift https://github.com/apple/swift/issues/65027
Description In Swift 5.8, SE-0335 "Introduce existential any" can be enabled by SE-0362 "Piecemeal adoption of upcoming language improvements". In that case, if the existential ...
👍 3
Avatar
そういえばこれ、グローバルアクターのexecutorを取り出すことについては書かれてるけど差し替えることについては書かれてなさそうですね。テストで同期的にexecutor内のJobを進めたいという需要は解決しないのかも?
Avatar
omochimetaru 4/8/2023 4:12 PM
あーたしかに それはまだ裏APIのままだね
Avatar
テストしたい物体が普通のactorなら差し替えられるけど、MainActorなclassとかだと辛そう、というよりMainActorを使わないほうがいいという選択にもなりそう
4:15 PM
と思ったら一応Future Directionsに上書きについて書いてありました。
4:16 PM
とりあえずまだっぽい
Avatar
Avatar
Iceman
と思ったら一応Future Directionsに上書きについて書いてありました。
omochimetaru 4/8/2023 4:16 PM
そこで触れてるんや 読み飛ばしてた
Avatar
ObservationがReviewに入りましたね。 https://forums.swift.org/t/se-0395-observability/64342
Hi Swift community, The review of SE-0395: Observability begins now and runs through April 24, 2023. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager. When emailing the review manager direct...
Avatar
おお、読む
👍🏻 1
Avatar
MainActor.ActorType なんだこれ
11:12 PM
valuesはchangesを使ったショートカットなんだろうか
11:13 PM
changesが指定したアクターの型パラメータでアイソレートされるという部分も具体的にどういう挙動や実装方法なのかイメージつかん
11:14 PM
たぶんこれによってfor awaitしててもメインスレッド反映がチラついて遅れたりしない、って意図なんだろうけど、、
11:18 PM
おお、、、マクロ実行時に型推論結果取りたいねって将来の話が出てきてる
👍🏻 1
Avatar
changesが指定したアクターの型パラメータでアイソレートされるという部分も具体的にどういう挙動や実装方法なのかイメージつかん たぶんこれによってfor awaitしててもメインスレッド反映がチラついて遅れたりしない、って意図なんだろうけど、、
僕もそこらへんがどういうことなんだろうと悩んでますw StateMachineみたいなもので状態管理をしていて、isolatedパラメータに渡されたactorでアイソレートしているというところまではなんとなくわかったのですが、あまりイメージがつかないんですよね... https://github.com/apple/swift/blob/main/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift#L427 https://github.com/apple/swift/blob/main/stdlib/public/Observation/Sources/Observation/ObservationRegistrarStateMachine.swift
(edited)
Avatar
おお、isolateパラメータにジェネリックに渡すのか
12:54 AM
isolatedはアクター境界ですが
12:54 AM
現在のアクターと同じなら同期的に呼び出すので
12:54 AM
たしかにasync処理が一周delayするのを避けられそうです
t_naruhodo 1
12:55 AM
現在のアクターと違う場合は、非同期投入になる
12:58 AM
withTrackingのonChangeはなんでオートクロージャでわざわざ関数を返す関数にしてるんや
Avatar
omochimetaru 4/12/2023 1:07 AM
valuesとchangesよくわからん 同期的に複数回変更された場合に、valuesは一回だけ通知されて、changesは毎回通知される?
1:07 AM
英語むずいから図にしてほしい、、
Avatar
changesは全ての変更値が配列で受け取れて、valuesは最後の変更値だけ出力するのかなと読み取ってました。 ObservedChanges emits values when a change is made and an available suspension point has been met by the isolation. This means that changes can be grouped up transactionally to the boundary of when a given actor is available to run. The ObservedValues asynchronous sequence on the other hand will await a change to values end emit the latest value that is available between the last iteration (or starting point of iteration) and the suspension. changesのグルーピングのタイミングがアイソレーションの中断ごとというところがまだイメージできてないんですよね...
Avatar
omochimetaru 4/12/2023 1:22 AM
public struct ObservedChange<Subject: Observable>: @unchecked Sendable { public func contains(_ member: PartialKeyPath<Subject>) -> Bool } extension ObservedChange where Subject: Sendable { public var subject: Subject { get } } /// An asynchronous sequence of observed changes. public struct ObservedChanges<Subject: Observable, Delivery: Actor>: AsyncSequence { public typealias Element = ObservedChange<Subject> public struct Iterator: AsyncIteratorProtocol { public mutating func next() async -> Element? } public func makeAsyncIterator() -> Iterator } extension ObservedChanges: @unchecked Sendable where Subject: Sendable { } @available(*, unavailable) extension ObservedChanges.Iterator: Sendable { }
1:23 AM
ObservedChangesは、Observable自身が subject から取り出せて、「何が変わったか」が contains(PartialKeyPath) で調べられる?
Avatar
Avatar
shiz
changesは全ての変更値が配列で受け取れて、valuesは最後の変更値だけ出力するのかなと読み取ってました。 ObservedChanges emits values when a change is made and an available suspension point has been met by the isolation. This means that changes can be grouped up transactionally to the boundary of when a given actor is available to run. The ObservedValues asynchronous sequence on the other hand will await a change to values end emit the latest value that is available between the last iteration (or starting point of iteration) and the suspension. changesのグルーピングのタイミングがアイソレーションの中断ごとというところがまだイメージできてないんですよね...
omochimetaru 4/12/2023 1:24 AM
全ての変更値が配列で受け取れて
↑この部分って↑のコードで現されてますかね?
Avatar
Avatar
shiz
changesは全ての変更値が配列で受け取れて、valuesは最後の変更値だけ出力するのかなと読み取ってました。 ObservedChanges emits values when a change is made and an available suspension point has been met by the isolation. This means that changes can be grouped up transactionally to the boundary of when a given actor is available to run. The ObservedValues asynchronous sequence on the other hand will await a change to values end emit the latest value that is available between the last iteration (or starting point of iteration) and the suspension. changesのグルーピングのタイミングがアイソレーションの中断ごとというところがまだイメージできてないんですよね...
omochimetaru 4/12/2023 1:26 AM
「アイソレーションの中断ごと」僕もよくわからないです access とか withMutation のスコープ関数で囲って実現してるような気がしたけど、 これらはプロパティの内側で呼ばれるから無理そうなんですよね どうやってこの「ひとまとめにするグループ」を制御しているんだろう。
Avatar
Avatar
omochimetaru
全ての変更値が配列で受け取れて
↑この部分って↑のコードで現されてますかね?
まだそこまで深掘りできていないんですが、 ObservedChanges.Iterationのnextの中でnextChangeが呼ばれていて、 https://github.com/apple/swift/blob/main/stdlib/public/Observation/Sources/Observation/ObservedChanges.swift#L93 その中でinsertNextChangeが呼ばれて、さらにその中で各Stateによって処理が分かれるのですが、 https://github.com/apple/swift/blob/main/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift#L312 Pending中は値をinsertしていて、 https://github.com/apple/swift/blob/main/stdlib/public/Observation/Sources/Observation/ObservationRegistrarStateMachine.swift#L54 来たるべきタイミングの時にcontinuation.resumeで変更した値を全部emitしているのではないか思っています。 https://github.com/apple/swift/blob/main/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift#L323
Avatar
わいわいでも言った気がするけど、 @StateObject@ObservedObject なくなると Binding が簡単に取れなくなって困らないのかなぁ。 @Observable final class Model { var order: Order? var account: Account? var hasAccount: Bool { return userCredential != nil && account != nil } var favoriteSmoothieIDs: Set<Smoothie.ID> = [] var selectedSmoothieID: Smoothie.ID? var searchString: String = "" var isApplePayEnabled: Bool = true var allRecipesUnlocked: Bool = false var unlockAllRecipesProduct: Product? } struct SmoothieList: View { var smoothies: [Smoothie] var model: Model var listedSmoothies: [Smoothie] { smoothies .filter { $0.matches(model.searchString) } .sorted(by: { $0.title.localizedCompare($1.title) == .orderedAscending }) } var body: some View { List(listedSmoothies) { smoothie in ... } } }
2:04 AM
あと↓がっかりなんだけど、これミスなく手で書くの辛そう・・・。 @Observable マクロががんばってくれたりはしない? extension MyObject { var someComputedProperty: Int { somePrivateProperty + someOtherProperty } nonisolated static func dependencies( of keyPath: PartialKeyPath<Self> ) -> TrackedProperties<Self> { switch keyPath { case \.someComputedProperty: return [\.somePrivateProperty, \.someOtherProperty] default: return [keyPath] } } }
2:04 AM
さすがに無理か。
Avatar
Avatar
shiz
まだそこまで深掘りできていないんですが、 ObservedChanges.Iterationのnextの中でnextChangeが呼ばれていて、 https://github.com/apple/swift/blob/main/stdlib/public/Observation/Sources/Observation/ObservedChanges.swift#L93 その中でinsertNextChangeが呼ばれて、さらにその中で各Stateによって処理が分かれるのですが、 https://github.com/apple/swift/blob/main/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift#L312 Pending中は値をinsertしていて、 https://github.com/apple/swift/blob/main/stdlib/public/Observation/Sources/Observation/ObservationRegistrarStateMachine.swift#L54 来たるべきタイミングの時にcontinuation.resumeで変更した値を全部emitしているのではないか思っています。 https://github.com/apple/swift/blob/main/stdlib/public/Observation/Sources/Observation/ObservationRegistrar.swift#L323
omochimetaru 4/12/2023 2:05 AM
追ってるけどめちゃくちゃ難しいですねこれ 疑問点の答えが全然見えてこない
😅 1
Avatar
Avatar
koher
あと↓がっかりなんだけど、これミスなく手で書くの辛そう・・・。 @Observable マクロががんばってくれたりはしない? extension MyObject { var someComputedProperty: Int { somePrivateProperty + someOtherProperty } nonisolated static func dependencies( of keyPath: PartialKeyPath<Self> ) -> TrackedProperties<Self> { switch keyPath { case \.someComputedProperty: return [\.somePrivateProperty, \.someOtherProperty] default: return [keyPath] } } }
omochimetaru 4/12/2023 2:05 AM
これ原理的にはObservationTrackingを使って自動的に実装できる説がフォーラムにも書かれてましたね (edited)
2:06 AM
ただし部分式が短絡するケースがあるので、依存プロパティが更新された時に(新たな依存が見えてくることがありえるから)またスキャンしないといけない (edited)
2:07 AM
提案書に議論が書いてないけど、自動実装(実行時依存解析)だとパフォーマンスペナルティが大きすぎるからやめたんじゃないかなあ
Avatar
Avatar
omochimetaru
追ってるけどめちゃくちゃ難しいですねこれ 疑問点の答えが全然見えてこない
omochimetaru 4/12/2023 2:08 AM
nextを呼んだ先でscheduleNextChangeでContinuation作って登録して、まあこれで発火可能になることはわかるんですが
2:08 AM
で、発火側は withMutating の中で呼んでる willSet と didSet でなんやかんやして、didSetで、登録されてるObservationをイテレートしているんだけど
2:09 AM
どういう手順で事が起きた場合に、「トランザクション間の複数の変更を一個にまとめる」挙動が生じるのかがわからない
2:09 AM
プロパティを一回書き込んだら (例: foo.a = 3 ) その単位で didSet が起きて発行して終わるような気がする・・・
Avatar
Avatar
omochimetaru
提案書に議論が書いてないけど、自動実装(実行時依存解析)だとパフォーマンスペナルティが大きすぎるからやめたんじゃないかなあ
デフォルト自動実装でパフォーマンスが気になるなら手動実装するとかでもいいから提供してほしいなぁ。
Avatar
omochimetaru 4/12/2023 2:10 AM
そもそも idle, pending, active,がなんなのかわからんし、trackingとかが混ざってるせいでわかりづらすぎうr
Avatar
Avatar
koher
デフォルト自動実装でパフォーマンスが気になるなら手動実装するとかでもいいから提供してほしいなぁ。
omochimetaru 4/12/2023 2:10 AM
デフォルト自動実装の dependencies は、全てのプロパティに依存してる設定でマクロ生成されるようですよ
2:11 AM
言葉が混ざっちゃうな、提案されてる(コンパイル時)自動実装は静的な固定全依存、動的にスキャンする方式はどっか行った (edited)
Avatar
お、そうなのか。それならまだいけそう。 Computed Property を購読するときは removeDuplicates しておけばマシになるかな。
Avatar
Avatar
omochimetaru
デフォルト自動実装の dependencies は、全てのプロパティに依存してる設定でマクロ生成されるようですよ
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0395-observability.md at main · apple/swift-evolution
👀 1
2:13 AM
The generated implementation for the dependencies(of:) requirement creates a list of all of the type's stored properties, and then returns that as the set of dependencies for any computed property. For the PropertyExample type above, that implementation looks like this:
Avatar
これでも一部のプロパティについてだけ自動では我慢できないから dependencies 独自実装しようとすると、それ以外のプロパティも実装しないといけないことになって、自動実装が消えてミス多発しそう・・・。
Avatar
omochimetaru 4/12/2023 2:17 AM
xxxChangesのステート3つだけ見ればよくて、idle/pending/activeで遷移するっぽいな
2:18 AM
これはobservationごとに管理されてて activeのときにdidSetが起きるとcontinuation.resumeで送信されてidleに戻る
2:19 AM
pendingのときにdidSetが起きると「ここまでの変更」にキーが追加される
2:19 AM
pendingってのが変更を継続的に記録して一つにまとめようとしている状態だ (edited)
2:20 AM
idleはresume送信後の初期状態で、ここでdidSetくるとpendingが始まる。
2:21 AM
insertNextChange が idle中に来るとactiveになる pending中に来ると、そこまで集めた変更(があれば)をresume送信してidleになる
2:21 AM
あーわかったぞ
2:23 AM
ObservedChangedはAsyncSequenceだから
2:23 AM
for-await-inで自動でnextが呼ばれるんだけど
2:23 AM
didSetでcontinuationが発火されるとそのnextがElementを返すんだけど
2:24 AM
その後forの中に入って、for本文でasync処理が実行されているまでの間が、idleなんだ
2:25 AM
で、for本文が終わって、またasync sequenceの次の値を読み取る準備ができたタイミングで、 やっとこさ next() が呼ばれるから
2:25 AM
その「次の next() が呼ばれるまでの間」に、発生したdidSetがpending stateとして累積されているんだわ (edited)
2:27 AM
didSetが発生するTaskと、for-awaitしてるTaskが別で並行に動いてるからズレが発生する、これがまとめられるって言ってる
2:28 AM
俺が疑問に思った withMutating のくくりだと毎回リセットされちゃうのではないか、は、同じアクターコンテキスト(Mainなど)においては多分そうで
2:29 AM
全部mainで組んだらプロパティに書き込むたびにイベントが来るんじゃないかな あ、でも送り側もmainでfor-await側もmainはありえないか、デッドロックするわ
2:34 AM
いやできるのか・・・?よくわからなくなってきた
2:35 AM
@MainActor func handleChanges(_ example: ChangesExample) { Task { @MainActor in for await change in example.changes(for: [\.someField, \.someOtherField]) { switch (change.contains(\.someField), change.contains(\.someOtherField)) case (true, true): print("Changed both properties") case (true, false): print("changed integer field") case (false, true): print("changed string field") default: fatalError("this case will never happen") } } } }
2:36 AM
↑これって、handleChangesはメインスレッドで呼ばれつつ、Taskがエンキューされて、 次のメインループでTask本文が実行されて、 example.changes().next が for-await によって呼ばれて・・・
2:37 AM
そうするとこの for-await は、MainActorでisolateされた本文コードだから、 async sequenceからエレメントが来たらMainActorにホップしてから処理されるけれど
2:37 AM
もし、この .next の結果を送信するための Continuationが、MainActorコンテキストなTaskから呼びされた場合は
2:38 AM
async sequenceの値送信側もmain actorで、for-awaitは、main actorからmain actorだからホップ無しで処理が進んで、 結果的に同期的にこのforの本文に入ってくるのかな。
2:38 AM
そうじゃないとUI更新が1フレーム遅れちゃうから困るんだけど。
2:40 AM
なんとなく以前からSwift Concurrencyで Task.init + for-await-in すると、1フレ遅れからは逃れられないように思ってたけど、 ちゃんとやれば大丈夫なんかね?
Avatar
awaitまたぎで1フレ遅れを回避できるのってwithCheckedContinuation系のみなはずなんですが、例外が増えるということなんでしょうかね
Avatar
Avatar
Iceman
awaitまたぎで1フレ遅れを回避できるのってwithCheckedContinuation系のみなはずなんですが、例外が増えるということなんでしょうかね
omochimetaru 4/12/2023 2:51 AM
Avatar
これってscheduleNextChange自体がasync関数なので1フレ遅れ得ませんかね?
2:53 AM
あ、そこでisolatedが効いてくるのか
Avatar
Avatar
Iceman
あ、そこでisolatedが効いてくるのか
omochimetaru 4/12/2023 2:53 AM
isolation: isolated Isolation,
↑これすごい
Avatar
キーワードのシンタックスハイライトがないとわけがわからないw
Avatar
omochimetaru 4/12/2023 2:54 AM
ObservedChanges.nextObservationRegistrar.nextChange (isolated) → ObservationRegistrar.scheduleNextChange (isolated) → withUnsafeContinuation
2:55 AM
ObservedChangesinitisolation: Isolation を受け取る。
Avatar
ちゃんと繋がってるのでasyncだけど同期的に処理されそうな気配ありますね
Avatar
その後forの中に入って、for本文でasync処理が実行されているまでの間が、idleなんだ で、for本文が終わって、またasync sequenceの次の値を読み取る準備ができたタイミングで、やっとこさ next() が呼ばれるからその「次の next() が呼ばれるまでの間」に、発生したdidSetがpending stateとして累積されているんだわ didSetが発生するTaskと、for-awaitしてるTaskが別で並行に動いてるからズレが発生する、これがまとめられるって言ってる
ありがとうございます。どのタイミングでどの状態になるのかを追ってみたもののわからずじまいでした😅
(edited)
Avatar
↑これって、handleChangesはメインスレッドで呼ばれつつ、Taskがエンキューされて
とすると、たとえば、 func viewDidLoad(…) { … handleChanges(example) example.someField = 10 // ここ } の「ここ」の変更は通知されないと思っているのですが、合ってますでしょうか?
Avatar
Avatar
shiz
↑これって、handleChangesはメインスレッドで呼ばれつつ、Taskがエンキューされて
とすると、たとえば、 func viewDidLoad(…) { … handleChanges(example) example.someField = 10 // ここ } の「ここ」の変更は通知されないと思っているのですが、合ってますでしょうか?
されないように思えますね for awaitの直前に改めてexample.someFieldを読んで再描画しておかないといけない? 微妙ですね 何か見落としてるかなあ?
Avatar
Avatar
omochimetaru
されないように思えますね for awaitの直前に改めてexample.someFieldを読んで再描画しておかないといけない? 微妙ですね 何か見落としてるかなあ?
Forumsのスレッドを見ているとそういう挙動なのかなと思っていて(KVOのinitial オプションのようなものがない) https://forums.swift.org/t/se-0395-observability/64342/24 そのために初期値も含めればいいのではみたいな話が出ているのかなと思ってます。(公式で何かinital value含め含められるものが欲しいですが) Task { for await value in chain([object.someProperty].async, object.values(for: \.someProperty)) { // Really important processing of the value } } https://forums.swift.org/t/se-0395-observability/64342/24 (edited)
I remember frequently relying on the initial value option in KVO. I'm surprised that's not coming over. However, I think it might be possible to prepend the initial value by chaining an iterator that emits the current value and then ends to the iterator produced by object.values(for: .someProperty). I think that could look like this using the ...
Avatar
おー鋭い指摘だ そのchainで自分で付け足すイディオムはめんどくさいので無理だw
t_desune 1
Avatar
Ben Cohenさんの書き込みの感じだと普通に修正されそう (edited)
👍🏻 1
Avatar
初期値取得できない問題は解決方法を検討しているようですね。 現状、初期値が失われる可能性がある if a property will be observed and the change in that property only happens once (and never happens again) and the confluence of events is such that the property observation via values(for:) is called asynchronously (e.g. in a Task) the first value could get lost. ただし、 初期値の取得はイテレーションと同じ分離領域で取得する必要がある 初期値が全部のケースで必要というわけではない 初期値を保持することでどこかのライフサイクルに影響を与えるかもしれない といったことを考慮しなければならない、と書かれてました。 https://forums.swift.org/t/se-0395-observability/64342/89
Cycling back to a few points of feedback: There is a slightly inaccurate but founded concern about flickering UI. I think it might be better to phrase that as more so the issue underlying that; the concern is consistency. Which is a very reasonable worry. The point of consistency problems crops up (paraphrasing a few posts by folks) that if a p...
Avatar
Kishikawa Katsumi 4/27/2023 12:15 PM
https://forums.swift.org/t/beta-testers-wanted-get-a-sneak-peek-at-github-s-code-scanning-support-for-swift/64632 GitHubのコードスキャンがもうすぐSwiftに対応するからβテストに協力してほしいって。
👋 Pierre from GitHub here. What’s happening? On June 1 2023, just ahead of WWDC 23, GitHub is adding Swift support to a number of our Advanced Security features: GitHub code scanning support for Swift enters public beta to help open-source and enterprise Swift developers secure their code with actionable security alerts right on your pull re...
👀 2
Avatar
Kishikawa Katsumi 4/27/2023 2:36 PM
手続きがSlackで自己紹介とリンクを貼るっていう方法なんだけど人力で有効にしていってくれるんだろうか。レビューとかもあるっていうしまあ人力でいいのか。
2:39 PM
とりあえず書いてみた。
Avatar
Kishikawa Katsumi 4/27/2023 4:38 PM
返事きたわ。GitHub Actionsセットアップしたら使えそう。
Avatar
omochimetaru 4/29/2023 2:40 AM
/// Returns a URL constructed by appending the given path to self. /// - Parameters: /// - path: The path to add /// - directoryHint: A hint to whether this URL will point to a directory @available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) public func appending<S>(path: S, directoryHint: URL.DirectoryHint = .inferFromPath) -> URL where S : StringProtocol https://forums.swift.org/t/back-from-revision-foundation-url-improvements/54605/28
2:42 AM
この新しい URL.appending() 、 Linux版 Foundation に全然追加されないのなんなんだろ? ソース(なさそう): https://github.com/apple/swift-corelibs-foundation/blob/2d23cf3dc07951ed2b988608d08d7a54cc53b26e/Sources/Foundation/URL.swift#L199 実行結果(なさそう): https://discord.com/channels/291054398077927425/430242233468452865/1101699773775499265 (edited)
Avatar
URL に限らず Foundation の API 変更への追従は基本遅いですよね.Date.now も iOS 15 で使えるようになって swift-corelibs-foundation にも乗って Swift のリリースに乗ったのが Swift 5.8 なので,1 年半遅れて Linux で使えるようになりましたし. https://github.com/apple/swift-corelibs-foundation/pull/4609 (edited)
I've had builds that succeed on macOS fail on Linux because bizarrely, Date.now is only supported on macOS, despite it being equivalent to just calling init(). Easy fix.
Avatar
Avatar
kebo
URL に限らず Foundation の API 変更への追従は基本遅いですよね.Date.now も iOS 15 で使えるようになって swift-corelibs-foundation にも乗って Swift のリリースに乗ったのが Swift 5.8 なので,1 年半遅れて Linux で使えるようになりましたし. https://github.com/apple/swift-corelibs-foundation/pull/4609 (edited)
Date.now の事、知りませんでした。 こんな簡単なやつも実装されないのか。 dannflorさんはAppleの人ではないみたいだし、野良のコントリビューションで対応されたのか・・・ あまりにもやる気ないな・・・
t_desune 1
Avatar
Observationの新しい実装がマージされてましたね。 AsyncSequenceへ準拠した型が消えて、withObservationTrackingを使ってsyncのfor loopでtrackingできるようになったり、個々のプロパティをTrackingから除外する@ObservationIgnoredが追加になったり、色々変更になるようです。 ObservationTrackingという型に@_spi(SwiftUI)がついているのがよくわかってないです😅 https://github.com/apple/swift/pull/65528
This is a draft of a leaner and more focused Observation. It removes some of the features that caused restrictions to the usages of the APIs in favor for leaving those for future development (and p...
👀 1
Avatar
Kishikawa Katsumi 5/10/2023 8:58 AM
@_spiはモジュールプライベートみたいなアクセス制御で普通にImportしても見えなくてImportしたい場合はImportする側で@_spi(SwiftUI) importって書くと見えるやつです。
8:59 AM
要するにモジュール間をまたがって呼び出す必要があるけど一般には公開したくないっていう場合に使います。
t_naruhodo 1
Avatar
いままで予想でしかなかったですが@_spi(SwiftUI)ついてると明確にSwiftUI意識されてることわかって面白いですね
9:02 AM
@_spi つけてimportされた型って再exportされるんでしたっけ?それとも@_implementationOnly相当?
Avatar
Kishikawa Katsumi 5/10/2023 9:06 AM
どうなんだろう。
Avatar
そのままだと公開出来ない /tmp/tmp.7NtbKdeUsR/Sources/Bar/Bar.swift:3:29: error: cannot use struct 'BarPrivate' here; it is an SPI imported from 'Foo' public func reExport(_: Foo.BarPrivate) { ^ Foo.BarPrivate:1:15: note: type declared here public struct BarPrivate { ^ /tmp/tmp.7NtbKdeUsR/Sources/Bar/Bar.swift:3:29: error: cannot use struct 'BarPrivate' here; it is an SPI imported from 'Foo' public func reExport(_: Foo.BarPrivate) { ^ Foo.BarPrivate:1:15: note: type declared here public struct BarPrivate { ^
9:08 AM
が、@_spi(ForBar) を再エクスポートしてる宣言にもつけるとできる (edited)
Avatar
なるほど、じゃあObservationTrackingは完全にユーザが意識しない型なんですね
Avatar
omochimetaru 5/16/2023 2:31 AM
@omochimetaru @tobi462 14.3でビルドできなくなったけど仕様だったので難しすぎるんですよね https://t.co/Bzw5X083rh
2:31 AM
Description I'm getting an error when building the following code with Swift 5.8. This error does not occur in Swift 5.7. protocol P {} struct MyP: P { let elements: [any P] } @resultBuilder st...
2:32 AM
2:32 AM
Swift5.8でResultBuilderの推論が改善された、ってblogでもアナウンスされていたけど、
2:32 AM
実際にはソース互換性が失われているケースがあるらしい・・・
2:33 AM
I am happy to announce that the result builder implementation has been re-worked in Swift 5.8 to greatly improve compile-time performance, code completion results, and diagnostics. The new implementation is now enabled by default on main and release/5.8. The Swift 5.8 result builder implementation enforces stricter type inference that matches th...
👀 1
2:33 AM
このスレッドに詳細が書いてあるらしい
Avatar
コンパイル通らなくなる分には実行時の挙動が勝手に変わることはないから… まだマシ (edited)
Avatar
omochimetaru 5/16/2023 2:38 AM
コンパイル通るけど動作変わるは確かにもっと地獄だけども。。 (edited)
2:39 AM
evolution無しの変更でコンパイルできないリグレッション起きるのこれまで聞いた記憶無い気がする
Avatar
evolution無い内部改善扱いなのかー、それで変わるのはきびしい (edited)
Avatar
omochimetaru 5/31/2023 3:16 PM
swift blogに書いてあったんですけどevolution dashboardでupcoming feature flagによる絞りこみができるらしい。 これ地味な知っ得情報ですね
3:16 PM
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
3:16 PM
右上の旗のアイコン。
3:17 PM
upcoming featureが増えすぎると、把握できなくなってせっかくの移行期間にフラグつけて準備しておくのを忘れる、 という失敗パターンがありそうなので。
3:17 PM
3:18 PM
↑XcodeはGUI提供してあげたらいいと思うけど・・・
3:19 PM
てかSwiftPMも ドット式で補完効かせて書けるようにできそう .target(name: "MyTarget", dependencies:[.fancyLibrary], swiftSettings: [.enableUpcomingFeature(name: “ConciseMagicFile”), .enableUpcomingFeature(name: “BareSlashRegexLiterals”), .enableUpcomingFeature(name: “ExistentialAny”)]) (edited)
3:20 PM
struct UpcomingFeatureName: ExpressibleByStringLiteral { static let conciseMagicFile = UpcomingFeatureName("ConciseMagicFile") (edited)
Avatar
https://github.com/apple/swift/pull/65993 みたいに Evolution にないフラグも入って来る感じなら結局一覧は https://github.com/apple/swift/blob/main/include/swift/Basic/Features.def を見ないとわからなくなっていくんじゃないかなと思うんですがどうなんでしょうね.
Avatar
omochimetaru 5/31/2023 3:58 PM
gwynneさんだ。 これはフラグを追加するevolution必須だと思います。 でもホーリーとドーグのコメント見る限り、今フラグ無いの意図的みたいですね。
Avatar
ここに Evolution にないからみたいな理由が書かれていたら Evolution のところで一覧を見れるようにしていく予定なのかなと思ったんですが,そういうコメントが出てこなかったので別にそういうわけじゃないのかなと思ってました.StrictConcurrency はないとしてもそれと同じでこれまで独立したフラグだったものが upcoming feature flag にコンバートされたりしたら Evolution なしでフラグが追加されるのもありうるのかなと思っちゃいました. (edited)
Avatar
omochimetaru 5/31/2023 4:03 PM
たしかにその論点でのコメントが無いけど、単にその先の話でややこしくなるからスルーしたんだと思いたいなあ・・・
t_naruhodo 1
4:03 PM
↑これとかは、まさに元々専用フラグだったのが、 Acceptの後で feature flag を追加する書類更新が行われているので (edited)
4:04 PM
そういう感じでSEに対応付けてほしいですね
4:06 PM
この話のケースなら↑これに追加されそう。
Avatar
-warn-concurrency 以降の変更が反映されていないですが確かにそれが一番近そうですね.Rust の https://doc.rust-lang.org/unstable-book/ みたいに別ドキュメントが必要になっちゃうのも管理が面倒そうなので Swift Evolution だけで済むようになっていけば確かにその方が良いなとは思います.
Avatar
omochimetaru 5/31/2023 4:12 PM
「Strict concurrency checking」の言及は出てくるけど
4:12 PM
-strict-concurrency は書いてないですよね。
4:13 PM
このフラグってそもそも公式/stableなんだろうか。みんな知ってるけど。
4:13 PM
位置づけがよくわかんない。
Avatar
ExistentialAnyチェックが標準ライブラリのプロトコルで効かない不具合がXcode 15で修正されたので、エラーのおかわりが来ました。Codableとか多用してると結構たくさんエラーになる感じ。
Avatar
omochimetaru 6/16/2023 5:22 AM
((a: A, b: B, …), x: X)というタプルを、(a: A, b: B, …, x: X)に書き換えるのを汎用化したいのですが
5:23 AM
たとえvariadic genericsを使っても、ラベル部分をキャプチャできないから無理、でしょうかね
5:24 AM
また、このタプルは型推論によって出てきて、ユーザーが手で定義しないので、マクロ生成による対応も無理、でしょうかね
Avatar
Observationの導入でエンティティ的な型をクラスにしたくなるモチベーションが生まれてしまったと思うんですが、これまでの値型中心のSwiftと整合性を取るの難しくないですか? ArrayDictionary に入れることを考えると、これまで要素の一つが変更されても全体の変更として検出されてしまっていたのが、 @Observable なクラスを使えば要素単体の変更として検出できて効率的。 これまでも全部 ObservableObject にして ArrayDictionary の要素の変更を直接検出する作戦はあったかもしれないけど、全部 ObservableObject にしちゃうと ObservableObjectObservableObject を保持してるときに、前者(保持してる側)を @StateObject 等で保持しても後者(保持されてる側)の変更を自動的に検出できるわけでなかったのであまり現実的でなかったけど、 Observation を使えば @StateObject とかなくても後者の変更を直接検出できる。
Avatar
以前のわいわいで値型のプロパティを掘って通知できる仕様案みたいなのを見て、それは難しくないかという議論をした気がしますが、そういったものはない感じでしょうか?
Avatar
僕も詳しく追えてないですが、↓で @Observable struct は作れなくなったようです。 https://discord.com/channels/291054398077927425/499393715140558881/1132302591146078299 あと、今見つけられないのですが、前に shiz さんが値型の @Observable には問題があるという意見をコアチームの誰かが発言してるフォーラムの投稿を挙げてくれてた気が・・・。
Avatar
Arrayとかに@Observableつけられない...?
Avatar
参照型かに関わらず後付けはできなくないですか?
Avatar
structで直接Observableするのは筋悪なのはそれはそうで、値型と参照型で境界を作って、参照型の側でObservableを実現するような仕組みだと良い感じになりそうな気はしています
3:11 AM
Wrap<User>でObservableするみたいな
3:11 AM
或いはstructを一般にObservableにwrapできるような仕組みでも良いのかも
Avatar
たとえば、 Timelinevar posts: [Post] を持つようなケースで、タイムラインのページから投稿の一つをタップして投稿詳細ページに遷移、遷移先で post.isLiked.toggle() したら遷移元のタイムラインにも反映させたいようなケースで、これまでは Poststruct にして @Binding で渡せばよかったですが、 Observation の恩恵を受けるには Post@Observable class にしないといけないですよね。
3:41 AM
(これまでのケースについて)実際には @Binding で 渡すのではなく、遷移元と遷移先で共有する ObservableObjectTimeline を保持していて、その ObservableObject を参照するとかかもですが、いずれにせよ本題は Observation の恩恵を受けるために Post@Observable class でないといけなくならないかという点で、その点には影響ないかと思います。 (edited)
Avatar
そのケースはBindingを使うの良さそうに思うのですが、Observableを使う方が良いのでしょうか?
3:43 AM
複数のviewに跨がって値の変更を共有するなら、Bindingの方が良さそう
Avatar
Binding だと、 post.isLiked,toggle() でタイムラインの Viewbody も走っちゃいませんか? (edited)
3:45 AM
Observation はピンポイントで変更のあった箇所だけ再レンダリングを走らせられるのが魅力かなと。
Avatar
structの宣言に併せて、Observableなclassの射影を作れるマクロがあると幸せそうな気がしてきたが
3:47 AM
マクロのマクロは出来ない気がする…
Avatar
仮にできたとしても、そういうものが必要になった時点でなんか間違ってる気がするんですよね・・・
Avatar
SwiftUIの側で、Equatableで==がtrueならレンダリングをサボる機構があれば、それだけでBindingだけでも良いんですよね
3:57 AM
なんというかこれは、SwiftUIで解決するべき問題を、言語側にやらせようとした歪みな気がします
Avatar
SwiftUIの側で、Equatableで==がtrueならレンダリングをサボる機構があれば、それだけでBindingだけでも良いんですよね
挙動的にはこの機構あるはずだからBindingで良いかなと思いました
Avatar
でも posts 自体は変更されてるから( 1 要素の isLiked だけとはいえ)、タイムライン側で == しても変更があるとしか言えなくないですか?
Avatar
Avatar
kitasuke
SwiftUIの側で、Equatableで==がtrueならレンダリングをサボる機構があれば、それだけでBindingだけでも良いんですよね
挙動的にはこの機構あるはずだからBindingで良いかなと思いました
View のレンダリングは行われなくても body は実行されないですか?
Avatar
Listに変更は通達されるが、その配下のRowViewは要素毎に再レンダされるかが決まるんじゃないかな
4:00 AM
bodyが評価されることはコスト的に大した問題では無くて、その先のレンダリングが実行されれば問題になる
Avatar
それが元々の思想ですが、結局仮想 View の時点で O(N) かかってるのが問題なのかなと。
4:00 AM
それは実 View のレンダリングコストと比較すると小さいとはいえ。
Avatar
多くなってもたかだか100個1000個くらいの演算なので無視で良い気がしますね (edited)
4:01 AM
そのためにコード全体が読みづらくなったり書きづらくなることの方がきつい
Avatar
SwiftUIのText等の各Viewにバインディングされてる値の==比較なので、 posts 自体が変わっても各要素で差分ある値のみレンダリングされる認識です。
4:02 AM
bodyが評価されることはコスト的に大した問題では無くて、その先のレンダリングが実行されれば問題になる
これはtarunonさんと同意見かな
4:03 AM
あと確か遷移元に戻る際にもそもそも遷移元 Viewbody は勝手に再実行されませんでしたっけ?これは気のせいかも。 (edited)
4:04 AM
数年前に _printChanges() でひたすらログを眺めてたらそんな感じだったような
Avatar
「bodyの中に重い演算を入れるな」これが本質かも
Avatar
single source of truth でアプリ全体で共有された状態があり、それが ArrayDictionary でエンティティを保持しており、その 1 要素の 1 プロパティが変更されただけで、それを参照しているすべての body の再実行がされ、その中にはループして O(N) のものもあり、実 View のレンダリングは行われないにしても、仮想 View の再生成すら辛い状況が、特にハイパフォーマンスが求められるアプリでは起こっているのかなと。
Avatar
リレーショナルデータベースもパフォーマンスのために非正規化したりするのでsingle source of truthとパフォーマンスはトレードオフのような気がします。
Avatar
私もそこは同意ですね、パフォーマンス必要ならチューニングは必須で、一番先にStateの分割は考えると思います
Avatar
正規化によるパフォーマンスの低下の話や、一つの巨大な State 型を作るという話ではなく、 structArrayDictionary に入れてしまった時点で、そのコレクション全体の変更として検出されてしまうという問題についてですね(SSOTの話を出したのは、そのコレクションが色々なところから参照された場合に影響度が大きいという話です)。 これまでも各要素を ObservableObject で表現すれば要素の変更を検出できましたが、ネストした ObservableObject の変更を(自動的には)検出できなかったのでいまいちでした。 Observation によって変更箇所がピンポイントで検出できるようになったけれども、それに乗っかるには @Observable class にしないといけない( struct にできない)というのが悩んでいるポイントです。 (edited)
Avatar
宣言的UIは基本的には都度全て更新するという考え方だと思うので、ナイーブな実装だとパフォーマンス上問題あるというのはそもそもそういうものなのではないでしょうか? (Reactもメモ化とかしないと子コンポーネント全部再レンダリングされるらしいですし)
Avatar
Avatar
trickart
宣言的UIは基本的には都度全て更新するという考え方だと思うので、ナイーブな実装だとパフォーマンス上問題あるというのはそもそもそういうものなのではないでしょうか? (Reactもメモ化とかしないと子コンポーネント全部再レンダリングされるらしいですし)
はい、そういう認識です。そして、新しく導入される Observation を使えば、ピンポイントに更新された箇所だけ更新できるという理解です。
Avatar
Avatar
koher
はい、そういう認識です。そして、新しく導入される Observation を使えば、ピンポイントに更新された箇所だけ更新できるという理解です。
であるならば、パフォーマンスのために各要素をclassにする等といったことは気持ち悪いけど仕方がないのかな…という立場です。
Avatar
それが、これまで築いてきた Swift の世界観と相容れないような気がして困惑してる感じですね・・・。Swiftのすべてのコードが Observation を使うわけでもないので、 Observation を前提としたコードとそれ以外で断絶が生まれそうですし。
❤️ 2
Avatar
あと、今見つけられないのですが、前に shiz さんが値型の @Observable には問題があるという意見をコアチームの誰かが発言してるフォーラムの投稿を挙げてくれてた気が・・・。
このあたりの話ですかね? 正しく理解できていないかもしれませんが... @Observable なstructの値を参照型が保持していて、その値のコピーが変更された場合に元の値のサブスクライバーにも変更が通知されてしまうのが問題で、これはCoWを使えば解決できそうだけど、そもそもの値型の概念やエッジケースがありそうだから後で考える、というようなことを言っているのかなと思ってます。 https://forums.swift.org/t/second-review-se-0395-observability/65261/113 https://forums.swift.org/t/second-review-se-0395-observability/65261/119
(edited)
To circle back on the structural nature of observable types - there are definitely use cases for things to be able to be Observable and interplay with observation that are structures; however as folks have raised there are some sharp edges. Namely of which - what happens when you copy a structure that is marked with @Observable. To go into this ...
Making the observation tracking data copy-on-write for value types seems better than making it truly shared, but it still doesn't seem right. I don't think I can explain what I see as the right thing here without a little bit of theory. I think folks might be confusing values and locations. These are both basic formal concepts of languages, t...
Avatar
値型に対する変更監視は本質的にうまくいかないと思いますけどねえ
11:52 PM
classの中でvarで保持されているstructのようなケースなら、そのstructのアイデンティティは安定しているけど、
11:52 PM
例えば classの中のdictionaryの中で保持されているような値型を考えると、
11:53 PM
dictionaryのrehashなどのタイミングで、コンテナの内部バッファ上での値のアドレスが変わったりします
11:54 PM
そういうときに操作として値 T のコピーをしている可能性がある。
11:55 PM
値型はいつでもコピーできるものとして設計されているのに対して、 アイデンティティ管理が必要な変更監視の概念を導入すると、 そういった思わぬコピーによっておかしなことになると思う
11:58 PM
コピーのタイミングだったらコピー元・コピー先を区別して、サブスクライバを複製しない、ということができるかもしれないけど、 一般にコピーの方向って意識していないはずなので変なバグが生じそうだし、
11:58 PM
実際にはSwiftではコピーのタイミングでなにかすることができないので、
11:58 PM
Copy on writeでできるのは、on writeの時点でカウンタがいくつか、を見られるだけなので、
11:58 PM
writeのタイミング、つまり変更イベント送信のタイミングですが、 そこで自分自身がコピー元なのかコピー先なのか区別できないので実装不可能な気がする。
12:00 AM
SwiftUIは値型のViewに対して変更監視のようなことができるけど、 あれは値型のViewはただのパラメータツリーを渡すためのインターフェースにすぎなくて、 ランタイムではビューツリー構造に基づくIdentityが定義・管理されていて、 そのアイデンティティのもとでイベントハンドリングしているからうまくいくのであって、
12:01 AM
ライブラリ実装によって値型のようなインターフェースの裏にクラスが隠れてて、 値の更新のたびにそのクラスとの対応付けを取ってるからできるのであって、 つまり値型に対する更新監視をしているわけではなくて、対応付けられたアイデンティティ空間の方で更新監視してる。 (edited)
Avatar
なんか実現無理そうな気がしますねwどうやろうとしているんだろう...
あれは値型のViewはただのパラメータツリーを渡すためのインターフェースにすぎなくて、 ランタイムではビューツリー構造に基づくIdentityが定義・管理されていて、 そのアイデンティティのもとでイベントハンドリングしているからうまくいくのであって、
実現するとしたらObservationにもMacroでこういう仕組みを導入するということなるんでしょうか?
(edited)
Avatar
Macroでできる範囲の話ではないと思います。 SwiftUIはViewの実装で頑張ってるんじゃなくて、Viewを受け取るランタイムのほうで頑張ってる話なので。
Avatar
、Viewを受け取るランタイムのほうで頑張ってる話なので。
なるほど。ありがとうございますmm
Avatar
SwiftUI普通に書いてると見逃しやすいですけど
12:57 AM
@main struct MyApp: App { var body: some Scene { WindowGroup { Text("Hello, world!") } } }
12:58 AM
ここで MyApp とか body とかが、暗黙に SwiftUI.App に渡されるところから始まるので。
t_naruhodo 1
t_kansha 1
Avatar
SwiftUIのViewはたんなるplistみたいな定義ファイル (edited)
1:37 AM
っていう認識がUIKitからくると混乱する原因よなーと思う。Viewっていう名前がよくない。
Avatar
omochimetaru 7/25/2023 1:41 AM
図面みたいなもので実体じゃないんですよね。
Avatar
Avatar
shiz
あと、今見つけられないのですが、前に shiz さんが値型の @Observable には問題があるという意見をコアチームの誰かが発言してるフォーラムの投稿を挙げてくれてた気が・・・。
このあたりの話ですかね? 正しく理解できていないかもしれませんが... @Observable なstructの値を参照型が保持していて、その値のコピーが変更された場合に元の値のサブスクライバーにも変更が通知されてしまうのが問題で、これはCoWを使えば解決できそうだけど、そもそもの値型の概念やエッジケースがありそうだから後で考える、というようなことを言っているのかなと思ってます。 https://forums.swift.org/t/second-review-se-0395-observability/65261/113 https://forums.swift.org/t/second-review-se-0395-observability/65261/119
(edited)
おお、これです。ありがとうございます!ここ( Discord )か Twitter で前に挙げられてたと思うのですが、検索しても見つけられず・・・。助かりました🙇‍♂️
Avatar
値型の observation はうまく機能しないと思います。たとえば、 var a: Foo = .init() var b: Foo = a withObservationTraking { print(a.x) } onChange: { print("onChange") } b.x = 42onChange が呼ばれるのか。呼ばれるなら、異なるインスタンスである ab の observation が混ざってて変だし(このあと、 a.x = -1 を実行するとどうなるのか)、呼ばれないならコピーされたら(たとえば computed property を介して Fooreturn されたら)観測できなくなる。 (edited)
Avatar
omochimetaru 7/25/2023 4:30 AM
computed propertyを介するだけで話終わるの確かにそうですねw
Avatar
根っこに参照型がいて、それが値型のプロパティを持つんじゃないとうまくいかないよね。そして、それだと結局今の ObservableObject とほぼ同じ使い方になる。
t_desune 1
Avatar
Kishikawa Katsumi 8/1/2023 4:29 PM
SwiftSyntax tries to minimize the use of existentials (aka. protocols spelled with any or protocols spelled without some) wherever possible. This is because when the stored value is more than 3 words (a word is the size of a pointer) large, these existentials store their data on the heap. The data stored inside RawSyntax is larger than 3 words and thus every time you pass a value around as a e.g. an ExprSyntaxProtocol, a new heap allocation will be made and that data needs to be reference-counted, which causes a very noticeable performance overhead.
SwiftSyntaxのドキュメント読んでたらこの記述に出会ったのだけど、3ワード以上の大きさだったらメモリがヒープに確保されるっていうのこれ以外に記述あるかな?
4:30 PM
apple/swiftリポジトリのドキュメントのどこかにも書いてあった方がいいんじゃないかなって。
4:33 PM
It does this using a fixed-size buffer, which is three pointers in size and pointer-aligned. This either directly contains the value, if its size and alignment are both less than or equal to the fixed-size buffer's, or contains a pointer to a side allocation owned by the existential container.
Avatar
Kishikawa Katsumi 8/1/2023 4:33 PM
それ、同じ意味っぽいすね。
4:34 PM
ありがとう!
Avatar
omochimetaru 9/9/2023 4:05 PM
Tuple conformances Authors: Slava Pestov Status: Implementation in progress Upcoming Feature Flag: TupleConformances Previous Proposal: SE-0283 Tuples Conform to Equatable, Comparable, and Hashable Review: (pitch) Introduction Tuples cannot conform to protocols today, and this surfaces in the form of obvious limitations, such as not being able...
4:06 PM
タプルのコンフォーマンスのピッチが出た 昔タプルをEquatableにしようとして実装できなかったやつ
4:07 PM
同時にパラメタライズドextensionが導入されててすごい 確かにこれないと書けないんだけど
4:07 PM
タプルコンフォーマンス以外に使えるんだろうか?
Avatar
つまりtupleは可変長ジェネリックスのtop typeを具体型で埋めたものになるってこと
Avatar
omochimetaru 9/9/2023 4:09 PM
最近進んだ可変長ジェネリクスを使って記述するようになってる (edited)
Avatar
パッと見た感じ壊れるシナリオ思い付かないな
4:10 PM
前のはすぐ壊れたけど
4:12 PM
これコンパイルの計算量はどんなもんなんでしょ、あんまり想像出来てない
4:13 PM
tuple作ってEquatableにしちゃうシナリオは其処彼処で出てきそうなので、重くなったらヤだなの感
Avatar
omochimetaru 9/9/2023 4:28 PM
他のconditional conformanceと変わらない気がする
4:28 PM
タプルの要素数が多ければその分重くなるけど計算量に効いてくる部分ではなさそう
4:32 PM
あーそうか、これまでも struct S<X>に対してextension Sって書いてたけど
4:33 PM
これって extension <X> S<X> って事なんじゃないか
4:34 PM
jroseさんが、typealias Tuple導入するなら、
Avatar
このままだと継承関係のある複数のprotocolで同時にconformできないか? (edited)
Avatar
omochimetaru 9/9/2023 4:34 PM
こっちで書けるようにすればパラメタライズエクステンションは要らないよ、って言ってる
Avatar
Avatar
tarunon
このままだと継承関係のある複数のprotocolで同時にconformできないか? (edited)
omochimetaru 9/9/2023 4:36 PM
どゆこと?
Avatar
cond confでEquatableとHashableを同時に入れようとするとだるかった記憶がある
4:37 PM
extension S: Equatable where X: Equatableと extension S: Hashable where X: Hashableを同時に書くと警告出てた記憶あるけど
4:38 PM
改善されたんだっけか
Avatar
omochimetaru 9/9/2023 4:39 PM
たしかにそもそもなんか変だなそれ
Avatar
XがEqならSもEqで、XがHashならSもHashにしたい
Avatar
omochimetaru 9/9/2023 4:39 PM
HashableにEquatableが含まれてるからEquatableの準拠が2つ書いてあることになっちゃうな
Avatar
モチベーション自体は別に変な話じゃないし、tupleもそうなると思う (edited)
Avatar
omochimetaru 9/9/2023 4:41 PM
今どうなってるんだろう?
4:41 PM
S<X>の場合に。
Avatar
記憶違いでなければ、昔は警告出ててクソ怠かったの覚えてる
Avatar
omochimetaru 9/9/2023 4:42 PM
A tuple extension must declare conformance to exactly one protocol.
こう書いてあるし、状況としてはタプルも同じだろうけど。
Avatar
いまは、手元にXcodeが無いです😇
4:42 PM
せや、swiftbotおるやん
Avatar
omochimetaru 9/9/2023 4:44 PM
ワイももう寝てる
Avatar
@swift-5.6.3 struct S<X> { var x: X } extension S: Equatable where X: Equatable {} extension S: Hashable where X: Hashable {}
Avatar
Avatar
tarunon
@swift-5.6.3 struct S<X> { var x: X } extension S: Equatable where X: Equatable {} extension S: Hashable where X: Hashable {}
swift56 BOT 9/9/2023 4:44 PM
no output
Avatar
警告無しかしら
Avatar
omochimetaru 9/9/2023 4:45 PM
それさあ、もしHashableの中の==が、Equatableの中の==と矛盾する別の実装だったらどうなるんだろ
4:45 PM
それともあれか、条件の包含関係を検出して、==については実装不要になってる?
Avatar
それは書けなくなっていれば正しいと思う
👉 1
Avatar
omochimetaru 9/9/2023 4:46 PM
Hashableの中の==はEquatableの準拠の方に飛ばされてれば綺麗だね
Avatar
でも、protocol conformanceの実装って、確か複雑な型の実装が優先されるみたいなの、あったよね
4:47 PM
その通りなら上書き可能かもしれん
Avatar
omochimetaru 9/9/2023 4:47 PM
じゃあ逆に cond confの条件が包含してなかったらどうなるんだ・・・・・
Avatar
Avatar
tarunon
でも、protocol conformanceの実装って、確か複雑な型の実装が優先されるみたいなの、あったよね
omochimetaru 9/9/2023 4:47 PM
や、conformanceは一つしか存在できない
4:47 PM
優先とかじゃない
Avatar
@swift-5.6.3 struct S<X> { var x: X } extension S: Hashable where X: Equatable { var hashValue: Int { 1 } } extension S: Equatable where X: Hashable {}
Avatar
Avatar
tarunon
@swift-5.6.3 struct S<X> { var x: X } extension S: Hashable where X: Equatable { var hashValue: Int { 1 } } extension S: Equatable where X: Hashable {}
swift56 BOT 9/9/2023 4:48 PM
exit status: 1 with <stdin>:2:1: error: type 'X' does not conform to protocol 'Hashable' extension S: Hashable where X: Equatable { ^ <stdin>:2:1: error: 'Hashable' requires that 'X' conform to 'Hashable' extension S: Hashable where X: Equatable { ^ <stdin>:2:1: note: requirement specified as 'X' : 'Hashable' extension S: Hashable where X: Equatable { ^ <stdin>:2:1: note: requirement from conditional conformance of 'S<X>' to 'Equatable' extension S: Hashable where X: Equatable { ^ <stdin>:3:7: warning: 'Hashable.hashValue' is deprecated as a protocol requirement; conform type 'S' to 'Hashable' by implementing 'hash(into:)' instead var hashValue: Int { 1 } ^
Avatar
omochimetaru 9/9/2023 4:48 PM
だから複数のモジュールでそれぞれ後付け準拠してると実行時にはガチャになって壊れる
Avatar
今はhash(into:)か
Avatar
Avatar
tarunon
@swift-5.6.3 struct S<X> { var x: X } extension S: Hashable where X: Equatable { var hashValue: Int { 1 } } extension S: Equatable where X: Hashable {}
omochimetaru 9/9/2023 4:49 PM
条件がひっくり返ってるのわざと?
Avatar
わざとだよ
4:49 PM
壊れそうだなって思って
4:50 PM
流石にXcode欲しいな
4:50 PM
明日また試すか
Avatar
12:49 PM
S: Hashable の条件は、 S: Equatable の条件を満たしていないといけない、って制約がかかってる!賢い。
Avatar
なるほどなぁ
Avatar
たしかにこれが成り立ってしまったら、Hashableに準拠する事によってEquatableの準拠条件を迂回できてしまうからだめなんだね
12:49 PM
もう一つ試した。
12:50 PM
Hashableの準拠だけ書いて、Equatableの準拠は書かなかったら、エラーになった。
12:50 PM
つまり、子プロトコルの準拠を書くときは、必ずその親プロトコルの準拠も明記しないといけない。
12:51 PM
うまいこと論理がおかしくならないように制限がかかってるんやな。
12:51 PM
変なコードを書いたことないから知らなかったw
Avatar
これHashable以外で起こります?
1:40 PM
Hashableでこれよく見ますが、他あんまみないなぁと
Avatar
omochimetaru 9/10/2023 1:45 PM
標準ライブラリだと継承されたプロトコルがHashableしかなさそう。 自前の P1とP2で実験してみるか。
Avatar
ジュニア 9/10/2023 3:57 PM
ExpressibleByStringLiteralとかもそうですね https://developer.apple.com/documentation/swift/expressiblebystringliteral これ単体に条件付き適合させようとして同じように怒られた記憶があります
A type that can be initialized with a string literal.
Avatar
omochimetaru 9/10/2023 5:21 PM
protocol ExpressibleByStringLiteral : ExpressibleByExtendedGraphemeClusterLiteral {} protocol ExpressibleByExtendedGraphemeClusterLiteral : ExpressibleByUnicodeScalarLiteral {} すごい、孫プロトコルだ 知らなかった
Avatar
自作のプロトコルでも同じですね
12:11 AM
Avatar
おお、本当ですね。
12:18 AM
@swift-5.8.1 struct S<X> {} extension S: Error where X: Error {}
Avatar
Avatar
Iceman
@swift-5.8.1 struct S<X> {} extension S: Error where X: Error {}
no output
Avatar
ErrorのSendableは言われないけど、何か特別なんでしょうかね
Avatar
普段見かけないのは同意だけど、親子付けプロトコル自体が珍しいし、さらにcond confにした時しか踏まないから、見かけないんだろう
12:21 AM
12:22 AM
S: ErrorS: Sendable も付いてきてるな・・・
12:23 AM
12:23 AM
Sendableってマーカープロトコルで、型システム的な扱いが特殊なんですよね
12:23 AM
それと関係して許されているのかなあ
12:24 AM
一般のプロトコルは型TのプロトコルPへのコンフォーマンスが実行時にグローバルに一つ登録されるけど
12:24 AM
Sendableに関しては実行時情報が存在しなくて、完全に静的な検査でしかない
12:25 AM
なので、普通のプロトコルと違って、 S が Sendable になる条件が複数あっても大丈夫・・・?
12:26 AM
12:26 AM
X: Sendable を2つ書いたら怒られた。
12:27 AM
12:27 AM
間接的に導入される Sendable conformance であっても、ちゃんと合計一つしか許されないようになっている。 (edited)
12:28 AM
うーん、Sendableに関しては、
12:29 AM
extension S: Error where X: Error {} って書くと自動的に extension S: Sendable where X: Error {} も生成されている(条件部分はコピー) ような挙動に見えますね。。 (edited)
12:30 AM
手で extension S: Sendable where X: Sendable {} を書けば、自然な定義にはなるから、困ることは無さそうだけど、ルールが違うのが気になるな
12:30 AM
既存の : Error がソース互換性を壊すから、仕方なく特別処理してるのか・・・? (edited)
12:32 AM
12:32 AM
↑自作のマーカープロトコルでも同じ挙動をする。Sendableだけじゃなさそう。
Avatar
なるほど。マーカープロトコル特有の挙動なんですね
Avatar
12:36 AM
ちょっと記述があったけど今調べてるcond confの挙動の話は書いて無さそう・・・?
Avatar
A marker protocol cannot be used in a generic constraint for a conditional protocol conformance to a non-marker protocol.
これは違いますか?
Avatar
それはちょっと違う
12:39 AM
「マーカープロトコルを、 ノンマーカープロトコル の準拠の 条件部分に 使えない」 です。 (edited)
Avatar
non-marker protocol(ここではError)に対してcond confの条件にできない、だから、逆にいえば必須にもできないのかなと
Avatar
いや、いま議論しているのは
Avatar
extension S: Error where X: Sendableが記載できないから、エラーにできないのかなと
12:40 AM
あれ、逆か
Avatar
extension S: Error where X: Error から、 暗黙に extension S: Sendable where X: Error が生成されているよね、というのは
12:41 AM
「マーカープロトコルへの準拠条件が ノンマーカープロトコル」なので、問題ないんです。明記もできます。
12:42 AM
その文は何を言ってるかというと
12:42 AM
「マーカープロトコルへの準拠状況」が実行時に消失しているので
12:42 AM
実行時のキャストでマーカープロトコルの準拠が使えないよという事です (edited)
12:43 AM
逆は大丈夫です。大丈夫だけど意味はないけど。実行時にテストする事ができないから。
12:43 AM
extension S: Error where X: Sendable ←禁止されているのはこっちですね これは実行時に X: Sendable がテストできないから駄目(情報自体が実行時には消えている) (edited)
12:44 AM
extension S: Sendable where X: Error ←こっちは実行時に条件部をテストする事自体はできる。 できるけど、 Sendableへの動的キャストが禁止されているから意味が無い。
12:48 AM
Avatar
extension S: Error where X: Error に対して extension S: Sendable where X: Error {} が自動で定義されるのはちょっと不思議ですね
Avatar
はい。 S: Hashable の場合と同様に、 S: Sendable も明記しなさい、で良いと思うんですけど・・・
12:52 AM
Error に対して親プロトコルの Sendable が後付けされたので、 既存の S: Error where がコンパイル不可能になるのを避けたのかなあ? (edited)
12:58 AM
c++ if (conformance->getSourceKind() == ConformanceEntryKind::Implied && !Proto->isMarkerProtocol()) {
12:58 AM
Implyされたconformance entryに関して、それが marker protocol でなければERROR(conditional_conformances_cannot_imply_conformances,none, "conditional conformance of type %0 to protocol %1 does not imply conformance to " "inherited protocol %2", (Type, Type, Type)) のエラーが出るようになってる。
1:00 AM
Introduce two semantic tweaks for marker protocols: Allow implied conditional conformances to marker protocols. Ban use of marker protocols in conditional conformances to non-marker protocols
1:00 AM
この分岐のパッチあった (edited)
1:00 AM
This improves source compatibility in cases where a marker protocol is introduced after-the-fact (e.g., for Error), and is safe because there's no runtime component to marker protocols.
1:00 AM
あたりだわ
1:00 AM
Errorに関するソース互換性を守るためだ・・・
1:01 AM
「ランタイムの影響が無いから見えないconformanceがあっても実害は無い」という言い訳?も付いてるな。
Avatar
omochimetaru 9/20/2023 2:05 AM
https://github.com/vapor/fluent-kit/blob/main/Sources/FluentKit/Concurrency/Database%2BConcurrency.swift#L4-L10 func transaction<T>(_ closure: @Sendable @escaping (Database) async throws -> T) async throws -> T { try await self.transaction { db -> EventLoopFuture<T> in let promise = self.eventLoop.makePromise(of: T.self) promise.completeWithTask{ try await closure(db) } return promise.futureResult }.get() } (edited)
2:06 AM
↑この transaction 関数の引数の closure って、 @Sendable@escaping も外していいと思うんですけど、正しい考えですかね?
2:06 AM
理由は、 self.transaction が返す EventLoopFutureawait future.get() して待機しているから、 この transaction メソッドが終了する時点では、必ず closure の呼び出しも終了しているからです。
2:08 AM
closure はEventLoopスレッドで実行されるのでconcurrency boundaryは跨いでるけど、 この transaction メソッド自体が async で、呼び出し側は必ず await で待たないといけないし。
2:09 AM
let closure = { (db) in ... } Task { closure() } try await db.transaction(closure) ↑呼び出し側で勝手にこういうふうにする事ができるか・・・? でもこの場合は、let closure の時点で @Sendable にしないと Task に渡せないから、この心配もないか
Avatar
@escapingはなくても良さそうですね。@Sendableに関してもclosureは一瞬EventLoopと別Taskのスレッドに移るけど、reentrantを考えてもclosureと同じActor contextの処理が並列実行されることはないような気がする?ので安全なような
Avatar
omochimetaru 9/21/2023 2:07 AM
I've been pondering upon the following code for a function. public extension Database { func transaction(_ closure: @Sendable @escaping (Database) async throws -> T) async throws -> T { try await self.transaction { db -> EventLoopFuture in let promise = self.eventLoop.makePromise(of: T.self) promise.completeW...
👍 3
2:07 AM
フォーラムに投稿してみました。
Avatar
返事きてるけどよくわからないですね。スコープ関数において、という前提が抜けてる気がする?
Avatar
omochimetaru 9/21/2023 7:11 AM
スコープ関数はまあおまけで、 それ以前に In this transaction function に対して no って言ってるな・・・
7:13 AM
lukasaさんはnioのメイン開発者なんだよな〜・・・
Avatar
omochimetaru 9/21/2023 7:33 AM
Sadly this is not what the concept of Sendable implies. Sendable is required any time we pass the value across concurrency domains, which we do here.
コンセプトがそうではないというのはわかるけど、 そのコンセプトが実現したいことは結局shared mutable stateへの同時アクセスを防ぐ事であり、 だから struct もしくは immutable class である事を要求しているのであって、 そもそも同時アクセスしない状況なら問題は起きないんじゃあなかろうか
7:34 AM
なんか説得力のある実際の unsafe send 事例があればいいんだけど・・・
Avatar
omochimetaru 9/21/2023 7:44 AM
返信が難しいけど、ちゃんと考えている事を伝える必要があるな、この回答じゃとうてい納得できんし
Avatar
omochimetaru 9/21/2023 8:18 AM
返信を書きました。
Avatar
「多分安全だけど、コンパイラが賢くなって Sendable 無しで渡せるようになるのが正しい解決方法で、現時点でアトリビュートを消すのは反対」という返事が貰えた。
Avatar
賢くなってなんとかなるタイプの問題なのかなぁ
Avatar
omochimetaru 9/21/2023 1:25 PM
Hello Swift Community! As strict concurrency checking comes closer to being a standard, error-producing part of the Swift language, the restriction that only Sendable values can be communicated between tasks, actors, and other isolation domains is becoming increasingly problematic. For many datatypes, sacrificing mutability to attain Sendable c...
1:25 PM
返信で引用されてるこれが
1:25 PM
まさにその実装例っぽい
Avatar
actor init/deinitの改善のPRでも出てきたflow-sensitive analysisというのを使うというやつですね。selfがdecayするという話でなんとなく覚えてました。 https://github.com/apple/swift-evolution/blob/main/proposals/0327-actor-initializers.md#flow-sensitive-actor-isolation (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
selfがdecayってどういう意味ですか?
Avatar
うまく説明できるかわからないですが、init内でactor isolatedなプロパティに安全にアクセスできる間はそれをできるようにして、安全でなくなったタイミングで(letではない)isolatedなプロパティへの直接アクセスを禁止する、というように変わることをdecay(衰退)と言っています。 プロポーザルに上がっていた例で見ると class NotSendableString { /* ... */ } final class Address: Sendable { /* ... */ } func greetCharlie(_ charlie: Charlie) {} actor Charlie { var score: Int let fixedNonSendable: NotSendableString let fixedSendable: Address var me: Charlie? = nil func incrementScore() { self.score += 1 } nonisolated func nonisolatedMethod() {} init(_ initialScore: Int) { self.score = initialScore // ✅ self.fixedNonSendable = NotSendableString("Charlie") // ✅ self.fixedSendable = NotSendableString("123 Main St.") // ✅ if score > 50 { nonisolatedMethod() // ✅ selfのnonisolatedな使用 greetCharlie(self) // ✅ selfのnonisolatedな使用 self.me = self // ✅ selfのnonisolatedな使用 } else if score < 50 { score = 50 } assert(score >= 50) // ❌ selfのnonisolatedな使用後に、可変のisolatedなプロパティへアクセスできなくなる _ = self.fixedNonSendable // ❌ selfのnonisolatedな使用後に、non-Sendableなプロパティへアクセスできなくなる _ = self.fixedSendable Task { await self.incrementScore() } // ✅ selfのnonisolatedな使用は引き続きOK(awaitしているのでactor isolated) } } (edited)
Avatar
最後のコメントの nonisolatedisolated の間違いですかね? (edited)
Avatar
これのことですか? Task { await self.incrementScore() } // ✅ selfのnonisolatedな使用は引き続きOK そうですね。これはawaitしてactorのboudary内の処理になるのでコメントが変だと思いました。 (edited)
Avatar
あ、和訳してくれただけで原文がそうなのか
Avatar
はい、今原文見ていて「あれ?ちょっと違うかも」と僕も思いましたw
Avatar
なるほど。 これ内容を理解していないけど、 とにかくこのフロー解析によってselfが同期的に使えない状態になることをdecayと呼んでいるのですね
12:05 AM
https://forums.swift.org/t/pitch-safely-sending-non-sendable-values-across-isolation-domains/66566/25 こっちのスレッドにも、問題のパターン(をもっとプリミティブにしたもの)が、安全なのかどうか、および静的解析の希望はあるのか、質問を書き込んでみました。
If a variable passed to a Task is accessed after it's passed, it will cause problems due to simultaneous access. However, if the variable is accessed after Task.value has been await-ed, as in the code below, I believe there would be no problem as there's no risk of simultaneous access. Am I correct? // not Sendable class NS {} func main() ...
👍🏻 1
Avatar
とにかくこのフロー解析によってselfが同期的に使えない状態になることをdecayと呼んでいるのですね
はい、selfをnonisolated selfとして扱うようにすることをdecayと呼んでいます。 the isolation of self decays (or changes) to nonisolated during any use of self that is not a direct stored-property access
(edited)
Avatar
nonisolated self になっているってことなのか、なるほど。
Avatar
decayって概念、他でも使えそうですね。初期化の間だけミュータブルだけど初期化終わってからはイミュータブルとか。
Avatar
omochimetaru 9/22/2023 1:41 AM
あーそれほしいなあ
1:42 AM
varで構築したほうが見やすくかけるけど、ここで構築完了だからこの先では変更しない
1:42 AM
って気持ちを表したいことがありますね
1:43 AM
var a0 = [0] a0 += [a] a0 += [b] let a = consume a0
👀 1
1:44 AM
こうできるようにならんかな
1:44 AM
consume operatorって入ったんだっけ
Avatar
consume operatorって入ったんだっけ
5.9で入りました。
(edited)
Avatar
おおーほんとですね
👀 1
2:11 AM
同名の宣言はできなかった。
Avatar
omochimetaru 9/22/2023 2:12 AM
手元がbetaだから変なエラーが出たのか。落としてこよう。
2:13 AM
同名はダメか〜 でもそれ以降の利用を潰せるなら0とか1とか付けてけばいいや (edited)
Avatar
omochimetaru 9/22/2023 5:42 AM
Xcode15にしたけどなんかだめだな
5:42 AM
あれ、文字列はいける
5:42 AM
1 はいけない
Avatar
Intはサイズ小さいからとか?
Avatar
top-level コードで書いた時に同じコンパイルエラーが出たことがあります.(その時は関数の中に書いたら解決した)
5:45 AM
関数ローカルかつ文字列のときしか動かない↑の手元と同じだな
t_naruhodo 1
5:46 AM
intでもletならいける
5:46 AM
なんかめっちゃバグってそうだなあ
😭 3
Avatar
Avatar
shiz
これのことですか? Task { await self.incrementScore() } // ✅ selfのnonisolatedな使用は引き続きOK そうですね。これはawaitしてactorのboudary内の処理になるのでコメントが変だと思いました。 (edited)
これ、 Task.initself を capture させるところが nonisolated use of self だと言っているのかもしれません。 nonisolatedなので actor context の引継ぎもおきなくて、 中で await が必要です
Avatar
Avatar
omochimetaru
これ、 Task.initself を capture させるところが nonisolated use of self だと言っているのかもしれません。 nonisolatedなので actor context の引継ぎもおきなくて、 中で await が必要です
あ、Task.init内は同じactor context内なのでawaitがいらないはずが、nonisolated selfなのでawaitが必要になっているんですね。そしてawaitでactorのexecuterにhopして実行されるので安全だと。
Avatar
omochimetaru 9/23/2023 1:04 AM
そうそう
t_naruhodo 1
Avatar
理解できました。ありがとうございます!
✌️ 1
Avatar
omochimetaru 9/23/2023 1:27 AM
SE-0327 を読み直した。わかったけど、めちゃくちゃ難しいな。
1:27 AM
アクターを使う側からすれば、どうせ await だらけになるんだから、 isolated async init だけ使っておけばええんちゃうか。
t_wakaru 1
Avatar
Repository of the pitch for Typed Throws for the Swift Language. - GitHub - DougGregor/swift-typed-throws: Repository of the pitch for Typed Throws for the Swift Language.
👀 2
11:12 AM
typed throws の野良プロポーザルをドーグがフォークした上で編集してる
Avatar
ざっと見た感じ↓あたりが変わっているのかなと思いました。 Error typeを()で囲むようにした throws CatError ↓ throws(CatError) rethrowsにも型を指定できるようになった func foo<E: Error>(closure: () throws(E) -> Void) rethrows(E) Resultはtyped errorを返すように変える extension Result { init(catching body: throws(Failure) -> Success) { ... } } 当時よりも型推論がパワーアップしてもっと簡単に書けるようになった。 enum CatError: Error { case sleeps case sitsAtATree } do { try callCat() // throws CatError if something { throw CatError.asleep // throws CatError } } catch .asleep { openFoodCan() } // note: CatError can be thrown out of this do...catch block when the cat isn't asleep**Rationale**:
Avatar
omochimetaru 9/25/2023 2:51 AM
A couple of things I missed in my previous set of updates: Talk about handling all uninhabited thrown error types Improve AsyncSequence and for..in iteration Add a future direction for distributed...
2:51 AM
パッチになってminuscorpさんに反映された
👀 1
Avatar
Hi all, While there is an active discussion of typed throws over in this thread, the latest proposal is from a thread started in July 2020. We have an updated proposal with a revised design for typed throws, incorporating a number of the ideas and arguments that have come up over the years. I'm also working on an implementation of this design. ...
👀 1
Avatar
展開はやい
Avatar
野良の人のproposal下書きにAppleがパッチ投げてそれでピッチ建てるの珍しいパターンだと思う
Avatar
N+1で草
Avatar
次はどうするんだろうね。
Avatar
オリジナルを作った人がNにしていたんじゃない?(パッチなので+1ということ)と思ったけど、そうではない?
12:22 PM
SE-NNNNになってるからだと思った
Avatar
野良ではなくなって実装も進めているのでReviewに進みそうな気がしますね。 進みは遅いのかもしれないですがw(N+1と言われるとつい思い浮かべてしまう) (edited)
😄 1
Avatar
Avatar
tarunon
SE-NNNNになってるからだと思った
単にこれまでの typed throws の pitch やら proposal 案やらが正確な数を把握できないほどたくさん (8 件くらい?) あるからそれを N として一括りにしているんだと思ってました.
Avatar
最初のコメントでこれまでのアイデアを集めたみたいなことを書いているので実際はそういうことなのかなあと思いました。
Avatar
Avatar
tarunon
SE-NNNNになってるからだと思った
omochimetaru 9/25/2023 1:09 PM
今回NじゃなくてXになってるのでSE-Xになってる
t_kusa 2
Avatar
なるほど
Avatar
omochimetaru 10/5/2023 3:15 PM
swift-foundationの中に
3:15 PM
#if FOUNDATION_FRAMEWORK @_implementationOnly import _ForSwiftFoundation /// Wraps an `NSCalendar` with more Swift-like `Calendar` API. See also: `_NSSwiftCalendar`. /// This is only used in the case where we have custom Objective-C subclasses of `NSCalendar`. It is assumed that the subclass is Sendable. internal final class _CalendarBridged: _CalendarProtocol, @unchecked Sendable { let _calendar: NSCalendar
3:15 PM
こういう #if があって、
3:16 PM
#if FOUNDATION_FRAMEWORK @_implementationOnly import _ForSwiftFoundation import CoreFoundation #else #endif こういうのもあるから
3:17 PM
おそらく、従来の Foundation.framework がインポートできる環境において機能していて、
3:18 PM
実装を再利用するとか、ObjC-Bridgingを swift-foundation でも再実装しているんだと思うけど
3:18 PM
// MARK: - Bridging #if FOUNDATION_FRAMEWORK @available(macOS 10.10, iOS 8.0, watchOS 2.0, tvOS 9.0, *) extension Calendar : ReferenceConvertible { public typealias ReferenceType = NSCalendar } @available(macOS 10.10, iOS 8.0, watchOS 2.0, tvOS 9.0, *) extension Calendar : _ObjectiveCBridgeable { @_semantics("convertToObjectiveC") public func _bridgeToObjectiveC() -> NSCalendar { _calendar.bridgeToNSCalendar() } public static func _forceBridgeFromObjectiveC(_ input: NSCalendar, result: inout Calendar?) { if !_conditionallyBridgeFromObjectiveC(input, result: &result) { fatalError("Unable to bridge \(_ObjectiveCType.self) to \(self)") } } public static func _conditionallyBridgeFromObjectiveC(_ input: NSCalendar, result: inout Calendar?) -> Bool { result = Calendar(reference: input) return true } @_effects(readonly) public static func _unconditionallyBridgeFromObjectiveC(_ source: NSCalendar?) -> Calendar { var result: Calendar? _forceBridgeFromObjectiveC(source!, result: &result) return result! } } @available(macOS 10.10, iOS 8.0, watchOS 2.0, tvOS 9.0, *) extension NSCalendar : _HasCustomAnyHashableRepresentation { // Must be @nonobjc to avoid infinite recursion during bridging. @nonobjc public func _toCustomAnyHashable() -> AnyHashable? { return AnyHashable(self as Calendar) } } #endif // FOUNDATION_FRAMEWORK
3:18 PM
特にこれが気になっている @_implementationOnly import _ForSwiftFoundation
3:19 PM
つまり、 Foundation.framework の中に _ForSwiftFoundation というモジュールがあるはずで、
3:19 PM
意味としては 「for swift-foundation」で、swift-foundationが Foundation.framework を取り込む時に見せるためのヘッダー?可視性?を制御されたものだと思うんだけど
3:20 PM
corelibs-foundationの中を見ててもそのようなモジュールを定義している場所が見つけられなくてなんだろうとなっている
3:22 PM
でもこのヘッダー 2015年 (Swift2.2) のころからあるし、関係無さそうなんだよね (edited)
3:23 PM
でもどっちもparkeraさんが関わっては居る
3:25 PM
// _CalendarICU, if present static var calendarICUClass: _CalendarProtocol.Type = { #if FOUNDATION_FRAMEWORK _CalendarICU.self #else if let name = _typeByName("FoundationInternationalization._CalendarICU"), let t = name as? _CalendarProtocol.Type { return t } else { // Use the default gregorian class return _CalendarGregorian.self } #endif }()
3:25 PM
↑この _CalendarICU って型も corelibs-foundation の中から見つけられない。謎が深まる。
Avatar
omochimetaru 10/6/2023 2:40 PM
普通にissue建てて正面から聞いてみようかな。
Avatar
Hey everyone! Attached is a pitch for a new language feature called Region Based Isolation. It is based off of the earlier pitched SendNonSendable proposal. Would love everyone's thoughts and feedback. Thank you for your time and thoughts! Abstract Swift Concurrency assigns values to isolation domains determined by actor and task boundaries....
12:33 AM
先日 Sendable つけなくていいケースについて話したけど
12:34 AM
それについてのピッチ
12:35 AM
リージョン解析(和名?)という手法によって、 アクター境界をまたぎつつ、同時にもう使われなくなる値については、Sendableが不要になる (edited)
12:35 AM
feature名が SendNonSendable で、トゲナシトゲトゲみたいでわかりづらいが
12:35 AM
「SendableじゃないけどSendできる」パターンを検出する事によって Sendable付与の必要性を緩和するという事 (edited)
12:42 AM
逆にこの話がでてきたことで、やはりアクター境界またぎでとにかくSendableが要求されるのは、その前後で値が送信元ドメインで維持される事によって、後に並行アクセスされうる可能性に備えている、という理屈がはっきりしてきたと思う
Avatar
ちゃんと読んでないし考えてないけど、deferやdeinitを使うときの不便さが解消されると嬉しいですね
Avatar
Hey everyone, In the latest typed throws pitch, the adoption of typed throws in the standard library was removed due to the pitch growing quite large by itself and the large surface area of both the Swift and Concurrency module that might adopt typed throws. This pitch covers the adoption of typed throws inside the Concurrency module. There ar...
12:57 AM
typed throws入った前提でConcurrencyに導入する提案
12:58 AM
エラーの有無でthrowing版とオーバーロードしてる系とかを一通り throws(Failure)に一本化してて良い感じ
12:59 AM
AsyncSequenceにFailureを追加して、next2メソッドを追加するところだけ、見た目が変だけど、仕方なさそう
🥲 1
Avatar
久々にSwift6に関する情報が出てました。 https://forums.swift.org/t/progress-toward-the-swift-6-language-mode/68315/5 (edited)
what about Noncopyable Generics ?
Avatar
omochimetaru 11/8/2023 2:58 AM
the Language Steering Group is narrowing the focus of remaining changes for Swift 6 to data-race safety by default.
(edited)
2:59 AM
Swift6のデフォルトの並行安全性の仕様を狭める?
2:59 AM
「6なら絶対安全」はやめるってことかな
3:09 AM
ついでに参照されてるこれ見逃していた
3:10 AM
クロージャへのisolated capture、クロージャの明示的 nonisolated、コンパイラ定数 #isolation@inheritsActorIsolation のアンスコ卒業
3:10 AM
いいね
3:11 AM
クロージャの静的継承だけだとできないパターンがあるの気になってたし、 inherticsはアンスコ付きで使いたい場面もあった。
Avatar
Swift6のデフォルトの並行安全性の仕様を狭める?
安全性は確保するけどTask Executor Preferenceとかが含まれないのかもしれないのかなと僕は思いました。 https://github.com/ktoso/swift-evolution/blob/wip-task-executors/proposals/NNNN-task-executor-preference.md
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - ktoso/swift-evolution
Avatar
omochimetaru 11/8/2023 3:32 AM
Together, these changes fill the remaining major holes in strict concurrency checking and improve the usability of strict concurrency checking by introducing more Sendable inference and enabling safe ways to transfer non-Sendable values across isolation boundaries.
3:33 AM
残ってる穴を塞ぐ今やってる取り組みやったら十分で、残りのadditiveなものは外す?
Avatar
僕は読んでいてそう感じました。なのでSwift5.10で穴を塞いで、それが完了したらもう次はSwift6.0にしたいのかなと。 (edited)
Avatar
omochimetaru 11/8/2023 5:25 AM
なるほど
5:26 AM
そういえば
5:26 AM
any必須化は見送るようだけど
5:27 AM
そうすると、「デフォルトのsomeへの切り替え」はしないってこと?
5:27 AM
The proposal also specifies that "bare" protocol names will no longer be permitted as types---they must either use any or some, as appropriate---under the upcoming feature flag ExistentialAny.
5:27 AM
ここそういう意味かね
5:28 AM
「ただのPを、any Pじゃなくてsome Pにする」ってアイデアがあって まずただのPを一度any Pにコードマイグレーションしてから、それを導入するためには、Swift6でany必須にしておかないといかん
Avatar
そうすると、「デフォルトのsomeへの切り替え」はしないってこと?
はい、これまで通りかなと思ってます。
「ただのPを、any Pじゃなくてsome Pにする」ってアイデアがあって
確かここら辺の話だったかと。(反対派も結構いて結論は出てなかったような...) https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918#should-some-be-the-default-in-swift-6-2
Swift 5.7 includes a suite of new language features that together enhance the expressivity and usability of any and some types, making abstract code more approachable and easier to internalize. In addition to making a lot of common generic code patterns easier to write by eliding an explicit generic signature completely, Swift 5.7 makes it very...
naruhodo 1
Avatar
omochimetaru 11/9/2023 2:55 PM
Hello, Swift community! The review of SE-0412: Strict concurrency for global variables begins now and runs through November 22nd, 2023. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager...
2:56 PM
グローバル変数のstrict concurrency
2:56 PM
Top-level global variables are already implicitly isolated to @MainActor and therefore automatically meet these proposed requirements.
2:57 PM
これ、もうそうなってる、って事ですよね??
2:57 PM
その場合、プロポーザルになんか意味あるのか。
2:58 PM
strict concurrencyがexperimentalだからそもそも正式仕様として議論できない気がするけど、部分的にここだけ確定する・・・?
Avatar
structやclass内のstatic変数とかもこれに該当するということを言いたいんですかね...? ``` Within this proposal, global variables encompass any storage of static duration: lets and stored vars that are either declared at global scope or as static member variables. (edited)
Avatar
あーそうかもしれない たしかにグローバル変数とトップレベルグローバル変数って書き分けてるのか
Avatar
Hello, Swift community! The review of SE-0413: Typed throws begins now and runs through November 30th, 2023. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager by email or DM. When conta...
Avatar
おお
Avatar
norio_nomura 12/1/2023 6:57 AM
swift.org でダウンロードできるmacOS版Toolchain、SnapshotsはUniversalだけどReleasesはx86_64しかないのね。 訂正: Debugging Symbolsがx86_64だけでした。 (edited)
🤣 2
Avatar
Avatar
norio_nomura
swift.org でダウンロードできるmacOS版Toolchain、SnapshotsはUniversalだけどReleasesはx86_64しかないのね。 訂正: Debugging Symbolsがx86_64だけでした。 (edited)
https://www.swift.org/download/https://download.swift.org/swift-5.9.1-release/xcode/swift-5.9.1-RELEASE/swift-5.9.1-RELEASE-osx.pkg とかは展開すると universal binary が入ってましたが別の場所のことを言われてますかね? $ file ./usr/bin/swift ./usr/bin/swift: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit x86_64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|WEAK_DEFINES|BINDS_TO_WEAK|PIE|HAS_TLV_DESCRI PTORS>] [arm64]
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
t_arigatou 1
Avatar
norio_nomura 12/1/2023 3:46 PM
ああ、こっち https://download.swift.org/swift-5.9.1-release/xcode/swift-5.9.1-RELEASE/swift-5.9.1-RELEASE-osx-symbols.pkg を入れるとx86_64だけになるみたいです。
👀 1
Avatar
norio_nomura 12/1/2023 3:59 PM
swift-5.10-DEVELOPMENT-SNAPSHOT-2023-11-30-a-osx-symbols.pkgもx86_64だけでした。 (edited)
Avatar
typed throws、do throws(XXXError)という新しい構文も追加したいということでレビューが延期されましたね。 https://forums.swift.org/t/extended-se-0413-typed-throws/68741 do throws(CatError) { if isDaylight && foodBowl.isEmpty { throw .sleeps // equivalent to CatError.sleeps } try callCat() } catch let myError { // myError is of type CatError } (edited)
The review period for SE-0413 was scheduled to end today. I am extending it for another week to allow discussion of a late-breaking modification suggested by @beccadax to allow explicit specification of what type may be thrown by a do block. The review period now runs through December 7. The following post on the original thread links to the PR...
Avatar
omochimetaru 12/2/2023 2:21 AM
なるほど、と思いました
t_wakaru 1
Avatar
omochimetaru 12/5/2023 4:17 AM
If you have been fighting with Sendability when using #swiftlang concurrency, check out this new swift evolution proposal which has just entered review: https://forums.swift.org/t/se-0414-region-based-isolation/68805. The proposal introduces a new diagnostic that allows one to transfer non-Sendable values into other
4:17 AM
Sendable付けなくても良くなる(場合がある)やつ審査いり! (edited)
🙌🏻 3
Avatar
これはほしい
Avatar
omochimetaru 12/5/2023 4:26 AM
一方的に渡すだけだから安全でしょ(でもコンパイラは文句を言う)、みたいなの結構あるんすよね (edited)
Avatar
Taskをどのexecutorで実行するかを指定できるようになる機能のReviewが始まってました。 Task(on: executor) { // starts and runs on the 'executor' await nonisolatedAsyncFunc() } Task.detached(on: executor) { // starts and runs on the 'executor' await nonisolatedAsyncFunc() } await withDiscardingTaskGroup { group in group.addTask(on: executor) { // starts and runs on the 'executor' await nonisolatedAsyncFunc() } } func nonisolatedAsyncFunc() async -> Int { // if the Task has a specific executor preference, // runs on that 'executor' rather than on the default global concurrent executor return 42 } https://forums.swift.org/t/se-0417-task-executor-preference/68958 (edited)
Hello Swift community, The review of SE-0417 "Task Executor Preference" begins now and runs through December 26th, 2023. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager via the forum ...
👀 2
Avatar
これないといろいろ不都合あったけどこれでようやくexecutorまわり完成しそうな気がする
4:24 AM
今まではactorの中でTaskを発火させて暗黙的なコンテキスト継承、globalActor、isolated引数でactor指定するくらいでしか指定できなくて、かつ全部シリアルキューだったのが問題だった
t_wakaru 2
Avatar
これは嬉しい
Avatar
The review of SE-0414: Region-based isolation ran from December 4th through December 18th. The Language Steering Group has decided that the proposal is returned for revision. The Language Steering Group believes that this proposal addresses an important usability problem in the strict concurrency checking model that eliminates a source of fals...
6:06 PM
Region解析にバグというか穴が2つあるらしくていったん見送られた (edited)
6:07 PM
Hey folks, The review of SE-0413: Typed throws ran from November 16th through December 7th. SE-0413 has been accepted. Most of the major questions about the proposal were worked out during the pitch phase, and review focused on a few remaining details: Parentheses A number of people expressed that they did not like the throws(CatError) synta...
6:07 PM
typed throwsはaccept
👏 4
6:07 PM
Swift5.10に入るんかね?
Avatar
Upcoming Feature Flag: FullTypedThrows なので正式にはSwift6からかもしれないですね。 今のところ、experimental feature flagに TypedThrows付けるとmainブランチでは動くみたいです。
Avatar
To mitigate this source compatibility problem in Swift 5, throw statements will be treated as always throwing any Error. In Swift 6, they will be treated as throwing the type of their thrown expression. One can enable the Swift 6 behavior with the upcoming feature flag named FullTypedThrows.
10:12 AM
5から使えるけど、throw FooError()の推論が、下位互換を失う挙動に変わるのが、そのフラグ,という事だと思う
Avatar
なるほど!ありがとうございます! このPRですね。 https://github.com/apple/swift/pull/69225
Swift5.10に入るんかね?
typed throwsのPRを眺めてみたのですが、今のところ release/5.10には入れてはいなさそうに見えますね。
(edited)
10:18 AM
typed throwsがAcceptedになったので https://forums.swift.org/t/pitch-typed-throws-in-the-concurrency-module/68210 も動きそうですね。
Hey everyone, In the latest typed throws pitch, the adoption of typed throws in the standard library was removed due to the pitch growing quite large by itself and the large surface area of both the Swift and Concurrency module that might adopt typed throws. This pitch covers the adoption of typed throws inside the Concurrency module. There ar...
Avatar
Region解析にバグというか穴が2つあるらしくていったん見送られた
そういえば、Function Body Macrosも見送られてましたね。 Limitations of preamble and body macros: While the proposed design for preamble macros makes it possible to inject both prologue and epilogue code using defer, the inability to examine a thrown error or the function's return value were cited as difficult limitations. Lack of closure support: While the Language Steering Group does agree that it would be useful to have this capability, applying function body macros to closures presents a number of unique challenges that do not apply to regular function declarations. For this reason, we are comfortable slicing closures off as a future direction for their own proposal. https://forums.swift.org/t/returned-for-revision-se-0415-function-body-macros/69114
(edited)
Hi all, The review for SE-0415: Function Body Macros ran from December 6rd to December 20th. The Language Steering Group has decided to return the proposal for revision. Feedback on this proposal mostly centered around concerns that the two forms of macros specifically proposed would not be sufficient to express the kinds of transformations th...
Avatar
Avatar
shiz
Region解析にバグというか穴が2つあるらしくていったん見送られた
そういえば、Function Body Macrosも見送られてましたね。 Limitations of preamble and body macros: While the proposed design for preamble macros makes it possible to inject both prologue and epilogue code using defer, the inability to examine a thrown error or the function's return value were cited as difficult limitations. Lack of closure support: While the Language Steering Group does agree that it would be useful to have this capability, applying function body macros to closures presents a number of unique challenges that do not apply to regular function declarations. For this reason, we are comfortable slicing closures off as a future direction for their own proposal. https://forums.swift.org/t/returned-for-revision-se-0415-function-body-macros/69114
(edited)
ふーむ、なるほど
Avatar
omochimetaru 2/10/2024 3:07 AM
Hi everyone, We'd like to share a pitch of a distributed actors feature we've been working on for a while now. This proposal extends distributed actor capabilities in one important aspect: it allows a proper server/client split of distributed applications! 🎉 When we first introduced distributed actors, many developers were asking about using t...
3:08 AM
distributed actorのサーバー/クライアントサポート
3:09 AM
プロトコルを介せるようになって、クライアントがサーバーアクターの真の型を知らなくても呼び出せる バイナリが異なってても接続できる
3:09 AM
これまでは難しかったらしい
3:09 AM
それと、プロトコルにマクロを付けると、接続用のユーティリティが生成される
3:10 AM
$Greeterみたいな、プロトコル名の頭にドル記号がついた型を生成するマクロらしい
3:10 AM
新しいドル記号のユースケースで面白い 普通にプロトコルにstaticメソッド生やした方がわかりやすそうだけど、それだと意味違うからダメなんやろな
Avatar
norio_nomura 2/29/2024 6:36 AM
Swift 5.9.1で@OptionSetがstdlibに追加されて、その後しれっと削除された様なのですが、SwiftMacro内には存在し続けて配布が続いている様です。これってどういう扱いになってるのでしょう? @swift-5.9.2 @swift-5.10.1 -Xfrontend -print-ast-decl @attached(member, names: named(RawValue), named(rawValue), named(`init`), arbitrary) @attached(extension, conformances: OptionSet) public macro OptionSet<RawType>() = #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") @OptionSet<UInt8> struct ShippingOptions { private enum Options: Int { case nextDay case secondDay case priority case standard } static let express: ShippingOptions = [.nextDay, .secondDay] static let all: ShippingOptions = [.express, .priority, .standard] } struct ShippingOptionsWithNoMacro { private enum Options: Int { case nextDay case secondDay case priority case standard } static let express: ShippingOptions = [.nextDay, .secondDay] static let all: ShippingOptions = [.express, .priority, .standard] }
Avatar
Avatar
norio_nomura
Swift 5.9.1で@OptionSetがstdlibに追加されて、その後しれっと削除された様なのですが、SwiftMacro内には存在し続けて配布が続いている様です。これってどういう扱いになってるのでしょう? @swift-5.9.2 @swift-5.10.1 -Xfrontend -print-ast-decl @attached(member, names: named(RawValue), named(rawValue), named(`init`), arbitrary) @attached(extension, conformances: OptionSet) public macro OptionSet<RawType>() = #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") @OptionSet<UInt8> struct ShippingOptions { private enum Options: Int { case nextDay case secondDay case priority case standard } static let express: ShippingOptions = [.nextDay, .secondDay] static let all: ShippingOptions = [.express, .priority, .standard] } struct ShippingOptionsWithNoMacro { private enum Options: Int { case nextDay case secondDay case priority case standard } static let express: ShippingOptions = [.nextDay, .secondDay] static let all: ShippingOptions = [.express, .priority, .standard] }
swift510 BOT 2/29/2024 6:36 AM
@attached(member, names: named(RawValue), named(rawValue), named(`init`), arbitrary) @attached(extension, conformances: OptionSet) public macro OptionSet<RawType>() = #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") internal struct ShippingOptions {
1.36 KB
Avatar
Avatar
norio_nomura
Swift 5.9.1で@OptionSetがstdlibに追加されて、その後しれっと削除された様なのですが、SwiftMacro内には存在し続けて配布が続いている様です。これってどういう扱いになってるのでしょう? @swift-5.9.2 @swift-5.10.1 -Xfrontend -print-ast-decl @attached(member, names: named(RawValue), named(rawValue), named(`init`), arbitrary) @attached(extension, conformances: OptionSet) public macro OptionSet<RawType>() = #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") @OptionSet<UInt8> struct ShippingOptions { private enum Options: Int { case nextDay case secondDay case priority case standard } static let express: ShippingOptions = [.nextDay, .secondDay] static let all: ShippingOptions = [.express, .priority, .standard] } struct ShippingOptionsWithNoMacro { private enum Options: Int { case nextDay case secondDay case priority case standard } static let express: ShippingOptions = [.nextDay, .secondDay] static let all: ShippingOptions = [.express, .priority, .standard] }
@attached(member, names: named(RawValue), named(rawValue), named(`init`), arbitrary) @attached(extension, conformances: OptionSet) public macro OptionSet<RawType>() = #externalMacro(module: "SwiftMacros", type: "OptionSetMacro") internal struct ShippingOptions {
1.36 KB
Avatar
norio_nomura 2/29/2024 6:39 AM
EvolutionへのPitchは存在してて、正式版はなさげ? https://forums.swift.org/t/pitch-optionset-macro/63547
Hi Swift Evolution, Here's a proposal for a macro to facilitate declaring option sets. Note this relies on SE-0389, currently in review. Proposal PR can be found here. Option Set Declaration Macro Proposal: SE-NNNN Authors: Doug Gregor, Ben Cohen Review Manager: TBD Status: Awaiting review Implementation: DougGregor/swift-macro-examples#1...
Avatar
norio_nomura 2/29/2024 7:56 AM
Evolution通ってないなら、PR書くだけで機能追加してくれたりするかな。
Avatar
Evolution通ってない実験的な機能だから削除したと言っているのかなと思いました。(だから誰かPR作ってEvolution通して欲しいということなのかと) If the feature is merged but doesn’t seem to be making progress, it may be removed. For what it’s worth, that has happened to work by Apple engineers. https://forums.swift.org/t/pitch-optionset-macro/63547/167 Embedded buildには残っているですかね? https://github.com/apple/swift/pull/69197 (edited)
It’s not reserved only for certain people. As code owners, we make a judgment call based on an informal assessment of the feature’s prospects and how much work it would take to maintain it as a branch for a few months. Sometimes the Language Working Group gets asked for their opinion on the first point. If the feature is merged but doesn’t seem...
It seems OptionSet was elided from embedded builds. This corrects that and includes it within those builds.
Avatar
Avatar
shiz
Evolution通ってない実験的な機能だから削除したと言っているのかなと思いました。(だから誰かPR作ってEvolution通して欲しいということなのかと) If the feature is merged but doesn’t seem to be making progress, it may be removed. For what it’s worth, that has happened to work by Apple engineers. https://forums.swift.org/t/pitch-optionset-macro/63547/167 Embedded buildには残っているですかね? https://github.com/apple/swift/pull/69197 (edited)
norio_nomura 3/2/2024 12:17 AM
なるほど、ありがとうございます。
12:18 AM
Embedded buildには残っているですかね?
Embeddedとか関係なく、SwiftMacroライブラリに実装は残っててstdlibへの登録が削除されてるみたいですね。
(edited)
Avatar
norio_nomura 3/2/2024 12:32 AM
あ、@OptionSet少し使ってみましたが、enum OptionsのメンバーにつけたDoc commentが生成されたメンバに引き継がれないので、使わない方が便利という結論になりました。
😢 5
Avatar
omochimetaru 3/8/2024 4:48 AM
Hello, Swift community! The review of SE-0426: BitwiseCopyable begins now and runs through March 20th, 2024. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager by DM. When contacting the...
4:49 AM
なんかめっちゃパフォーマンス指向な仕様が出てきた
4:50 AM
ValueWitness関数を使うジェネリックコードの生成をカットできるらしい あれ重いから良さそう
4:51 AM
embed系のモチベーションなんかなあ
Avatar
モジュールまたいでるときのジェネリック関数の呼び出しが速くなりそうですね
Avatar
omochimetaru 3/8/2024 7:11 AM
そうですね。最適化のヒントにすぎないようなものを型情報で取りまわすのが面白い。
Avatar
omochimetaru 3/9/2024 6:59 AM
Hello, Swift community! The review of SE-0427: Noncopyable Generics begins now and runs through March 22nd, 2024. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager by email or DM. When ...
7:00 AM
noncopyable generics、実装大変そうだったけどできたみたいだ
7:01 AM
従来はgeneric parameter typeは常にcopyableだったから、optionalに入れられないなど制約が多かった
Avatar
omochimetaru 3/9/2024 7:47 AM
~CopyableはデフォルトのCopyableの打ち消しであって
7:48 AM
「コピー制約がない事」であって、「コピーできない制約」ではないから
7:48 AM
<T: ~Copyable>にはIntなども準拠するのが
7:48 AM
ちょっとコツがあるね
Avatar
Avatar
omochimetaru
そういう感じでSEに対応付けてほしいですね
そういえば結局 Swift Evolution には紐付けない形で Upcoming Feature Flag が追加されてました.(のでやっぱりフラグ一覧はソースコードから知るしかなさそう) https://github.com/apple/swift/blob/761812af5f7f2009f6d3e00bfd87379992f54db1/include/swift/Basic/Features.def#L176 (edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
えーw evolution通して!
😂 3
Avatar
omochimetaru 3/12/2024 6:20 PM
✍️ Playdate developers: the Swift team's newly-announced embedded language support means you can now write Playdate games in Swift! Read more about it on the Swift blog: https://www.swift.org/blog/byte-sized-swift-tiny-games-playdate
6:21 PM
Swift公式ブログで組み込みSwiftのアナウンス来た、しかもPlaydate
Avatar
try! Swiftのデモのネタが潰れてしまった
Avatar
持ってるPlaydate ファームウェアアップデートでブリックして無用の長物となっていて、サポートに問い合わせてもなにも返事がなくて、なくてなんだかなーって思ってる
Avatar
自分は電池の減りが異常でPanicに問い合わせたら交換品送ってくれたのですがサポート体制がまだ整って無さそうですね
t_naruhodo 2
1:35 AM
Panicというか warranty@play.date か。中の人同じでしょyけど。
Avatar
omochimetaru 4/2/2024 3:29 AM
Fellow Swift enthusiasts, I am delighted to share an update on our community support goals that the Core Team announced last year in an announcement regarding creating new steering groups. For those of you who may have forgotten, the distinction between a workgroup and a steering group is: Steering groups are responsible for the overall stra...
3:30 AM
プラットフォームステアリンググループが立ち上がったよというアナウンスで
3:30 AM
どういうメンバーでどういう領域にSwiftを広げていくかみたいな方向性が示されてる
3:31 AM
Fermyon社(僕はよく知らない)のDanielleさんがWASM on cloudを推進するという部分と (edited)
3:32 AM
KubaさんがiOSデバイスなどのセキュアエンクレイブで走るsepOSに組み込みSwiftを展開しているという部分が特に興味深かった (edited)
3:33 AM
組み込みSwiftが結局何を狙ってるのかあんまりはっきりしてなかった(どこかでは出てたのか?)と思うけど
3:33 AM
セキュリティチップで使うつもりだったんですね
3:34 AM
たしかにCやCxxだとheartbleed脆弱性とかも言語仕様のせいみたいなところあったしね でもRustじゃないんだなー
3:35 AM
あとWASMのトレンドはブラウザじゃなくてVMですね、マクロ実行環境の話もそうだし (edited)
Avatar
へぇ、Fastly以外にもSwiftWASMでクラウドコンピューティング提供してるとこあったんですね
Avatar
omochimetaru 4/2/2024 3:37 AM
だよね、これ、Fastlyとはまた別よね
3:38 AM
3:40 AM
FastlyはWASMを後から追加したって感じだけど、Fermyonのシステムはそもそも基盤からWASMを中心にしたアーキテクチャなのか・・・?
3:40 AM
なんかCGIみたいな構成してますね
Avatar
omochimetaru 4/2/2024 3:40 AM
ほんとだw HTMLをprintしとるw (edited)
3:41 AM
3:41 AM
この並びでJS(TS)とRubyとPythonがないの面白いな
Avatar
そのへんは専用SDKがありますね
Avatar
omochimetaru 4/2/2024 3:42 AM
あ、別のところにあるのか
3:42 AM
こういうのがあったりする
Avatar
omochimetaru 4/2/2024 3:42 AM
あ、 Fermyon ってフェルミ粒子のことか spinは素粒子のスピンに掛けてるのか
3:42 AM
オシャレだ・・・
Avatar
jsはあるけど、rubyはないな・・・
3:45 AM
RubyはインタプリタがWasmで動いてもコードとパックする部分はややハッキーだからまだ対応されてないのかもな
Avatar
omochimetaru 4/2/2024 3:49 AM
ビジネス的には今サーバサイドで利用が多い言語から対応するのがいいと思うけど
3:49 AM
Swiftあるのすごいな
3:50 AM
むしろFermyonからサーバサイドSwiftデビューしてもらう構えだな
Avatar
GoとかRustはきれいな型が提供されてるので、CGI方式じゃなくてきれいな型も欲しいですね
3:52 AM
https://www.swift.org/blog/sswg-update-2024/ によると標準HTTPライブラリを提供したがってそうなので、それができたらそれに乗っかれると良さそう
naruhodo 1
Avatar
omochimetaru 4/2/2024 3:52 AM
ほんとだ、だいぶ違う
Avatar
Kishikawa Katsumi 4/2/2024 7:40 AM
Danielleさんは8、9年前にCocoaPodsを面倒見てくれてた人やなあ。
Avatar
omochimetaru 4/2/2024 7:57 AM
She was previously an iOS developer and maintainer of tools like CocoaPods, Nomad, and Kubernetes.
そのように紹介されてました。
(edited)
Avatar
omochimetaru 4/3/2024 10:36 PM
We’re pleased to introduce a repository of example projects that demonstrate how Embedded Swift can be used to develop software on a range of microcontrollers.
10:36 PM
Kubaさんからembedswiftの紹介だ
Avatar
アツイですね!!
Avatar
Embedded Swift の Swift パッケージから swift-mmio パッケージを依存に追加してビルドできないなぁと思っていたところだったので,ちょうど参考になるやつでした.
Avatar
omochimetaru 4/15/2024 1:35 AM
過去のこれ、誤りに気がついた https://discord.com/channels/291054398077927425/306995750418513920/1153874527114231809 public extension Database { func transaction<T>(_ closure: @Sendable @escaping (Database) async throws -> T) async throws -> T { try await self.transaction { db -> EventLoopFuture<T> in let promise = self.eventLoop.makePromise(of: T.self) promise.completeWithTask{ try await closure(db) } return promise.futureResult }.get() } この closure から @Sendable は外せない。 理由は、 closureEventLoopFuture の中で実行されている間に、 この executor は await しているだけでブロックはされていないから。 例えば closureActor の中にあった場合、 Actor のメソッド自体は interleave するから、同じisolationからこの closure を呼び出される可能性があって、 EventLoop threadとの並行実行になりうる。
Avatar
omochimetaru 4/15/2024 2:10 AM
こういう場合に transferring を使えば closure が呼び出し元でコピーが生き残ってない事を要請できて @Sendable が外せるんだろうか?
👀 1
Avatar
なんかできそうな気がしますね。 When a call passes an argument to a transferring parameter, the caller cannot use the argument value again after the callee returns. https://github.com/apple/swift-evolution/blob/main/proposals/0430-transferring-parameters-and-results.md#ownership-convention-for-transferring-parameters (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
t_oltsu 1
Avatar
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
5:10 AM
これはいらないと特定のasyncな呼び出しを特定のexecutorで実施することはできないですよねー。
5:11 AM
現状ではactorのfuncか、globalActorのがついてないと必ずなんらかのバックグラウンドスレッドで実行されちゃう (edited)
Avatar
omochimetaru 4/17/2024 5:25 AM
SerialExecutorであれば、それを指定したActorを作って、isolated引数にactorを渡せばそこで実行できるけど、特にisolated引数がないasync関数を持っていく方法はないと思います
Avatar
isoalted引数か...!
Avatar
omochimetaru 4/17/2024 7:17 AM
使われてるの見たことない。
Avatar
actor自体もロックの代わり以外で使われてるのを見たことがない
t_sorena 1
Avatar
omochimetaru 4/17/2024 7:33 AM
これactorにしたら楽かな〜って後から試すと、微妙に同期インターフェースにしてる部分があってだめ、みたいなことが多い
t_wakaru 4
7:34 AM
これから新規に作るシステムならactorで全部組むとかやれる気がしている
7:34 AM
あーでも、 XCTestCase.setup とかが同期を要求してて困ったりするんだよな
Avatar
XCTestCase.setUpasync throws 版が使えませんか? https://developer.apple.com/documentation/xctest/xctest/3856481-setup
Provides an opportunity to reset state asynchronously and handle errors before calling each test method in a test case.
Avatar
Avatar
ジュニア
XCTestCase.setUpasync throws 版が使えませんか? https://developer.apple.com/documentation/xctest/xctest/3856481-setup
class funcの方が同期しかないんですよね
t_naruhodo 1
😢 1
Avatar
transferringという名前を考え直したいようです。 the Language Steering Group has concerns about the spelling of the transferring modifier. The distinction between consuming a non-copyable type and transferring an object graph to a different concurrency domain is already subtle, and the fact that transferring sounds plausibly like an ownership modifier for non-copyable types adds to that problem https://forums.swift.org/t/returned-for-revision-se-0430-transferring-isolation-regions-of-parameter-and-result-values/71297
The first review of SE-0438 has concluded and the proposal has been returned for revision. Feedback from the review suggests that this is a good overall design with a strong motivation. However, the Language Steering Group has concerns about the spelling of the transferring modifier. The distinction between consuming a non-copyable type and tra...
Avatar
disconnected, sending, ownregionなどが出てますね
t_desune 1
Avatar
actor自体もロックの代わり以外で使われてるのを見たことがない
これもMutexが入ったことで変わってくるんですかねー https://github.com/apple/swift-evolution/blob/main/proposals/0433-mutex.md こんな話題があったのでちょっと気になりました。 https://forums.swift.org/t/se-0433-mutex-vs-actor-general-advice/71338
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
With SE-0433 adding Mutex to the standard library. I'm wondering what the general advice is regarding using Mutex vs actor. Here is a very simple case of a FIFO using Array as storage to illustrate. FIFO has two methods of enqueuing and dequeuing. In the first case, FIFO is implemented using an actor and an Array as storage and in the second c...
Avatar
理想的な空間ではactorが有効に機能するけど現実的な空間ではかなり頑張らないと安全にできない...
Avatar
https://github.com/apple/swift/issues/71174 これを引いた気がする
Description No response Reproduction struct Foo { init<A: Actor>(actor: isolated A) async { } } Stack dump 0 swift-frontend 0x00000001065d7d8c llvm::sys::PrintStackTrace(llvm::raw_ostream&...
7:40 PM
struct ではないけれど。
Avatar
再現コードみじか。
Avatar
structである必要はなくて、asyncのinitializerにisolatedがあればcrashする
Avatar
ああ、なるほど。
11:44 PM
Actorのinitなら色々とisolationのルールがあるから仕方なさそうだけど、structでも壊れるのは嫌ですね
Avatar
ちょっと嫌ですねこれは。isolatedが欲しいinitはあると思う。
Avatar
同期のinit + asyncなstatic funcに分けたらとりあえず回避できる?
Avatar
自身の初期化にawaitが必要とかだと無理かもしれない?
12:17 AM
状況次第かな...
Avatar
Try to workaround apple/swift#71174, which crashes Swift with an async initializer with isolated actor argument. I have no idea what I am doing.
👀 1
8:52 PM
Swift何もわからんけどこれなら動く
Avatar
omochimetaru 5/2/2024 6:50 AM
Hi everyone, I'm incredibly happy to be able to announce the selected projects for this year: Expansion of Swift Macros in Visual Studio Code by @lokeshtr and mentor @ahoppen and @adam-fowler Swift-etcd: A Native Client for Seamless Integration with etcd Servers by @ayushi2103 and mentor: @FranzBusch Lexical scopes for swift-syntax by ...
6:50 AM
GSoCプロジェクトが決まったらしい
6:50 AM
Expansion of Swift Macros in Visual Studio Code by @lokeshtr and mentor @ahoppen and @adam-fowler Swift-etcd: A Native Client for Seamless Integration with etcd Servers by @ayushi2103 and mentor: @FranzBusch Lexical scopes for swift-syntax by @MAJKFL and mentor: @Douglas_Gregor Add a deploy SwiftPM plugin and a Swift-based DSL to the Swift runtime for AWS Lambda by @esraaeiid and mentor: @sebsto (edited)
6:51 AM
WASMマクロランナーはどこへ・・・? (edited)
6:52 AM
AWS LambdaのSwift用のDSL?はなんのこっちゃだな、気になる (edited)
Avatar
Avatar
omochimetaru
WASMマクロランナーはどこへ・・・? (edited)
GSoC一切関係なく勝手に進んでる
Avatar
Avatar
Yuta Saito
GSoC一切関係なく勝手に進んでる
omochimetaru 5/2/2024 6:53 AM
進んでるからむしろGSoCの枠組みに載せない方が捗って良いってことかしら。
Avatar
良くも悪くも期間区切られちゃうしそういう側面もあるかもしれない
7:36 AM
よくわかんないけどTerraformみたいなJSONがあるんやな
7:36 AM
こういうかっちりしたデータ構造はResultBuilderにしてもあまり嬉しくなくて 普通に struct で構築したらいいと思うけどな (edited)
Avatar
Cloud FormationといってTerraformのAWS専用版みたいなやつがあるんですよね
Avatar
omochimetaru 5/2/2024 7:37 AM
これがCloud Formationなのか。
Avatar
AWSリソースしか扱えないし状態が壊れやすいので評判はよくない
Avatar
omochimetaru 5/2/2024 7:38 AM
それはどっちも割と嫌やな
Avatar
omochimetaru 5/4/2024 4:10 PM
https://t.co/HDfWBl6B8G
Rustの標準ライブラリにはunsafe関数に関する多くの事前条件チェックが実装されているが、標準ライブラリは通常リリースモードで配布されるので、ほとんどの開発者はこのチェックを全く実行できていなかった。
4:10 PM
このアサーションをコード生成まで遅延させることで、ユーザー自身のデバッグ設定に基づいて実行できるようになった
例えば、slice::from_raw_parts は非ヌルでアライメントされたポインタを要求する。アライメントされていないポインタはUBをもたらし偶然不幸にも「動作してしまう」かもしれない
4:10 PM
この話題、Swiftにも全く同じ課題がありそうで気になった。
4:11 PM
stdlibの中にdebug/release気にしたいろんな安全機構があるけど、みんなが使ってるのはreleaseだから。
4:12 PM
そもそもメジャーな環境のiOSではstdlibがprebuiltな時点で詰んどるけど
Avatar
だいたいのpreconditionはinlinableなコード片になっていてswiftmodule/swiftinterfaceに露出しているのでimportする側のユーザコード生成時にコンパイル時ビルドモード分岐が確定します
Avatar
omochimetaru 5/4/2024 4:13 PM
ああ〜〜〜 @alwaysEmitIntoClient だったら遅延してるのか!!
4:14 PM
逆なのか Swiftはとっくに解決済みだったのか
Avatar
最初から解決してた
Avatar
omochimetaru 5/4/2024 4:14 PM
すげ〜
4:15 PM
Rustと対比するとABI安定性を意識した設計だったのがうまく機能してるのか?
4:15 PM
Rustは基本API互換性だけでフルビルドする世界観だからstdlibだけ特殊だったのかなというイメージ
Avatar
Rustだとprebuiltなライブラリを配布することがstd以外に無い世界観だから。。
👉 1
4:16 PM
そうそう
Avatar
omochimetaru 5/4/2024 4:16 PM
言語仕様レベルでそう言う事を取り扱うコンセプトが作り込まれていなかったんや (edited)
4:18 PM
おもしろいな SwiftがABIの関心が強いの、言語の発展において足枷になりがちと感じてたけど、こういうメリットはあるな
Avatar
Hi everyone! SE-0301 "Package editing commands" was accepted a while ago, but the implementation never managed to land. I went ahead and implemented the three commands it specifies: swift package add-product swift package add-target swift package add-dependency Now, it didn't take very long for me to want to add another command to edit packa...
12:22 AM
SE-0301実装したけど、 $ swift package foo が増えすぎてるから、 $ swift package manifesto foo みたいなサブコマンド空間に整理するのはどうですか、みたいなスレ
12:22 AM
個人的には賛成だ
Avatar
norio_nomura 5/28/2024 1:17 AM
サブコマンドにshell completionが効けば増えてもどうとでもなる気が。効かない現状だと整理しても、その過程で混乱するだけに思える。 (edited)
Avatar
omochimetaru 5/28/2024 1:21 AM
単語が add から始まるから(記憶がおぼろげだと)補完を引き出すのが難しくないですか? (edited)
1:22 AM
manifesto とか target だったら、 全件補完で見た時に探してるものだと推測しやすいし、 man まで打ってから、補完して、その次はマニフェスト編集に使えるサブコマンドが一覧されるから便利。
Avatar
norio_nomura 5/28/2024 1:23 AM
ああ、SE-0301に関してはそうですね。
Avatar
omochimetaru 5/28/2024 1:24 AM
ああ、僕の要約が悪いのか。Douglasさんは他の既存コマンドのグルーピングの話までは踏み込んでなさそう (edited)
Avatar
norio_nomura 5/28/2024 1:26 AM
現状、swift-packageへのシンボリックリンクになってるサブコマンド群のほとんどにshell completionが効かないですよね。
Avatar
omochimetaru 5/28/2024 1:29 AM
そうですね。これは効いた方が嬉しい。
1:29 AM
この辺やった事ないけど、 swift-argument-parser を使ってるから、補完定義ファイルも生成できるんじゃあないんかな
1:30 AM
インストーラーの口がないんだろうか
Avatar
We are proposing a new abstraction for safe, direct access ot memory: Span. This is a substantial update to our earlier pitch, "Safe Access to Contiguous Storage", and is a companion to the Non-Escapable Types proposal. Some of the changes in this version are: The type's name is changed to Span. As a name, Span is short, pithy, precedented, ...
11:21 PM
メモリアドレスと要素数を持つSpanの提案 ArraySliceとかSubstringみたいなコレクションの一部を切り出す型だけど、それらと違って根元のコレクションと独立で、メモリ領域を抽象化する 特筆すべきはnon Escapableになっていること
11:22 PM
ポインタと違って脱出させられないから本体が削除されてdanglingになることがない
Avatar
ライフタイム依存関係の提案も前提にしていて、Spanを返す本体が生きてる間しか使えないっぽい borrowing funcの場合に dependsOn を自動適用するらしい https://github.com/swiftlang/swift-evolution/blob/e814e62c17741dfe82e2f55eb1d751157c77a853/proposals/NNNN-lifetime-dependency.md#implicit-lifetime-dependencies
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution
11:32 PM
Rustでいうところのlifetime parameterを、明示的な型パラメータとして導入することなしに、関数のアトリビュートとかでフロー解析的に対応しようとしているのかな・・・?
Avatar
可能ならおしゃれだけど、人間が背景理解してちゃんと使えるのかな (edited)
Avatar
omochimetaru 6/27/2024 5:20 AM
ある程度読んだ dependsOnを書くのがまずあって、省略できるパターンもあるようだ
naruhodo 1
5:21 AM
割と自然な仕様に見えるので使いたい人は使えるんじゃないか
Avatar
Hi all, The review of SE-0439: Allow trailing comma in comma-separated lists concluded on July 14, 2024. The language steering group has decided that the proposal should be accepted with modifications. Particularly with changes in the language and ecosystem since consideration of SE-0084, members of the steering group agree that there's some b...
12:00 AM
ケツカンマ、決着
12:01 AM
左右対象なカッコの中はケツカンマOK
12:02 AM
継承リストとif条件みたいな、開きカッコが後ろにくるやつとかはNG
12:03 AM
それとtype positionの[Int,]はNG
12:04 AM
結局どの状況が許容されるのか列挙されてないからわかりにくいンゴね
Avatar
Kishikawa Katsumi 7/19/2024 12:29 AM
いつから有効になるんかな。こういう文法の変更は早いほうがいいから6にねじ込んでくれないかな。
Avatar
たしかに、新しい記法が古いコンパイラじゃどうにもならない
12:33 AM
Swift 6.0 Release Process This post describes the release process, and estimated schedule for Swift 6.0. Snapshots of Swift 6.0 Downloadable snapshots of the Swift 6.0 release branch will be posted regularly as part of continuous integration testing. As support is available, snapshot downloads will be added for newly supported platforms. Once ...
12:34 AM
6.0リリースブランチへの追加変更はSE通過が必要で個別のインパクトを考慮して決める
12:34 AM
ルール的には入れる事もできそうか?
Avatar
まだ pitch とかは出ていなかった気がしますが,Swift でも Rust みたいに unsafe な API を呼び出すことができる箇所を限定的かつ明示的にすることでそれ以外の箇所が safe であることを保証する試みが...? https://github.com/swiftlang/swift/pull/75413
Allow any declaration to be marked with @unsafe, meaning that it involves unsafe code. This also extends to C declarations marked with the swift_attr("unsafe") attribute. Under a separate...
Avatar
うまくいくのかな? array[1] とか optional! もunsafeだけど
Avatar
内容見る限り、array[1]optional! はUnsafe扱いしてないっぽいですね、optional.unsafelyUnwrapped の方は対象ですが (edited)
Avatar
optiona!とかは安全ですよね?
Avatar
変なメモリアクセスさせない、という意味では安全だと思います
2:30 AM
多分Swift的にも、Unsafe はメモリアクセスの意味だと思います
2:35 AM
% cat test.swift var someInt: Int? = nil print(someInt.unsafelyUnwrapped) % swift -O test.swift 0
Avatar
omochimetaru 7/24/2024 3:04 AM
なるほど。memory safetyの話か。
Avatar
クラッシュする (fatal error が起こる) は safe なんですね
12:06 PM
コンパイル時値パラメータの実装をAzoyさんが出してる
12:07 PM
フォーラムでは動きないけどなんだろうね
12:09 PM
cxxかembed関連で欲しいのかな
12:09 PM
Azoyさんエグいテーマ良く実装してる
Avatar
Avatar
omochimetaru
フォーラムでは動きないけどなんだろうね
固定長配列関連では Forums とか別 Discord コミュニティとかで度々議論に上がってるのを見かけますね.(Azoy さんの動機がそれかどうかはわかりませんがテストコードの固定長 Vector とかをみる限り意識はしてそう) https://forums.swift.org/t/approaches-for-fixed-size-arrays/58894
We're looking into how best to give Swift the equivalent functionality of fixed-size arrays in C or other systems languages. Here are some directions I've been considering, and I'd love to hear the community's ideas and reactions: Tuples as fixed-size arrays This was the approach outlined in our most recent pitch on the subject: we already use...
Avatar
ついに固定長配列が来るのか〜 concurrency safetyの次の波かしら
Avatar
Hi everyone. For Embedded Swift and other low-overhead and performance sensitive code bases, we're looking into improving Swift's support for fixed-capacity data structures with inline storage. @Alejandro has been working on adding support for integer generic parameters, which is one step towards allowing these sorts of types to be generic over ...
11:33 PM
値パラメータのアナウンスとドラフトが出ました!
t_oltsu 6
11:34 PM
可変長パラメータとも組み合わせられるらしい→これは将来の話だった (edited)
11:36 PM
For Embedded Swift and other low-overhead and performance sensitive code bases, we're looking into improving Swift's support for fixed-capacity data structures with inline storage.
11:36 PM
組み込みなどのパフォーマンス最適化のためだそう
Avatar
読んできたけど参照はできても演算はできないらしい
11:54 PM
行列の掛け算は作れるけど結合は作れない
11:55 PM
双方向型推論のサポートが必要で制限が必要らしい
Avatar
omochimetaru 9/5/2024 4:39 PM
We've talked about this a lot during early actor days, and currently the answer really might be to use distributed actor + process isolation. There's recent thread about this: Runtime extensibility via distributed actors, as well as a demo here: GitHub - martiall/swift-subprocess-distributedactors, using just pipes and how one could even run th...
4:40 PM
fatalErrorセーフにする機能について話されていて、actorシステムでエラー復帰する話にも触れられているが、
4:40 PM
それについてコンラッドさん曰く、プロセスを分離してその間をdistributed actorで繋ぐのが良いと書いてる
👀 3
4:41 PM
言語のモデルとうまくフィットするし良いやり方だと思う アーランと比べると本物のプロセスになってる分オーバーヘッドはありそうだけど
Avatar
ユースケースにFluentのクラッシュが示されてて、わかるw
11:19 PM
今回の例だとDBに触るコンポーネントがdistributed actorになるということか
Avatar
omochimetaru 9/5/2024 11:20 PM
それもちょっと変な話よね 視点や粒度の違う話が流れてると思う
Avatar
機能的にはrpcの部分しか使ってないから過剰だし、手間も大きいよなぁ
Avatar
fatalErrorで困るの分かる
Avatar
Avatar
omochimetaru
コンパイル時値パラメータの実装をAzoyさんが出してる
マージされて最新の snapshot で試せるようになってますね.
Avatar
Avatar
omochimetaru
ついに固定長配列が来るのか〜 concurrency safetyの次の波かしら
また Azoy さんでした.固定長配列型の実装. https://github.com/swiftlang/swift/pull/76438
This PR adds a new type to the standard library Vector who is a fixed size array. One can define a value of Vector like so: var numbers = Vector&lt;3, Int&gt;(repeating: 0) numbers[0] = 1 n...
Avatar
omochimetaru 9/13/2024 4:14 AM
おお?Vectorも公式に実装されるんですね
4:18 AM
実装おもしろいな。 プロパティが何も書いてなくて、 @_rawLayout(likeArrayOf: Element, count: Count, movesAsLike) が直接レイアウトを決めてて、 実装はポインタ操作してるw
4:19 AM
文法としてもNパラメータをタプルのようなものに展開するための言語機能がそもそもないのか
4:20 AM
というかVectorがそれなのか? 一般人はこのVectorを再利用すればN要素をもつ型が普通に書ける
Avatar
Avatar
omochimetaru
実装おもしろいな。 プロパティが何も書いてなくて、 @_rawLayout(likeArrayOf: Element, count: Count, movesAsLike) が直接レイアウトを決めてて、 実装はポインタ操作してるw
その辺は Azoy さんが swift-collections に追加された Cell で同じようなのを見ました. https://github.com/apple/swift-collections/pull/398 (edited)
This adds a Box type who is a noncopyable type that provides a safe abstraction for owning a heap allocated value as well as a Cell type who is a noncopyable type that provides an inline value with...
Avatar
omochimetaru 9/13/2024 5:08 AM
こんなのがあるんですね BoxはわかりやすいけどCellはいつ使うんだ?Inoutで取れるのが使いどころなんだろうか
Avatar
~Copyable な型を多用していると class が使えないので欲しくなりますね.Rust の Cell と同じ使い道という認識です.
Avatar
public subscript() -> T { @_transparent unsafeAddress { UnsafePointer<T>(pointer) } @_transparent nonmutating unsafeMutableAddress { pointer } }
7:12 AM
こんなの書けるんですね
7:13 AM
let intOnHeap = Box<Int>(0) XCTAssertEqual(intOnHeap[], 0) なるほどそのまま引数のないsubscriptになるのか
Avatar
omochimetaru 9/13/2024 7:16 AM
Shareable mutable containers.
ふむふむ
7:18 AM
Cell
• 不変の外見で可変性を持つ:Cell<T>は、内側のデータを変更するための可変性を提供しますが、その外見は不変です。つまり、所有権があっても参照や借用を用いずに内部のデータを変更できます。これにより、通常では不可能な状況での内部の可変性(interior mutability)を実現します。
(edited)
7:19 AM
インテリアミュータビリティってアゾイさんも書いてるな、なるほどこれがキーワードなのか
Avatar
I look forward to having non-escapable types in the language! A bit of a niche question, but… If I need to refer to "any metatype", I can no longer say Any.Type since the addition of move-only types, and must instead say any ~Copyable.Type. With the addition of ~Escapable, "any metatype" becomes any (~Copyable & ~Escapable).Type… I think? This...
11:45 AM
Hi everyone, The review of SE-0447 "Span: Safe Access to Contiguous Storage " begins now and runs through October 1, 2024. In order to try this feature out, the proposal authors have provided toolchains: Toolchain for macOS: https://ci.swift.org/job/swift-PR-toolchain-macos/1498/artifact/branch-main/swift-PR-76406-1498-osx.tar.gz Toolchain ...
11:46 AM
not EscapableとSpanが一気に審査来た
11:47 AM
これはC並みに速そうで良いですね
Avatar
extension ContiguousArray { borrowing func span() -> dependsOn(self) Span<Element> { ... construct a Span ... } } わーお
Avatar
それはどこに書いてあった?
Avatar
こっちはまだフォーラム入りはしてないかな でも前ドラフト読んだ
12:28 PM
Rustがフォーマルに型システムと統合してるのに対して
12:28 PM
アドホックな文法になってるのが面白い
12:28 PM
rethrows とかと似ている。
12:29 PM
これで大丈夫なのかどうかは経験が浅くてわからんけどなんとなくユースケース足りそうには見える
Avatar
ピッチ眺めてたら明示的なライフタイムパラメータのあたりで白熱してて全部読みきれなかった https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency/69865/107
A question that has come up a few times in the discussion about lifetime dependency in this thread is, how will Swift's lifetime dependency feature stack up to Rust, both in the near term, and in the future? I took some time to explore this topic. This question is important to answer because Rust is perhaps the only other successful mainstream p...
👀 2
Avatar
長!勉強になりそう、あとでよも
Avatar
SwiftはRustの面倒な部分を全部言語側が吸収してるけど、 (edited)
2:17 PM
逆にこういう低レベルな操作をしたいときにユーザが書く手段を言語レベルで提供する必要があるんだなぁ
Avatar
Avatar
Yuta Saito
ピッチ眺めてたら明示的なライフタイムパラメータのあたりで白熱してて全部読みきれなかった https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency/69865/107
読んだ,面白かった
12:23 PM
提案してるモデルはRustより弱いけど、さらにその拡張としてnamed lifetimeというのを想定すると、
12:24 PM
それはRustで書けるパターンも書けるし、書けないパターンも書けてさらに強くなる
12:24 PM
それと、サンプル実装を見てみると、ユースサイトのコードでRustよりSwiftの方式の方が記述が少なくてノイズが減ってる いや、これは書き下してるだけで推論可能なのかなあ? (edited)
12:27 PM
ただRustのライフタイムが型パラメータ経由になってることでそれが表現の制約になってて、Swiftはそれを柔軟にコントロール可能になる
12:27 PM
これはJavaのジェネリクスとSwiftのプロトコルのassociatedtypeの関係に似てると思った
12:28 PM
named lifetimeの文法は見た目にもそれに似てる
12:31 PM
続く議論もめちゃ盛り上がってて重いな・・・
Avatar
Xcode 16 と iOS 18 や macOS 15 で、with checked continuation とかで、アクセス例外でまくってるぽい…
8:32 PM
自分でも他のデバイスで確認したけど影響でかそう (edited)
👀 2
8:33 PM
(自分の実機の手元では再現してないんだけど。) (edited)
8:34 PM
I want to raise the visibility of withCheckedContinuation crashes on Xcode 16 RC · Issue #75952 · swiftlang/swift · GitHub, which is a major, 100% reproducible crash for Catalyst users when using any of the global with* concurrency functions, except withUnsafeContinuation (apparently). This affects withCheckedContinuation, withTaskCancellationHa...
Avatar
https://github.com/RevenueCat/purchases-ios/issues/4177#issuecomment-2357299083 回避対応として withUnsafeThrowingContinuation に変えると起きないみたいで凌いでいるとかありました (辛い)
I have updated Purchases SDK to the latest version I have read the Contribution Guidelines I have searched the Community I have read docs.revenuecat.com I have searched for existing Github issues D...
Avatar
あまりにも基盤すぎるAPIが壊れてるのヤバいな
😨 7
Avatar
自分もunsafeでworkaroundしましたね、、unsafeなのがsafeなのウケる
🫨 5
Avatar
トゲナシトゲトゲだ
😂 3
Avatar
メモリ安全性にstrictモードを導入しようという話が出てましたね👀 This document proposes a path toward an optional “strict” subset of Swift that prohibits any unsafe features. This subset is intended to be used for Swift code bases where memory safety is an absolute requirement, such as security-critical libraries.  https://forums.swift.org/t/prospective-vision-optional-strict-memory-safety-for-swift/75090
Hello Swift Community, The Language Steering Group would like to gather feedback on a prospective vision for optional strict memory safety for Swift. Vision documents help describe an overall direction for Swift. The actual Swift changes for executing on the vision will come as a series of separate proposals, so concrete details (e.g., specifi...
Avatar
あとでじっくり読もうと思いますが、配列のsubscriptアクセスはどうするんだろう?
Avatar
僕もざっとしか見られてないのですが、subscript(unchecked:) (Spanのプロポーザルで導入予定)を使うと書いてありますね。
Avatar
読みました
12:04 AM
勘違いしていて、memory safetyとruntime failureは別ですね
12:05 AM
これはmemory safetyを実現する機能の話で、Array subscriptとか optional force unwrap (!) とかは実行時に止まるけどチェックは付いてるからメモリ安全ではある。
12:06 AM
メモリ安全性のないAPIを全部禁止して、明示的にマークしたりスコープした範囲だけで使えるモードを考えているようです (edited)
12:07 AM
Optional.unsafelyUnwrapped は、! と違って、リリースビルドだとチェックも消えるらしい。ので nil の時はメモリ危険らしい。 (edited)
t_naruhodo 1
Avatar
omochimetaru 10/4/2024 3:41 AM
I've written up an early draft proposal for a new @abi attribute. This idea originated as a way to make subtler changes than @preconcurrency allows, but it looks like it will be a very flexible tool. It's sort of like a safer, more ergonomic version of @_silgen_name that's compatible with a lot more declarations. I'm also working on an early ...
3:41 AM
関数のシンボル名を指定する機能の提案
3:42 AM
従来のsilgen_nameと違って、生のシンボル名を指定するのではなく、Swiftの関数シグネチャを書いて指定できるのと、
3:42 AM
本当のシグネチャとバイナリ互換性が取れているかをチェックしてくれるらしい
3:43 AM
これにより、バイナリについての深い知識がなくても、安全にシンボル名を変更することができる
3:43 AM
これは、ライブラリのAPIを変更しつつも、ABIを変更しないで維持できるようにするために提供する
3:45 AM
具体例としてconcurrencyに対応する過程でsendingをつけたりアクター指定をつけたりしてABIが変わってしまうのを防ぎたいらしい
3:46 AM
これ見てて思ったけど、関係のあるユーザーがstdlibとシステムフレームワークを提供してるAppleの開発者ぐらいしか居ないので
3:46 AM
もしかしてこういうのがないからABI互換性を保つのが難しいせいでApple SDKのconcurrency対応が遅れているのか?と思った (edited)
t_naruhodo 2
Avatar
Avatar
kebo
また Azoy さんでした.固定長配列型の実装. https://github.com/swiftlang/swift/pull/76438
後追いで Azoy さんからなかなか読み応えのある pitch が出てました. https://forums.swift.org/t/vector-a-fixed-size-array/75264
Hi Evolution, with the recent pitch for Integer Generics, we finally have a way to express counts, capacities, and more for types. The most natural extension from that pitch in my opinion is finally letting Swift have fixed-size arrays. Here is my pitch for such a construct for the standard library. Please let me know what you think! Vector, a ...
Avatar
おお,読みたい
Avatar
読んだ おおむね普通
8:26 AM
Cの int [3](Int, Int, Int) にマッピングしてるところを Vector<3, Int> にしたいらしい 互換性フラグにするとのこと
8:26 AM
スレッドのほとんどは Vector って名前についての話になっててあまり面白くなかった
8:27 AM
Vector<N, T>Vector<T, N> のどっちがいいかの話と、 略記 [N x T] は面白い
t_desune 1
Avatar
ちょっと前から話されていたbacktikを使って色々と識別子にできようにするプロポーザルが出てましたね。 ↓みたいな感じです。 @Test func `square returns x * x`() { #expect(square(4) == 4 * 4) } case ColorVariant { case `50` case `100` case `200` } let color = Color(hue: .red, variant: .`100`) extension UIImage { static var `10.circle`: UIImage { ... } } https://forums.swift.org/t/se-0451-raw-identifiers/75602 import `myapp/extensions/widget/common/utils` // if explicit disambiguation is needed: `myapp/extensions/widget/common/utils`.SomeClass こんなこともできるのか (edited)
👀 1
👏 3
t_naruhodo 2
Avatar
Kishikawa Katsumi 10/24/2024 11:36 PM
先頭が数字にできるのいいね。
Avatar
数字シンボルはやりたいことある
12:06 AM
スラッシュ付きのモジュール名は、階層として認識してるわけじゃないから常にフルパスになってあんまり嬉しくなさそう
t_naruhodo 1
Avatar
modifyreadアクセサのpitchが5年の時を経て出てきましたね。 https://forums.swift.org/t/pitch-modify-and-read-accessors/75627
Hi Swift evolution, We are proposing modify and read accessors for properties and subscripts. The proposal would formalize the underscored _modify and _read accessors that have been unofficially available since Swift 5.0. These accessors allow copies to be avoided when changing and viewing a value's fields. As such, in their underscored form...
👀 2
Avatar
concurrencyとnon Copyableが終わってやっと進み始めたw
t_desune 1
t_kusa 1
11:09 PM
RawIdentifierが通ったよ
Avatar
Kishikawa Katsumi 12/4/2024 11:57 PM
これは使いどころがあるから使ってみたい。
Avatar
来年のフォーカスエリアが発表されてました.Swift Concurrency が簡単に使えるようにするというのと,ハイパフォーマンスなコードを書くためのローレベルな領域の強化と,C++ や Java など他言語との相互運用性強化の 3 つが書かれてました. https://forums.swift.org/t/swift-language-focus-areas-heading-into-2025/76611
With Swift 6.0 and the Swift 6 language mode now released, Swift language development under the Language Steering Group is now focused on three major areas: making Swift Concurrency easier to approach and adopt, providing powerful low-level language and library tools for high-performance programming and constrained environments, and improving ...
Avatar
みました、いずれもフォーラムやgithubで既に匂わせのあるものでしたね
t_desune 2
8:57 AM
個人的にはconcurrencyのアクセス容易性が眉唾なんだけどもうまくいくのかな
t_wakaru 1
8:57 AM
全くマルチスレッドにならないアプリケーションならグローバル変数も安全だ、とか書いてあるんだけど
8:58 AM
そんなのなくないか?ほとんどのユーザーはiOS開発だし・・・
Avatar
いいですね。順当に進化する感じ
8:59 AM
パフォーマンスはそんなに求めてないような気はする
Avatar
Java interop向けの改善で他の言語向けにもバインドしやすくなるとかは良さそう
9:00 AM
ABI情報のエクスポート機能とかの事でしょうね
Avatar
Avatar
omochimetaru
全くマルチスレッドにならないアプリケーションならグローバル変数も安全だ、とか書いてあるんだけど
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - hborla/swift-evolution
Avatar
それです、長いビジョンドキュメントがある
👍 1
Avatar
↑は読んでないですけど、暗黙的に全部MainActorということにして明示的にマークした処理だけ別Actorで動かすみたいなのでもアプリなら十分ワークしそう
Avatar
Avatar
Iceman
パフォーマンスはそんなに求めてないような気はする
ニッチだとは思いますが個人でブラウザエンジン開発しててここが強化されるのは嬉しいです.Ladybird という元 KHTML や WebKit やその他ブラウザを開発していた経歴のある人が立ち上げたプロジェクトがあって,ブラウザエンジンから開発されて GitHub の創業者とかからも出資を受けていたりするんですが,そちらでもちょっと前に C++ から Swift に乗り換えていくみたいな発表をしていて,同じように思うだろうなと思います.
Avatar
Avatar
kebo
ニッチだとは思いますが個人でブラウザエンジン開発しててここが強化されるのは嬉しいです.Ladybird という元 KHTML や WebKit やその他ブラウザを開発していた経歴のある人が立ち上げたプロジェクトがあって,ブラウザエンジンから開発されて GitHub の創業者とかからも出資を受けていたりするんですが,そちらでもちょっと前に C++ から Swift に乗り換えていくみたいな発表をしていて,同じように思うだろうなと思います.
なるほど。FirefoxはコアエンジンをどこかのタイミングでRustに乗り換えたみたいな話を聞いたことがありますが、そのようなケースの選択肢にSwiftが上がれるようになるのはいいですね
Avatar
Avatar
kebo
ニッチだとは思いますが個人でブラウザエンジン開発しててここが強化されるのは嬉しいです.Ladybird という元 KHTML や WebKit やその他ブラウザを開発していた経歴のある人が立ち上げたプロジェクトがあって,ブラウザエンジンから開発されて GitHub の創業者とかからも出資を受けていたりするんですが,そちらでもちょっと前に C++ から Swift に乗り換えていくみたいな発表をしていて,同じように思うだろうなと思います.
ladybirdってそんなプロの案件だったんだ
9:10 AM
ブラウザってまだやり残してる事あったのか?みてみよ
Avatar
Co-founder Chris Wanstrath shares his thoughts.
9:19 AM
they’re all funded by Google’s advertising empire. Chrome, Edge, Brave, Arc, and Opera all use Google’s Chromium. Apple receives billions to make Google the default search engine in Safari, and Firefox has a similar deal where they receive hundreds of millions each year.
9:19 AM
Googleのお金が絡んでないブラウザが必要らしい
Avatar
まあ元々は同じ作者が作っている SerenityOS という OS で動くブラウザが必要だったからこれのサイドプロジェクトとしてブラウザを作っただけだったので,後付けの理由だとは思いますがw https://serenityos.org
Avatar
セレニティOSも趣味かな?と思ってました
9:22 AM
Hello! I've been chatting about this with several Swift team members over the past few weeks/months, but I figured a post here on the forums was due. At the Ladybird Browser project we've been experimenting with more and more Swift C++ Interop lately. In general our goals with Swift fall into a few categories. The first one is that of course,...
9:22 AM
Swiftの話はここかな?
Avatar
でもエンジンを作る人が誰もいなくなっている世の中で割と実装が進んでいるエンジンなので,多様性の面で必要以上に期待されて持ち上げられている感じはありますね.
Avatar
Avatar
kebo
でもエンジンを作る人が誰もいなくなっている世の中で割と実装が進んでいるエンジンなので,多様性の面で必要以上に期待されて持ち上げられている感じはありますね.
Firefoxやモジラが結局経営的にキツくなった経緯を見ると、厳しそうだけどなあ
Avatar
Avatar
omochimetaru
Swiftの話はここかな?
どっちかというとこっちですね. https://x.com/awesomekling/status/1822236888188498031
We've been evaluating a number of C++ successor languages for @ladybirdbrowser, and the one best suited to our needs appears to be @SwiftLang 🪶 Over the last few months, I've asked a bunch of folks to pick some little part of our project and try rewriting it in the different
Avatar
つ、ついーとなのか
9:27 AM
メモリ安全なC++後継として評価されてるのは嬉しい
9:28 AM
Rustじゃないんだ
Avatar
@Zitroney_ @ladybirdbrowser @SwiftLang In the end it came down to Swift vs Rust, and Swift is strictly better in OO support and C++ interop.
Avatar
OOはオブジェクト指向?
👍 1
Avatar
この文脈ならそうっぽい
Avatar
classのことかなあ
Avatar
その辺について Andreas さんとかが話している動画が YouTube にあった気がします (edited)
Avatar
rustもdyn traitとかで同じ事できそうだけど、まあArc<>とか必要でめんどいからかなあ cxx interopはデカそう、現実的に (edited)
Avatar
Rc<RefCell<dyn T>> 書きたくなさすぎる
Avatar
継承ってRustにはないですよね?
Avatar
継承はない認識
Avatar
無いと思います。コンポジションするしか無い
Avatar
でもSwiftもabstractとかないからクラスそんなに強くはないよね
Avatar
Avatar
Yuta Saito
Rc<RefCell<dyn T>> 書きたくなさすぎる
まあそういうことなんかな〜
9:33 AM
(てかその3連合成も全くわからん)
Avatar
RcじゃなくてArcじゃないのかな
Avatar
たしかにSwiftのHeapObjectと同等のものとしてはArcか
Avatar
あーこの投稿で
9:49 AM
SwiftがトレースGCに統合できない事に触れてるんや
Avatar
GC? In my Swift code? It&#39;s more likely than you think. This should let us experiment with the &quot;FFI Runtime&quot; approach to Swift+LibWeb/LibJS integration. Big thanks to @gryn...
9:59 AM
cxx側からSwift VWT触ってメモリ管理しようとしてるの・・・? (edited)
Avatar
Ladybirdの人は動画で、チームにいろんな言語で試しにブラウザ書かせてみたらSwiftが一番良かったと話してた。90年代に設計された技術スタックなので、クラスの継承を使えるのが良いとか。
Avatar
Avatar
ainame
Ladybirdの人は動画で、チームにいろんな言語で試しにブラウザ書かせてみたらSwiftが一番良かったと話してた。90年代に設計された技術スタックなので、クラスの継承を使えるのが良いとか。
なるほどーそこまでやったんですね
10:03 AM
個人的にSwiftはまさにそういうポテンシャルのある設計をしてると思うので、バイアスのない(?)立場からこうやって発見されるのは嬉しいな
10:06 AM
ドーグがこのパッチに詳しいコメントしてるのね
10:08 AM
GCについては
After moving from the pattern of RefCounted types + JS Wrappers to directly GC-allocating our DOM and Web APIs, we found that it was significantly easier to avoid leaks and cycles.
(edited)
Avatar
swift-distributed-tracingの中にあるコードなんですが
12:11 PM
これはコンパイルできて
12:11 PM
これはコンパイルできないのって何ででしょう?
12:12 PM
違いは TaskLocalwithValue スコープ関数で包むのをやめただけ
12:15 PM
withValue真似してもコンパイルできないし。
Avatar
どうやってstdlibはコンパイルされているんだ
Avatar
I have two questions: How should scope functions be implemented? Why does the standard library’s TaskLocal.withValue compile successfully? Let me explain step by step. Suppose we want to create a higher-order function that adds log output to a code block. A scope function is something that adds such effects to a block of code without modifyi...
1:15 AM
フォーラムに投稿した
Avatar
これRBIのバグと思ってたんですがどうなんでしょうね
Avatar
どうなんだろう? エラーメッセージは正しいことを言ってると思うんだよね 呼び出し側が actor だったとして、 isolation = #isolation なら スコープ関数自体は actor isolate されてて、 引数の operation 関数は non isolate だから、その返り値は越境している。 (edited)
2:22 AM
だから個人的には Task.withValue がコンパイルできていることの方がおかしいんじゃないかと思っている
Avatar
actorの中で作ったasyncクロージャって自動的にそのactorにisolateされませんでしたっけ?
2:38 AM
それはinheritActorContextのおかげか
Avatar
されるけど、それは呼び出し側の実装次第で、この withSpan から見たらそういうものが渡ってきたかどうかわからなくない?
Avatar
あーなるほど?ネストしてる場合か!
Avatar
全く関係ないグローバルなnonisolated funcが operation として直接渡されている可能性がある (edited)
Avatar
isolated(any)の出番なのかな
2:39 AM
.isolationが取り出せるやつ
Avatar
取り出せるだけなので、operationと同じcontextでTaskを走らせることはできるけど
Avatar
あんまりユーザが使うAPIには思えないけど
Avatar
それが isolation: と同じかどうかは保証されてないよ
2:40 AM
なので withSpan の本文と operation の返り値の間で越境があることは変わらない
Avatar
withSpanの中も同じisolationである必要あるんですっけ
2:42 AM
でもwithSpanは同じでやってるのか
Avatar
使い勝手としては同じisolationになってないと、スコープ関数をつけるとコンパイルエラーになる、みたいなことが起きてしまう withSpanは同じかのように動く
Avatar
フォーラムの会話を進めたら ClosureIsolation のドラフトを紹介された。 確かに @inheritsIsolation はうまくいきそう。 https://github.com/sophiapoirier/swift-evolution/blob/closure-isolation/proposals/nnnn-closure-isolation-control.md
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - sophiapoirier/swift-evolution
👀 1
3:02 PM
ちなみにその古い版である @_inheritActorContext はちょっとクセがある挙動をしているらしい
Avatar
結局 TaskLocal.withValue は strict concurrency ではない Swift 5 でコンパイルされてるからスコープ関数として使えるという事みたい
1:28 AM
swift-distributed-tracingはコンカレンシーセーフティーロンダリングをしているだけだった。
Avatar
なるほど味がある
t_desune 1
Avatar
omochimetaru 1/3/2025 3:46 PM
Hi Swit Evolution, A proposal to formalize an attribute that has existed since fairly early Swift in underscored form, that gives more control over generic performance. Explicit Specialization Proposal: SE-NNNN Authors: Ben Cohen Review Manager: TBD Implementation: Available in nightly toolchains using the underscored @_specialize Status: Aw...
3:46 PM
長らく裏技だった @_specialize をアンスコ外して正規仕様にする提案
3:52 PM
知らなかったんだけど、これ特殊化版を生成するだけじゃなくて、特殊化版へのファストパス分岐もジェネリック版に挿入されるらしい
Avatar
これってアンスコ時代もそういう挙動でしたよね?
3:53 PM
一般版の頭で順番にas?して、最適化パスがあればそれに切り替える実装になるやつ
Avatar
omochimetaru 1/3/2025 3:54 PM
そうみたい
3:55 PM
And inside the unspecialized generic code, the additional check-and-redispatch logic will be inserted at the start of the function.
3:56 PM
プロポーザル自体はアンスコ版には触れてないけども
3:56 PM
A proposal to formalize an attribute that has existed since fairly early Swift in underscored form
投稿の頭にこう書いてあるので
3:57 PM
多分仕様の話はそのままアンスコ版の解説でもある (edited)
Avatar
こんな細かい機能なんで覚えてるのかと思ったけど、前に自分で調べてた https://github.com/sidepelican/waiwaiswiftc/blob/master/%2319/waiwaiswiftc19.md#おまけ
iine 1
Avatar
omochimetaru 1/8/2025 11:54 PM
This is a second attempt (first one is at #77321), based on feedback I was given that introducing a second distinct AST dumper would make evolution of the compiler&#39;s AST internals more diff...
👍🏻 1
11:54 PM
型解いたASTをjsonで受け取れるらしい
Avatar
omochimetaru 1/13/2025 1:40 AM
The Swift Programming Language. Contribute to swiftlang/swift development by creating an account on GitHub.
1:43 AM
@SwiftifyImport というマクロが作られてる
1:46 AM
1:49 AM
Cの関数をインポートした後に、それをよりSwiftらしいシグネチャにするためのラッパー関数の本文を自動生成するマクロ
👀 1
1:50 AM
特にポインターをSpanにしたりとかする
1:52 AM
使い方わかりづらいけど面白い、真似できることがありそう
Avatar
import SwiftData @Model final class Item { var foo: Foo init(foo: Foo) { self.foo = foo } } struct Foo: Sendable, Codable { var value: Int? } これを item.foo.valuenilItemmodelContext.insert(newItem) してから modelContext.save() するとクラッシュするんですが、これはバグでしょうか?
Avatar
I've run into an issue where setting a property on a SwiftData object to a Codable struct with an optional String crashes the app. For example, if I have the following model object and struct : @Mo...
11:29 PM
concurrencyがいらないモジュールをビルドオプションでmain actor指定するモード
Avatar
omochimetaru 1/28/2025 1:21 AM
見かけに @MainActor が無いだけで意味的には付いてるから、安全性と使いやすさが両立してるのは良さそう (edited)
1:21 AM
ただこれ以降はコードだけ見てもconcurrencyの挙動が何もわからなくなってしまうな
1:21 AM
このコンパイラオプションによって全く意味が変わってくる場所が多すぎて。 (edited)
Avatar
Kishikawa Katsumi 1/28/2025 1:36 AM
見た目にわからんっていうのはもうちょいどうにかしてほしいけどシングルスレッドモードっていうのは悪くないな。
Avatar
omochimetaru 1/28/2025 1:47 AM
例えばファイルの先頭に @SingleThreadMode って書く、みたいな感じなら見た目にわかるだろうけど、ファイルごとじゃなくてモジュールレベルの設定にしたいみたいだから、それだとやっぱり見た目にわからんなあ
1:48 AM
1:48 AM
4 で Allevato さんが typealias で設定するのはどうかって書いてるな
1:48 AM
まあこれも別ファイルだと気づけないが
Avatar
norio_nomura 2/1/2025 2:37 PM
https://www.swift.org/blog/the-next-chapter-in-swift-build-technologies/ https://github.com/swiftlang/swift-build
Swift Build is a high-level build system based on [llbuild] with great support for building Swift. It is used by Xcode to build Xcode projects and Swift packages, and by Swift Playground. It can also be used as the Swift Package Manager build system in preview form when passing --build-system swiftbuild.
(edited)
Swift continues to grow in popularity as a cross-platform language supporting a wide variety of use cases, with support on a variety of embedded devices, form factors that encompass wearables to server, and a wide variety of operating systems. As Swift expands, there’s value in investing in matching cross-platform build tools that provide a powe...
A high-level build system based on llbuild, used by Xcode, Swift Playground, and the Swift Package Manager - swiftlang/swift-build
🙌🏻 1
Avatar
omochimetaru 2/1/2025 5:17 PM
おー、アツい
5:22 PM
Co-authored-by: Jake Petroules &lt;jake.petroules@apple.com&gt; Co-authored-by: Daniel Dunbar &lt;daniel_dunbar@apple.com&gt; Co-authored-by: Michael Rawdon &lt;rawdon@apple.com...
Avatar
Scipioでも将来的にはswift-package-managerへの依存からこれに置き換えていけるとよさそうだなぁ
Avatar
omochimetaru 2/2/2025 12:51 AM
PIF処理部分はこれに含まれてるんですかね?まだ見てない
12:52 AM
それともそこはxcodebuildの範疇で、これはその下請けなのかな?
Avatar
omochimetaru 2/2/2025 12:42 PM
doccにいろいろ書類あるから読んでる
Avatar
omochimetaru 2/2/2025 11:23 PM
https://forums.swift.org/t/evolving-swiftpm-builds-with-swift-build/77596 ここに示されてる方針はわかりやすい
11:24 PM
面白いのだと、swift-driverをCLIから使うんじゃなくてlibSwiftDriverを使う事で、ビルドグラフシステムにドライバー配下のミニタスクも統合したいらしい (edited)
11:25 PM
SwiftPMもGUIアプリとかサポートできるようにしていくらしい 本格的にxcodeprojが不要になったら嬉しいなあ
Avatar
omochimetaru 2/3/2025 12:12 AM
Project Model This is the Swift Build representation of a package graph in SwiftPM or workspace in Xcode, including all model objects and all data that they contain. This representation very closely matches the higher-level representations, although some transforms or derived information are present in some cases where it is considered beneficial. The term "PIF" (Project Interchange Format) is used both to describe the serialized representation used to transfer the model from clients to Swift Build, and as a shorthand for the Swift Build-side representation of the model.
SwiftBuild.docc/Architecture/build-system-architecture.md
(edited)
12:13 AM
PIFもswift-buildの範疇なんですね
12:13 AM
PIFが元からあったxcodeprojの下請けだと思っていたけど実は逆なのかなあ? (edited)
12:14 AM
Apple内部でのswift-buildプロジェクトの成果としてPIFがxcodeprojを置き換える形で後から生えた?
Avatar
へー
1:14 AM
xcodeが単なるコードエディタになって、buildまわりは全部ossでswift-*のリリースと歩調があえば、xcodeの遅いリリースサイクルを待たなくて良くなるのは良いなあ
Avatar
omochimetaru 2/3/2025 1:14 AM
project interchange という名前も swiftpm を xcodeproj に持っていく部分の事な気がする (edited)
Avatar
class NonSendable {} func makeNonSendable() async -> NonSendable { NonSendable() } struct Demo: View { nonisolated func foo() async { _ = await makeNonSendable() } var body: some View { Text("Hello, World!") .task { _ = await makeNonSendable() // NG await foo() // OK } } } ↑これ、直接 makeNonSendable 呼び出すのと、foo 経由で呼び出すのって、ぶっちゃけ中身同じはずですが、なぜ直接 makeNonSendable を呼び出すとcross actor boundaryエラーになるのかすごい理解できないですよね… (edited)
Avatar
omochimetaru 2/5/2025 10:27 PM
fooはnonisolatedだから呼べて、 .taskはMainActorだから呼べない?
Avatar
makeNoSendableとfooではシグネチャが異なるので、(Sendable準拠していない)戻り値があるmakeNonSendableを呼び出す際にはコンパイルエラーが発生するでしょうか?
Avatar
はい、コンパイルエラーが発生します。シグネチャが異なるのは理解できますが、ただやってることが同じなのに、片方だけコンパイルエラーが発生するのが納得いかないですよね…
👀 1
Avatar
最終的にやってることは同じですが、nonisolatedと返り値を捨ててることで意味的には結構違いがありませんか?
Avatar
戻り値を捨てなくても、同じように一回 foo 経由ならやりたいことはできるのに、そうしないとできないのはなんか納得できないですよね… class NonSendable { var bool: Bool = .random() } func makeNonSendable() async -> NonSendable { NonSendable() } struct Demo: View { @State private var bool: Bool? nonisolated func foo() async { let ns = await makeNonSendable() Task { @MainActor in bool = ns.bool } } var body: some View { Text("Hello, World!") .task { // NG let ns = await makeNonSendable() bool = ns.bool } .task { // OK await foo() } } } ↑のコード、結局 foo の中でも ns がアクター隔離超えて .bool 渡してるじゃん…? (edited)
t_naruhodo 1
Avatar
omochimetaru 2/6/2025 2:34 AM
あれ、それはできるのか
2:36 AM
呼び出しはできないけど、呼び出した結果のNSは移せるのはRBIが効くからか でもそれなら呼び出しもできて良さそうに思えるな
Avatar
func makeNonSendable() async -> sending NonSendable { NonSendable() } sending使えば同じになる気がします
Avatar
はい、sending 使えば普通に呼び出せますが、問題はそれ実装側が気をつけないと呼び出し側が結構大変で上のような実装をしないといけないから、ライブラリー開発する側としてはなんとかしてほしいって思いますよね…
t_naruhodo 1
Avatar
現状の設計の延長線上で実現するとしたら sendingにできるパターンでは自動でsendingになる、みたいなイメージですかね、何か不都合あるかな...?
Avatar
omochimetaru 2/6/2025 3:48 AM
論点はそこではないような?
t_naruhodo 1
Avatar
まあ論点はそこではなく、同じことやってるはずなのになぜ foo がよくて直接呼び出すのはダメかってことですね
Avatar
omochimetaru 2/6/2025 3:49 AM
nonisolatedで呼び出してからその結果をmainに渡せるのであれば
3:49 AM
最初からmainで呼び出せていいはず
Avatar
そうそれ
Avatar
なるほど、そもそも関数の分け方の問題か
Avatar
omochimetaru 2/6/2025 3:50 AM
渡せる理屈は、nonisolatedならそのタスクにしか値が関連を持たないから非同期アクセスしなきしグローバル変数もないから後からの影響もないからで
3:51 AM
それならそもそも呼び出せるはずだ・・・
Avatar
kntkさんの言ってることの続きで言ったら、個人的にはデフォルトがsendingで、共有してるオブジェクトを返してる時明示的に sharing とかのキーワードつけないと返せないみたいな宣言の仕方がいいじゃないかなと思っています、nonescaping から @escaping に変わったのと同じように
t_naruhodo 1
Avatar
Avatar
lovee
kntkさんの言ってることの続きで言ったら、個人的にはデフォルトがsendingで、共有してるオブジェクトを返してる時明示的に sharing とかのキーワードつけないと返せないみたいな宣言の仕方がいいじゃないかなと思っています、nonescaping から @escaping に変わったのと同じように
omochimetaru 2/6/2025 3:51 AM
いや、そこはSwiftのオーナーシップの考え方がずっとあって
3:52 AM
initの引数はsendingだけど、メソッドの返り値はgetで、中のプロパティへのアクセサになる、というのがデフォルト戦略なんです
t_naruhodo 1
3:53 AM
参照カウントを増やすかどうかと関係してて、Cocoaのころから引き継がれてます
3:53 AM
新しい値を作って返す方がマイナーケースですね
Avatar
オブジェクトなら確かに新しい値作って返すのがマイナーかもしれないですが、structでもNonSendableのを新しく作って返すのって割とよくあるじゃん…? あーでもそれだとsharingしてるかどうかわからないか
Avatar
omochimetaru 2/6/2025 3:55 AM
なのでsendingにしちゃうといろんな前提と矛盾して多分困ります
t_naruhodo 1
3:55 AM
structはそもそもSendableにするのがいいですねえ
3:56 AM
まあ、いまはグローバル関数だから、「中身のメンバーを返す」ケースがないけど。
Avatar
まあそれはよしとして、結局なぜ同じくアクター隔離領域超えてるはずなのに、foo の中にやるのはよくて直接呼び出しするのはダメなのかがやはりわからない 🤔
Avatar
omochimetaru 2/6/2025 3:59 AM
RBIに搭載されてる考え方が
3:59 AM
一般のルールの方とズレてるんだと思います
👀 1
4:00 AM
つまり単に仕様設計上の考慮漏れだと思います 指摘した方がいいのかも もうあるかもだけど
Avatar
ちなみにこれって foo で呼び出せるのがおかしいです?直接呼び出せないのがおかしいです? (edited)
Avatar
omochimetaru 2/6/2025 4:13 AM
fooから呼び出せるのは問題ないと思います makeNonSendbleの中身をどうにかして、マルチスレッドバグが引き起こせるかどうかで考えればいいですが、起こり得ない気がしています
❤️ 1
Avatar
あとで時間あったらSwift Forumsに起票しておきます 🙌
🙌 1
Avatar
Consider this code: class NonSendable { var bool: Bool = .random() } func makeNonSendable() async -> NonSendable { NonSendable() } struct Demo: View { @State private var bool: Bool? nonisolated func foo() async { let ns = await makeNonSendable() Task { @MainActor in bool = ns.bool } } ...
Avatar
omochimetaru 2/6/2025 7:39 AM
僕の意見も書いておきました。
t_kansha 1
Avatar
omochimetaru 2/7/2025 4:19 AM
@lovee Jamieさんが興味深い返信をくれてますね
4:19 AM
リンク先のパッチを見てみるとこう書いてある
In terms of the test suite the only difference is that we allow for non-Sendable types to be returned from nonisolated functions. This is safe due to the rules of rbi. We do still error when we return non-Sendable functions across isolation boundaries though.
(edited)
👀 1
4:20 AM
「non Sendableな値をnonisolated functionから返すことを許す」「RBIのルールによって安全」
4:20 AM
新しいSwiftなら検査が緩和されて呼び出せるようになりそう。 (edited)
happy 3
Avatar
ところで↑のPR、誰からもレビューされることなく実装者が一人の独断でマージしてしまうのは、なんかちょっとアレな気がするんですよね…
Avatar
omochimetaru 2/7/2025 2:44 PM
ほんとだ、誰もリアクションしてない
2:46 PM
マージ後にswift evolutionが立つ事もあるけど・・・これはどうだろうなあ 一応緩和されるだけだからソース互換性は保たれますね
yoshi 1
Avatar
https://github.com/swift-server/async-http-client/blob/89dc8d0068eb4d3dea050eac6a0c913098c60d97/Sources/AsyncHTTPClient/StructuredConcurrencyHelpers.swift#L18-L47 このasyncDoの実装、キャンセルが起きた時にfinallyが巻き添えを食らわないように工夫されてて面白い
Avatar
omochimetaru 2/11/2025 6:20 AM
Task { }.value で包むとタスクが別になるから Task.isCancelled な状態と区別できるのか。
Avatar
switch foo { case .bar where let hoge: hoge.fuga ... } みたいにswitchの中でunwrapできると嬉しいなーとずっと思ってるんだけど自分だけなんだろうか 🤔
Avatar
switch (foo, hoge) { case (.bar, let hoge?): hoge.fuga ... }
6:48 AM
こうですかね?
Avatar
あーなるほど、2つでswitchに入れるんですね 今度ためしてみます 🙏
Avatar
元々欲しかったのこういうのだった... 😢 switch foo { case let .bar(baz) where let qux = baz.qux: qux ... }
Avatar
omochimetaru 2/20/2025 4:19 PM
Hi folks, The review of SE-0461: Run nonisolated async functions on the caller's actor by default begins now and runs through March 2, 2025. This proposal is one that's been contemplated in the recently approved vision document to improve the approachability of Swift's data-race safety facilities. Reviews are an important part of the Swift ev...
4:20 PM
nonisolatedの実行コンテキスト変えるやーつ 審査入り!
👀 2
👍🏻 3
Avatar
だいぶ使いやすくなりそうだな
11:20 PM
feature flagでうまく移行もできそう
👍 2
11:11 PM
次世代Codableの計画
11:14 PM
フォーマット特有の実装をマクロで生成してexistentialの利用を回避 辞書のデコードでパーサ手動にしてkeyの順番を固定して中間オブジェクトを回避
11:15 PM
RustのSerdeと同等の速さを目指すらしい
Avatar
今だとコンパイラによるコード生成を全部マクロに置き換えられたりするのかな
Avatar
その方針みたいですね 僕も最近そういうのをやりました ただproperty wrapperが絡む特殊なパターンで無理な事がちょっとあったような
Avatar
マクロ側を改善して全てのプロパティラッパーを置き換えることができるようにしようっていう GSoC プロジェクトアイデアがありましたよね. https://www.swift.org/gsoc2025/#potential-projects
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
おお、これそこまで踏み込むんですね、見逃してた
11:33 PM
Macros and init accessors in their current state might not be sufficient to cover all of the property wrapper use scenarios, so the project is most likely going to require improving and expanding the aforementioned features as well.
Avatar
「全部マクロで実装してみたものがあるよ」的なものがあげられてるかざっとみたけど、なかった (edited)
11:52 PM
swift-testingみたいに「Codableを使ってはダメ」的な縛りがあるところからしか、次世代Codableは実装されない気がする
Avatar
プロパティラッパーが引数をアトリビュー側で持つやつと、initで変な型を受け取るやつ、initが空のやつを、ラッパーの定義読まないと無理そう
Avatar
Avatar
norio_nomura
swift-testingみたいに「Codableを使ってはダメ」的な縛りがあるところからしか、次世代Codableは実装されない気がする
それめっちゃありそうですね 歪で一部退化するから好きじゃない・・・
Avatar
サーバだとcodableの遅さは顕著なので出たら置き換えたい
Avatar
それな
Avatar
マクロ使ったオレオレ実装をみんな色々作ってみればいいんじゃね?とかパッと思うけど、5つのYAMLライブラリ依存があるgolangのプロジェクトとか見ると「そんな未来は嫌だ」ってなるよね。 [https://github.com/lima-vm/lima/issues/2597]
Avatar
www
12:17 AM
マクロを使った自作の問題点は、僕がやったのもまさにそうなんですが、 挙動をコントロールするためのアトリビュートとかがそのマクロ専用になるので、
12:18 AM
型のコードとしてそれが焼かれちゃうので他の実装に切り替えたりするのが難しいですね
12:18 AM
↑のYAMLの話もそうなのかはわからんけど (edited)
Avatar
Limaは依存してるパッケージがそれぞれ別のYAMLライブラリに依存してる。直接使ってるのは2つだったかな?結果5つ (edited)
12:23 AM
goalngは実装を切り替えるのは楽だったはず。言語サポート的には、プロパティに対応するシリアライザ毎のキーの定義だけな気がする。 (edited)
12:25 AM
キーの定義もシリアライザ専用ではなく汎用だったかも。 (edited)
Avatar
goはプロパティに文字列メタデータを付与することができて、各種ライブラリはその文字列全体をパースしつつ自分用の設定だけ読み取る、って感じだったと思います
t_arigatou 1
Avatar
オレオレ実装が生まれても切り替えが容易になってる。Apple主導では採用されなさそうな発想かな
Avatar
なるほど〜
Avatar
複数のen/decoders対応について書いてる人いるな。 [https://forums.swift.org/t/the-future-of-serialization-deserialization-apis/78585/18]
12:44 AM
golangの文字列メタデータ的な、複数のen/decodersで共通で使えるものを作るってのは、良い考えな気がする。
12:46 AM
Codableがデファクトなのは変わらないと思うから、Codable以外を取っ替え引っ替えできる仕組みを整えて、みんなで一斉にオレオレ実装。
Avatar
swift-foundationのSubprocess、難産だったけど固まったようだ https://forums.swift.org/t/accepted-as-version-0-1-sf-0007-subprocess/78787
Avatar
パッケージ分けるらしい
Avatar
runグローバル関数になったんだ
Avatar
Subprocessはswift-systemに依存する
12:12 AM
Foundationへの拡張はpackage traitを使うらしい
Avatar
Avatar
Yuta Saito
runグローバル関数になったんだ
ね、思い切ったね
12:13 AM
When this trait is on, Subprocess includes a dependency on Foundation and adds extensions on Foundation types like Data.
Avatar
ややこしくなってきた
Avatar
オーバーロードのバリエーションが色々あって難しいな
Avatar
トップレベル関数になったのはスクリプティング用途での儀式を減らしたいとのこと https://forums.swift.org/t/review-3rd-sf-0007-subprocess/78078/58
I prefer the top level run function. I think it is important to look for opportunities to reduce the amount of ceremony required to do simple things. It improves the approachability of the language as a whole. There is always an option to add the module name to the function to disambiguate where needed. The compiler produces a reasonable fix-i...
Avatar
Avatar
Yuta Saito
トップレベル関数になったのはスクリプティング用途での儀式を減らしたいとのこと https://forums.swift.org/t/review-3rd-sf-0007-subprocess/78078/58
これはわかる、一番ニーズがあるのがそのケースだと思うし、ええんちゃうか
12:19 AM
でもfoundationの外に作るなら、どうやってスクリプトから使うんだ?
Avatar
最終的にはOSとツールチェインに含まれることになるとしてもプレビュー期間中にスクリプティングユースケースを試せなさそう
Avatar
だよなあ サードパーティのやつ使うぐらいか
12:23 AM
あ、runの分類の解説が続きに書いてあった (edited)
12:29 AM
await終わったら出力が全部キャプチャされてるグループと
12:29 AM
bodyクロージャを与えて、入力をストリームで渡しつつ、実行中のプロセスが得られるグループがあるんだな
Avatar
バイナリデータは [UInt8] が基本で、 これからはそれに追加で borrowing RawSpan が出てくるのか
12:39 AM
Foundationがあるときは Data もある
12:41 AM
var platformOptions = PlatformOptions() // Bind child fd 4 to a parent fd platformOptions.preSpawnProcessConfigurator = { _, fileAttr in let parentFd: FileDescriptor = … posix_spawn_file_actions_adddup2(&fileAttr, parentFd.rawValue, 4) }
12:42 AM
トリッキーなやつもできるらしい
12:46 AM
// Override the executable path let result2 = try await run( .path("/some/executable"), arguments: .init( executablePathOverride: "/new/executable/path", remainingValues: ["arg1", "arg2"] ) )
12:47 AM
バイナリのファイル名と argv[0] を変えたいケースもあるんやな
12:47 AM
それこそ swiftcswift-frontend みたいなやつかな
12:49 AM
swift-concurrencyのcancel来たらrunをgraceful shutdownするのすげー
12:51 AM
Foundation.URL じゃなくて SystemPackage.FilePath になるのも結構大きな決定だな
12:51 AM
ファイルパスに URL 使ってきたけど追従しようかな
Avatar
ファイルパス、どちらかというとURLがいいのかなと思いつつFileManagerがStringしか対応してないAPIを持ってたり悩ましかったところに更に新しいのが増えるんですね
Avatar
omochimetaru 3/26/2025 1:03 AM
FileManagerがStringしか対応してない
これめっちゃ中途半端ですよね 自分でextensionしてURLで使ってます
t_wakaru 1
Avatar
ジュニア 3/27/2025 3:15 PM
withTaskGroup使うべきなのはさておき) ↓のコードのTask { await counter.increment() }のところってコンパイル通って問題ないのでしょうか? https://discord.com/channels/291054398077927425/430242233468452865/1354831534745714689 MainActorに隔離されたSendableでないcounterがnon-isolatedなasyncメソッドにsendされていてエラーになると思ったんですが… データ競合も起きてそうに見えます。
Avatar
omochimetaru 3/27/2025 3:22 PM
全然だめにおもえる。
😢 1
Avatar
ジュニア 3/27/2025 3:25 PM
関連Issue探してなければ立ててきます🫥
👍 2
Avatar
Avatar
ジュニア
withTaskGroup使うべきなのはさておき) ↓のコードのTask { await counter.increment() }のところってコンパイル通って問題ないのでしょうか? https://discord.com/channels/291054398077927425/430242233468452865/1354831534745714689 MainActorに隔離されたSendableでないcounterがnon-isolatedなasyncメソッドにsendされていてエラーになると思ったんですが… データ競合も起きてそうに見えます。
似た問題を遠い昔にissue建てたんですがまだ治っていない 😵💫 https://github.com/swiftlang/swift/issues/76541
Description Non-Sendable value can be accessed from Global-Actor-isolated Task And normal Task concurrently. Reproduction the following code can be complied with no error/warning on swift 6 mode fi...
🥲 1
Avatar
Avatar
kntk
似た問題を遠い昔にissue建てたんですがまだ治っていない 😵💫 https://github.com/swiftlang/swift/issues/76541
ジュニア 3/27/2025 5:50 PM
ありがとうございます!見たところ同じ問題みたいなので静観します…
❤️ 1
Avatar
Avatar
ジュニア
ありがとうございます!見たところ同じ問題みたいなので静観します…
とはいえこのIssueが半年以上放置されて埋もれている上 ジュニアさんのは(原因は同じRBIの考慮漏れかもですが)asyncメソッド呼び出しでselfがbondaryを跨ぐというユースケースは違うので新しく立てても良いかもと思いました!お任せします 🙇‍♂️ (edited)
❤️ 1
👍 1
Avatar
omochimetaru 4/3/2025 1:20 AM
GSoCのマクロによるproperty wrapperの件、学生さんが実装計画出してたので、かねてよりの疑問点をぶつけておいた https://forums.swift.org/t/gsoc-2025-re-implement-property-wrappers-with-macros/78573/19 (edited)
❤️ 4
Avatar
property wrapperって関数の引数にも使えるけど、今はそこにマクロは使えないからどうなるんだらうな
4:05 AM
専用マクロが増えるかな
Avatar
omochimetaru 4/5/2025 5:50 AM
そこはパラメータアトリビュートマクロみたいな感じで増やさないと無理そうね 関数ボディマクロみたいに本文に介入しないといけないし
Avatar
omochimetaru 4/5/2025 11:58 AM
なんか他の候補者のZiadさんから、アリハント君とのやりとり見た、ワイのプロポーザルも見てくれ、とDMが来たw
👏🏻 2
1:34 PM
GSoCオリジナルテーマで、Androidでも使えるようにswiftjavaのJNIモードを作るニキ
Avatar
いいなこれ
3:22 PM
ていうかswiftjavaのJavaKitって元々JNIを対象としてたものだったと思うけど、違ったのかな
Avatar
omochimetaru 4/6/2025 3:59 PM
jextract-swift – the source generator that ingests .swiftinterface files and makes them available to be called from generated Java sources Swift 6.x development snapshots, because of dependence on rich swift interface files JDK 22+ because of dependence on JEP-454: Foreign Function & Memory API We are validating the implementation using the currently supported non-LTE release, which at present means JDK-23.
3:59 PM
次世代のJNIみたいなやつを使うらしいよ
t_naruhodo 1
2:44 PM
ファイルごとのデフォルトアイソレーションの設定に private typealias DefaultIsolation = MainActor を使う案 ホーリーは一度反対したけど考え直したらしい
2:46 PM
逆に非隔離にする場合は private typealias DefaultIsolation = nonisolated と書くらしい これは右辺はいつものキーワードに見えるが、小文字で始まる型として新たに定義する
2:49 PM
以前の提案は #swiftSettings( .defaultIsolation(MainActor.self) ) だった (edited)
2:51 PM
ついでに引用されてたんだけど、こうやってデフォルトのリテラル型を変えられるらしい。 private typealias IntegerLiteralType = Int16 let x = 1 print(type(of: x)) // Int16
t_majika 5
Avatar
Kishikawa Katsumi 4/8/2025 2:58 PM
typealiasでいいんかな。pragmaとかのほうがいいのでは。
Avatar
omochimetaru 4/8/2025 3:00 PM
#swiftSettingの方ではpragmaみたいな新しい文法を入れたくない、という感じでしたね
3:01 PM
SwiftSettingはトップレベルの関数呼び出し風だから良いらしい 引数にラベルがあったり値をドット式で書けたり
3:03 PM
で、他のstrict concurrencyとかは、警告レベルの変更にすぎないけど、これは関数や型定義の解釈が変わるから、レベルが違って、型定義みたいなもんなんだと
Avatar
Kishikawa Katsumi 4/8/2025 3:07 PM
既存の文法を流用するのだいぶわかりにくいと思うけどな。typealiasがassociatedtypeになったのもそういうことじゃないのかな。
Avatar
omochimetaru 4/8/2025 3:10 PM
そうですねえ、みかけだけ同じでも意味が同じわけじゃないんですよねえ
3:11 PM
コンパイラがファイルレベルの型を受け取る、という挙動とはマッチしてるけど、そもそも特別な型名だけコンパイラに特別に読み取られる、というのがマジックすぎて謎ではある
Avatar
Kishikawa Katsumi 4/8/2025 3:18 PM
既存の文法を流用するのは互換性の問題もあると思うけどいいんやろか。 すでにprivate typealias DefaultIsolation = MainActorってファイルに書いてる人がおるかもしれん。
Avatar
omochimetaru 4/8/2025 3:20 PM
ですね。 ソース互換性の章には This seems extremely unlikely. って書いてあるけどw
Avatar
Kishikawa Katsumi 4/8/2025 3:21 PM
そうだけどそういうところはextremely unlikelyで済ましていいものかね。
3:21 PM
と思うんだよね。
Avatar
omochimetaru 4/8/2025 3:22 PM
なんか普通に #defaultisolation = MainActor とかでいい気がするなあ
❤️ 1
Avatar
Kishikawa Katsumi 4/8/2025 3:30 PM
それいいと思うな。
Avatar
NSURL, CFURL と swift-foundation の URL の挙動が違うのを修正しようとしているらしいですね. https://github.com/swiftlang/swift-foundation/pull/1238
Changes to allow NSURL and CFURL to use the Swift URL implementation. With this refactoring, the behavior of URL should be identical, except for a few minor compatibility/bug fixes to the parser an...
👀 3
Avatar
Swift gives developers a way to limit the use of declarations in certain contexts using the @available attribute. For example, a library developer can specify that a new API is only available at runtime on macOS 15 or newer using @available: @available(macOS, introduced: 15) public struct Foo { /* ... */ } The compiler only accepts references ...
12:09 AM
availableで使える判定値を@availabilityDomainで定義できる boolかバージョンタプルが使える
12:10 AM
もちろんコンパイル時定数でなけらばならないらしい
Avatar
ユーザにこの機能が解放されるの面白いけど、あんまり使い所が思いつかないな
Avatar
abiコンパチなバイナリを配布する状況が例として挙げられてるけど、やらないもんね
Avatar
今後AWSとかがLambdaとかでSwiftランタイムを提供して、NIOやcollectionsがプリインストールされてる、みたいな状況?
12:36 AM
Lambdaのランタイムはこちらで管理できるからこの状況でもこれは使う必要ないな‥
12:37 AM
ランタイムがユーザ管理されていてかつSwiftアプリケーションが頻繁に使われて共通パッケージ群がある状況、Apple製品以外に何があるんだ
Avatar
norio_nomura 4/17/2025 1:41 AM
swift-foundationビルド時に、swift-frontendに渡される大量の
-enable-experimental-feature 'AvailabilityMacro=FoundationPredicateRegex 6.1:macOS 15, iOS 18, tvOS 18, watchOS 11'
みたいなオプションを見ると、別途定義できた方が良さそうと思う。
Avatar
これを使って available(WASI, unavailable) とか available(Windows, unavailable) みたいなのが書けるようになるならめっちゃ欲しいです. こういう時↓ https://forums.swift.org/t/pitch-a-vision-for-webassembly-support-in-swift/79060/12
Avatar
omochimetaru 4/17/2025 5:38 AM
今ピンポイントの無効化って書けないから _unavailableInEmbedded があるんですよね。
Avatar
確かにそういうケースは便利そうですね
Avatar
omochimetaru 4/22/2025 8:23 AM
Contribute to apple/swift-play-experimental development by creating an account on GitHub.
8:24 AM
$ cat Sources/Fibonacci/Fibonacci.swift func fibonacci(_ n: Int) -> Int { ... } import Playgrounds #Playground("Fibonacci") { for n in 0..<10 { print("fibonacci(\(n)) = \(fibonacci(n))") } } こういうのを書いておくと
8:24 AM
$ swift play --list Building for debugging... Found 1 Playground * Fibonacci/Fibonacci.swift:23 "Fibonacci" $ swift play Fibonacci Building for debugging... ---- Running Playground "Fibonacci" - Hit ^C to quit ---- Fibonacci(7) = 21 ^C
8:25 AM
こういう感じで、シンボルがある状況でreplできるらしい
👀 3
8:25 AM
swiftpm側にも手が入ってるそうな
8:25 AM
ライブラリを簡単に試せるようにするものかな?
Avatar
PythonとかRubyでよくやる if name == "main" みたいなやつとして使えるのかな
9:37 AM
README見るとファイル名とサンプルコードの内容を一致させるのがメリットっぽいように見える
Avatar
omochimetaru 4/22/2025 9:37 AM
$ swift play --list Building for debugging... Found 1 Playground
  • Fibonacci/Fibonacci.swift:23 "Fibonacci"
9:38 AM
1ファイルの中に複数定義できそう?
Avatar
実行のためのexecutableターゲットを作らなくて良いのがメリットか
Avatar
omochimetaru 4/22/2025 9:38 AM
あー、ターゲットは要らないのかこれ
Avatar
タスクランチャーみたいなもの?
9:40 AM
argument parserより手軽なアプローチという感じ?
Avatar
XcodeのSwift Macrosのテンプレートにある動作確認のためだけのClient targetみたいなの生えるけどこれがいらなくなるかも? (edited)
Avatar
と思ったけど引数とかさすがに欲しいような
Avatar
Rustのインラインテストてきな?
Avatar
Avatar
Iceman
と思ったけど引数とかさすがに欲しいような
omochimetaru 4/22/2025 9:43 AM
ワンショットじゃなくてインタラクティブなreplに入るんじゃないかなあ
9:43 AM
Hit ^C to quit って出てるし
9:43 AM
見た目はnpm runに似てるけどplayはplaygroundの略なんじゃないか
Avatar
インタラクティブなんですかねこれ?
Avatar
omochimetaru 4/22/2025 9:45 AM
最後に^Cって書いてあるからそうかなって
Avatar
入力を受ける機構がないなぁって
Avatar
omochimetaru 4/22/2025 9:46 AM
swift replとかと同じでその場で打ち込むんじゃ? xcodeならplaygroundっぽくしてくれそう
9:46 AM
swiftpm側のリポジトリ検索してもなんも出てこないな
Avatar
norio_nomura 4/22/2025 9:51 AM
The Package Manager for the Swift Programming Language - Comparing swiftlang:main...chrismiles:eng/chrismiles/swift-play-prototype · swiftlang/swift-package-manager
Avatar
omochimetaru 4/22/2025 9:51 AM
おっ
9:52 AM
フォーク先にあったのか
Avatar
完全に用途が被っているわけではないのは理解しているんですが Swift Snippets との棲み分けどうするんだろうと思ってしまいました (edited)
1:53 PM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution
2:08 PM
アナウンスここにあった
2:09 PM
Note that running doesn't immediately stop at the end of the playground body, requiring ^C to end execution. This is for two really useful reasons: Any asynchronous code or callbacks will continue to execute and produce output; swift play monitors for any changes to files in the package and will automatically re-build/re-run if a file is modified. This makes for a super convenient iterative development tool.
t_naruhodo 1
2:10 PM
replとは違うけど、ターミナルが捕まって、コマンド打つまで開いていて、ソース側がウォッチされていてボットリロードされるみたい
2:12 PM
パッケージ開発をしやすくするものっぽいな
2:13 PM
ユニットテストと違うのは保存したらすぐ実行される事と、プライベートなシンボルが見える事かな
6:19 PM
static libraryをswiftpmでサポート artifact bundleが従来xcframeworkとexecutableをサポートしていたが、これに追加されるらしい
👀 1
6:21 PM
ちゃんとそのstatic libから依存するシンボルが解決できるかどうか調べるツールも提供する そのためにswiftツールチェーンにobjdumpを同梱する
Avatar
Avatar
kebo
https://github.com/apple/swift/pull/65993 みたいに Evolution にないフラグも入って来る感じなら結局一覧は https://github.com/apple/swift/blob/main/include/swift/Basic/Features.def を見ないとわからなくなっていくんじゃないかなと思うんですがどうなんでしょうね.
feature フラグの一覧が無い問題ですが,swift -print-supported-features で feature フラグの完全な一覧が表示できるようになってました.Swift 6.2 にも cherry-pick されそうです. https://github.com/swiftlang/swift/pull/80833
Replace -emit-supported-features with -emit-supported-arguments mode because &amp;quot;features&amp;quot; part was never implemented. Introduce -print-supported-features option that prints supporte...
👀 2
Avatar
norio_nomura 6/4/2025 11:44 PM
@swift-main -print-supported-features
Avatar
Avatar
norio_nomura
@swift-main -print-supported-features
swiftNightly BOT 6/4/2025 11:44 PM
{ "features": { "optional": [
3.23 KB
Exported 13,928 message(s)
Timezone: UTC+0